Hukatiza na kufanya kazi nyingi katika Arduino. Jinsi ya kufanya kazi sambamba (Nyezi) katika programu ya Arduino

Kwa ujumla, Arduino haitumii usawazishaji wa kweli wa kazi, au usomaji mwingi. Lakini inawezekana kwa kila marudio ya mzunguko kitanzi () amuru kidhibiti kidogo kuangalia ikiwa ni wakati wa kufanya nyongeza, kazi ya usuli. Katika kesi hii, itaonekana kwa mtumiaji kuwa kazi kadhaa zinafanywa wakati huo huo.

Kwa mfano, hebu tuwashe LED kwa mzunguko fulani na, wakati huo huo, tufanye sauti zinazoongezeka na zinazopungua kama siren kutoka kwa emitter ya piezo. Tayari tumeunganisha LED na emitter ya piezo kwa Arduino zaidi ya mara moja. Wacha tukusanye mzunguko kama inavyoonyeshwa kwenye takwimu.

Ukiunganisha LED kwenye pini ya dijiti isipokuwa "13", usisahau kuhusu kizuia kikomo cha sasa cha takriban ohms 220.

2 Udhibiti wa emitter ya LED na piezo kwa kutumia delay() operator

Wacha tuandike mchoro kama huu na tuupakie kwa Arduino.

Const int soundPin = 3; /* tangaza kigezo na nambari ya pini, ambayo kipengele cha piezoelectric kinaunganishwa */ const int ledPin = 13; // tangaza kigezo kwa nambari ya pini ya LED usanidi utupu () ( pinMode(soundPin, OUTPUT); // tangaza pini 3 kama pato. pinMode(ledPin, OUTPUT); // tangaza pini 13 kama pato. } kitanzi utupu() (// Udhibiti wa sauti: tone (soundPin, 700); // fanya sauti kwa mzunguko wa kuchelewa kwa 700 Hz (200); tone(soundPin, 500); // kwa mzunguko wa kuchelewa kwa 500 Hz (200); tone(soundPin, 300); // kwa mzunguko wa kuchelewa kwa 300 Hz (200); tone(soundPin, 200); // kwa mzunguko wa kuchelewa kwa 200 Hz (200); // Udhibiti wa LED: digitalWrite (ledPin, HIGH); // kuchelewa kwa mwanga (200); digitalWrite(ledPin, LOW); // kuzima kuchelewa (200); }

Baada ya kuiwasha, ni wazi kwamba mchoro haufanyiki kama tunavyohitaji: hadi siren ifanye kazi kikamilifu, LED haitaangaza, lakini tungependa LED itupe. wakati sauti ya king'ora. Tatizo ni nini hapa?

Ukweli ni kwamba tatizo hili haliwezi kutatuliwa kwa njia ya kawaida. Kazi zinafanywa na microcontroller madhubuti mfululizo. Opereta kuchelewesha () huchelewesha utekelezaji wa programu kwa muda maalum, na hadi wakati huu utakapomalizika, amri zifuatazo za programu hazitatekelezwa. Kwa sababu hii, hatuwezi kuweka muda tofauti wa utekelezaji kwa kila kazi kwenye kitanzi kitanzi () programu. Kwa hiyo, unahitaji kwa namna fulani kuiga multitasking.

3 Michakato sambamba bila mwendeshaji wa "kuchelewesha ()".

Chaguo ambalo Arduino itafanya kazi sambamba-pseudo lilipendekezwa na watengenezaji wa Arduino. Kiini cha njia ni kwamba kwa kila marudio ya mzunguko kitanzi () tunaangalia ikiwa ni wakati wa kupepesa LED (fanya kazi ya chinichini) au la. Na ikiwa imefika, basi tunageuza hali ya LED. Hii ni aina ya chaguo la bypass kwa operator kuchelewesha ().

Const int soundPin = 3; // kutofautiana na nambari ya siri ya kipengele cha piezoelectric const int ledPin = 13; // kutofautiana na nambari ya pini ya LED const ledInterval ndefu = 200; // Muda wa kupepesa kwa LED, ms. int ledState = CHINI; // hali ya awali ya LED ambayo haijasajiliwa kwa muda mrefuMillis = 0; // kuhifadhi wakati wa uanzishaji wa awali wa LED usanidi utupu () ( pinMode(soundPin, OUTPUT); // weka pini 3 kama pato. pinMode(ledPin, OUTPUT); // weka pini 13 kama pato. } kitanzi utupu() (// Udhibiti wa sauti: tone (soundPin, 700); kuchelewa (200); tone(soundPin, 500); kuchelewa (200); tone(soundPin, 300); kuchelewa (200); tone(soundPin, 200); kuchelewa (200); // Flashing LED: // muda tangu Arduino iwashwe, ms: unsigned long currentMillis = millis(); // Ikiwa wakati wa kufumba macho umefika, ikiwa (currentMillis - previousMillis >= ledInterval) ( previousMillis = currentMillis; // basi kumbuka wakati wa sasa ikiwa (ledState == CHINI) ( // na kugeuza hali ya LED ledState = JUU; ) vinginevyo ( ledState = LOW; ) digitalWrite(ledPin, ledState); // kubadili hali ya LED) }

Hasara kubwa njia hii ni kwamba sehemu ya msimbo kabla ya kizuizi cha udhibiti wa LED lazima itekelezwe kwa kasi zaidi kuliko muda wa kupepesa wa LED "ledInterval". Vinginevyo, blinking itatokea mara chache zaidi kuliko lazima, na hatutapata athari za utekelezaji sambamba wa kazi. Hasa, katika mchoro wetu, muda wa mabadiliko ya sauti ya siren ni 200+200+200+200 = 800 ms, na tunaweka muda wa kuangaza kwa LED hadi 200 ms. Lakini LED itaangaza kwa muda wa 800 ms, ambayo ni mara 4 zaidi kuliko tuliyoweka.

Kwa ujumla, ikiwa msimbo hutumia operator kuchelewesha (), katika kesi hii ni vigumu kuiga pseudo-parallelism, hivyo ni vyema kuepuka.

KATIKA kwa kesi hii Itakuwa muhimu kwa kitengo cha kudhibiti sauti ya siren pia kuangalia kama wakati umefika au la, na si kutumia kuchelewesha (). Lakini hii ingeongeza idadi ya nambari na kufanya programu isisomeke.

4 Kutumia Maktaba ya ArduinoThread ili kuunda nyuzi zinazofanana

Ili kutatua tatizo, tutatumia maktaba ya ajabu Uzi wa Arduino, ambayo inakuwezesha kuunda michakato ya pseudo-sambamba kwa urahisi. Inafanya kazi kwa njia sawa, lakini hukuruhusu kuzuia kuandika nambari ili kuangalia wakati - ikiwa unahitaji kufanya kazi katika kitanzi hiki au la. Hii inapunguza kiasi cha msimbo na inaboresha usomaji wa mchoro. Wacha tuangalie maktaba inavyofanya kazi.


Kwanza kabisa, pakua kumbukumbu ya maktaba kutoka kwa tovuti rasmi na uifungue kwenye saraka maktaba/ mazingira ya maendeleo Kitambulisho cha Arduino. Kisha badilisha jina la folda ArduinoThread-master V Uzi wa Arduino.

Mchoro wa uunganisho utabaki sawa. Msimbo wa programu pekee ndio utabadilika.

#pamoja na // kuunganisha maktaba ya ArduinoThread const int soundPin = 3; // kutofautiana na nambari ya siri ya kipengele cha piezoelectric const int ledPin = 13; // kutofautiana na nambari ya siri ya LED Thread ledThread = Thread(); // tengeneza thread ya kudhibiti LED Thread soundThread = Thread (); // unda thread ya kudhibiti siren usanidi utupu () ( pinMode(soundPin, OUTPUT); // tangaza pini 3 kama pato. pinMode(ledPin, OUTPUT); // tangaza pini 13 kama pato. ledThread.onRun(ledBlink); // toa kazi kwa thread ledThread.setInterval(1000); // weka muda wa majibu, ms soundThread.onRun(sauti); // toa kazi kwa thread soundThread.setInterval(20); // weka muda wa majibu, ms } kitanzi utupu() (// Angalia ikiwa ni wakati wa LED kubadili: ikiwa (ledThread.shouldRun()) ledThread.run(); // anza uzi // Angalia ikiwa ni wakati wa kubadilisha sauti ya siren: ikiwa (soundThread.shouldRun()) soundThread.run(); // anzisha thread } // Mkondo wa LED: led utupuBlink() ( tuli bool ledStatus = uongo; // Hali ya LED Imewashwa/Zima ledStatus = !ledHali; // Geuza hali ya digitalWrite(ledPin, ledStatus); // kuzima / kuzima LED } // Mkondo wa king'ora: sauti tupu () ( tuli int tone = 100; // sauti ya sauti, toni ya Hz (soundPin, tani); // washa king'ora kwa "tani" Hz ikiwa (tani)

Katika programu tunaunda nyuzi mbili - ledTread Na Uzi wa sauti, kila mmoja hufanya operesheni yake mwenyewe: mtu hupiga LED, pili hudhibiti sauti ya siren. Katika kila iteration ya kitanzi, kwa kila thread sisi kuangalia kama wakati umefika kwa ajili ya utekelezaji wake au la. Ikifika, inazinduliwa kwa ajili ya utekelezaji kwa kutumia njia kukimbia (). Jambo kuu sio kutumia operator kuchelewesha (). Kanuni hutoa maelezo ya kina zaidi.


Wacha tupakie nambari kwenye kumbukumbu ya Arduino na tuiendeshe. Sasa kila kitu kinafanya kazi kama inavyopaswa!

Maagizo

Kwa ujumla, Arduino haitumii usawazishaji wa kweli wa kazi, au usomaji mwingi.
Lakini kila wakati kitanzi cha "loop()" kinarudiwa, unaweza kubainisha ili kuangalia ikiwa ni wakati wa kufanya kazi ya ziada, ya nyuma. Katika kesi hii, itaonekana kwa mtumiaji kuwa kazi kadhaa zinafanywa wakati huo huo.
Kwa mfano, hebu tupepete kwa marudio fulani na, wakati huo huo, tufanye sauti zinazoongezeka na kupungua kama king'ora kutoka kwa mtoaji wa piezo.
Tayari tumeunganisha LED na Arduino kwa Arduino zaidi ya mara moja. Wacha tukusanye mzunguko kama inavyoonyeshwa kwenye takwimu. Ukiunganisha LED kwenye pini ya dijiti isipokuwa "13", usisahau kuhusu kizuia kikomo cha sasa cha takriban ohms 220.

Wacha tuandike mchoro kama huu na tuupakie kwa Arduino.
Baada ya kutazama ubao, ni wazi kwamba mchoro haufanyiki kama tunavyohitaji: mpaka siren ifanye kazi kikamilifu, LED haitapiga, na tungependa LED iwashe WAKATI wa siren. Tatizo ni nini hapa?
Ukweli ni kwamba tatizo hili haliwezi kutatuliwa kwa njia ya kawaida. Kazi zinafanywa na microcontroller madhubuti mfululizo. Opereta "kuchelewesha ()" huchelewesha utekelezaji wa programu kwa muda maalum, na hadi wakati huu utakapomalizika, amri zifuatazo katika programu hazitatekelezwa. Kwa sababu ya hili, hatuwezi kuweka muda tofauti wa utekelezaji kwa kila kazi katika kitanzi cha "loop()" cha programu.
Kwa hiyo, unahitaji kwa namna fulani kuiga multitasking.

Chaguo ambalo Arduino itafanya kazi pseudo-parallel linapendekezwa na wasanidi wa Arduino katika makala https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay.
Kiini cha njia ni kwamba kwa kila marudio ya kitanzi () tunaangalia ikiwa ni wakati wa kuangaza LED (fanya kazi ya nyuma) au la. Na ikiwa imefika, basi tunageuza hali ya LED. Hii ni aina ya kupita kwa "kuchelewesha ()".
Ubaya mkubwa wa njia hii ni kwamba sehemu ya msimbo kabla ya kizuizi cha udhibiti wa LED lazima itekelezwe kwa muda mrefu zaidi ya muda wa kupepesa wa LED "ledInterval". Vinginevyo, blinking itatokea mara chache zaidi kuliko lazima, na hatutapata athari za utekelezaji sambamba wa kazi. Hasa, katika mchoro wetu, muda wa mabadiliko ya sauti ya siren ni 200+200+200+200 = 800 ms, na tunaweka muda wa kuangaza kwa LED hadi 200 ms. Lakini LED itaangaza kwa muda wa 800 ms, ambayo ni mara 4 tofauti na kile tunachoweka. Kwa ujumla, ikiwa nambari yako hutumia opereta "delay()", ni ngumu kuiga usawa wa uwongo, kwa hivyo inashauriwa kuizuia.
Katika kesi hii, itakuwa muhimu kwa kitengo cha kudhibiti siren pia kuangalia ikiwa wakati umefika au la, na usitumie "kuchelewesha ()". Lakini hii ingeongeza idadi ya nambari na kufanya programu isisomeke.

Ili kutatua tatizo hili, tutatumia maktaba ya ajabu ya ArduinoThread, ambayo inakuwezesha kuunda michakato ya pseudo-sambamba kwa urahisi. Ni sawa, lakini hukuruhusu usiandike msimbo ili kuangalia wakati - ikiwa unahitaji kufanya kazi katika mzunguko huu au la. Hii inapunguza kiasi cha msimbo na inaboresha usomaji wa mchoro. Wacha tuangalie maktaba inavyofanya kazi.
Kwanza kabisa, pakua kumbukumbu ya maktaba kutoka kwa tovuti rasmi https://github.com/ivanseidel/ArduinoThread/archive/master.zip na uifungue kwenye saraka ya "maktaba" ya mazingira ya maendeleo ya Arduino IDE. Kisha ubadilishe jina la folda ya "ArduinoThread-master" kuwa "ArduinoThread".

Mchoro wa uunganisho utabaki sawa. Msimbo wa programu pekee ndio utabadilika. Sasa itaonekana kama katika inset.
Katika programu tunaunda nyuzi mbili, kila mmoja akifanya kazi yake mwenyewe: moja hupiga LED, ya pili inadhibiti sauti ya siren. Katika kila iteration ya kitanzi, kwa kila thread sisi kuangalia kama wakati umefika kwa ajili ya utekelezaji wake au la. Ikifika, inazinduliwa kwa utekelezaji kwa kutumia njia ya "run()". Jambo kuu sio kutumia opereta "kuchelewesha ()".
Kanuni hutoa maelezo ya kina zaidi.
Wacha tupakie nambari kwenye kumbukumbu ya Arduino na tuiendeshe. Sasa kila kitu kinafanya kazi kama inavyopaswa!

Shauku, utiifu wa kazi au matamanio yaliyoongezeka yanatusukuma kuchukua majukumu na majukumu mengi iwezekanavyo. Kwa hiyo, katika usiku wa kipindi cha kuripoti, kichwa chako kinapasuka na kazi ambazo hazijatimizwa, na "orodha ya mambo ya kufanya" huwa na urefu wa safu ya Ukuta.

Utahitaji

  • - mratibu
  • - programu ya kupanga wakati wa kufanya kazi (kwa mfano, saa ya ChromoDoro - Programu ya Google http://click.ru/9ZC1)
  • - Ratiba ya kazi au "orodha ya kufanya" katika mfumo wa jedwali.
  • - stika na alama

Maagizo

"Kwangu na mimi"

Kazi zote zimegawanywa katika zile zinazohitaji kufanywa, au zinaweza kupewa mtu ambaye hana shughuli nyingi. Kuna aina ya wasimamizi wanaowajibika kupita kiasi ambao wanaamini kwamba lazima wachukue kazi ya idara nzima juu yao wenyewe. Kwa hiyo, wazazi hawakuruhusu kufunga kamba za viatu vyako kwa sababu wazazi ni bora zaidi. Huwezi kumnyang'anya na kumnyima mhudumu wa chini nafasi ya kuonyesha uwezo wake. Ni sawa na nyumbani. Badala ya kujiahidi kila usiku kurekebisha bomba linalotiririka, unahitaji kumwita fundi bomba na kuvuka kazi kutoka kwenye orodha.

"Chini na kuchelewesha"

Jambo hili la kisaikolojia lina aina nyingi na, ipasavyo, ufafanuzi, lakini kwa ujumla ni kusita kuanza kutatua shida. Wakati mwingine hatua ya kwanza ni ngumu kuchukua kwa sababu ya woga mdogo wa kutofaulu, wakati mwingine ni kusita kabisa kuhama kutoka kwa hali nzuri ya uvivu kwenda kwa hali isiyofaa. Mara nyingi mtu hujiambia: "Nitakula apple, kucheza solitaire na kisha ...". Tunahitaji kubadili mawazo yetu. Na fanya apple na solitaire thawabu kwa juhudi zako. Na, mantra ya kila siku itasikika kama: "Ikiwa nitafanya kazi kwa dakika 15, nitakula apple! Ninastahili." Lakini sanaa ya usimamizi wa wakati sio rahisi.

Vikundi vya kazi

Katika biashara, hizi zinaweza kuwa kazi zinazohusiana na maeneo ya kazi (vifaa au bei). Mwanafunzi ana vizuizi vya mada vya nyenzo inayosomwa. Watu wa hali ya juu hugawanya ghorofa katika kanda. "Bafuni", "ukanda", "nafasi karibu na TV" - kila mtu anayo mbinu ya mtu binafsi. Na usitumie zaidi ya dakika 15 katika kila eneo ili kurejesha utulivu. Hii inatosha kudumisha usafi kwa urahisi, kuokoa muda na sio kwenda wazimu na hatia juu ya kazi ambazo hazijakamilika. Karibu na kila kikundi cha kazi, ni vizuri kuandika takriban asilimia ya kazi iliyokamilishwa. Matokeo yanayoonekana ya kazi huchangia faraja ya kisaikolojia na kuongezeka kwa wasiwasi, ambayo huzuia kukamilika kwa kazi.

Kuhamasisha

Ikiwa iko, basi hila za kiufundi zitaboresha kazi. Ikiwa kuna matatizo nayo, basi vikumbusho vya elektroniki na stika zitasababisha hasira. Kwa hiyo, ni muhimu kuelewa faida za kutatua matatizo na kukabiliana na kazi kwa uangalifu. Ikiwa akili inazunguka, ikipotoshwa na upuuzi wa kupendeza, basi labda hakuna furaha ya kutosha ndani yake. Ni vigumu zaidi kwa mtu aliyeshuka moyo kuwa na ufanisi. Hii ina maana kwamba motisha kwa ajili ya kutatua matatizo, msukumo na mtazamo maalum chanya wa ubunifu lazima kutafutwa kutoka nje.

Video kwenye mada

Kumbuka

Kazi zote zinaweza kugawanywa katika makundi manne yanayojulikana: muhimu na si ya haraka, muhimu na ya haraka, sio muhimu na ya haraka, sio muhimu na si ya haraka. Kisha itakuwa rahisi kuhesabu wakati wa kukamilisha kila kazi. Jambo kuu sio kusahau kujumuisha mapumziko ya dakika kumi na tano.

Ushauri wa manufaa

Usinyunyize dawa. Sisi sote tunajaribu kuishi kulingana na matarajio ya watu wengine. Lakini lazima tujifunze kusema: "Acha." Ili kukamilisha kazi kwa ufanisi, unahitaji kuzingatia kabisa. Na kwa hili, inaonekana, unahitaji kufanya kazi kwa mwelekeo mmoja, ukipunguza jitihada zote za akili yako kutatua matatizo.

Kwa ujumla, Arduino haitumii usawazishaji wa kweli wa kazi, au usomaji mwingi. Lakini inawezekana kwa kila marudio ya mzunguko kitanzi () amuru kidhibiti kidogo kuangalia ikiwa ni wakati wa kufanya kazi ya ziada, ya chinichini. Katika kesi hii, itaonekana kwa mtumiaji kuwa kazi kadhaa zinafanywa wakati huo huo.

Kwa mfano, hebu tuwashe LED kwa mzunguko fulani na, wakati huo huo, tufanye sauti zinazoongezeka na zinazopungua kama siren kutoka kwa emitter ya piezo. Tayari tumeunganisha LED na emitter ya piezo kwa Arduino zaidi ya mara moja. Wacha tukusanye mzunguko kama inavyoonyeshwa kwenye takwimu.

Ukiunganisha LED kwenye pini ya dijiti isipokuwa "13", usisahau kuhusu kizuia kikomo cha sasa cha takriban ohms 220.

2 Udhibiti wa emitter ya LED na piezo kwa kutumia delay() operator

Wacha tuandike mchoro kama huu na tuupakie kwa Arduino.

Const int soundPin = 3; /* kutangaza kutofautiana na nambari ya pini ambayo kipengele cha piezoelectric kimeunganishwa */ const int ledPin = 13; // tangaza kigezo kwa nambari ya pini ya LED usanidi utupu () ( pinMode(soundPin, OUTPUT); // tangaza pini 3 kama pato. pinMode(ledPin, OUTPUT); // tangaza pini 13 kama pato. } kitanzi utupu() (// Udhibiti wa sauti: tone (soundPin, 700); // fanya sauti kwa mzunguko wa kuchelewa kwa 700 Hz (200); tone(soundPin, 500); // kwa mzunguko wa kuchelewa kwa 500 Hz (200); tone(soundPin, 300); // kwa mzunguko wa kuchelewa kwa 300 Hz (200); tone(soundPin, 200); // kwa mzunguko wa kuchelewa kwa 200 Hz (200); // Udhibiti wa LED: digitalWrite (ledPin, HIGH); // kuchelewa kwa mwanga (200); digitalWrite(ledPin, LOW); // kuzima kuchelewa (200); }

Baada ya kuiwasha, ni wazi kwamba mchoro haufanyiki kama tunavyohitaji: hadi siren ifanye kazi kikamilifu, LED haitaangaza, lakini tungependa LED itupe. wakati sauti ya king'ora. Tatizo ni nini hapa?

Ukweli ni kwamba tatizo hili haliwezi kutatuliwa kwa njia ya kawaida. Kazi zinafanywa na microcontroller madhubuti mfululizo. Opereta kuchelewesha () huchelewesha utekelezaji wa programu kwa muda maalum, na hadi wakati huu utakapomalizika, amri zifuatazo za programu hazitatekelezwa. Kwa sababu hii, hatuwezi kuweka muda tofauti wa utekelezaji kwa kila kazi kwenye kitanzi kitanzi () programu. Kwa hiyo, unahitaji kwa namna fulani kuiga multitasking.

3 Michakato sambamba bila mwendeshaji wa "kuchelewesha ()".

Chaguo ambalo Arduino itafanya kazi sambamba-pseudo lilipendekezwa na watengenezaji wa Arduino. Kiini cha njia ni kwamba kwa kila marudio ya mzunguko kitanzi () tunaangalia ikiwa ni wakati wa kupepesa LED (fanya kazi ya chinichini) au la. Na ikiwa imefika, basi tunageuza hali ya LED. Hii ni aina ya chaguo la bypass kwa operator kuchelewesha ().

Const int soundPin = 3; // kutofautiana na nambari ya siri ya kipengele cha piezoelectric const int ledPin = 13; // kutofautiana na nambari ya pini ya LED const ledInterval ndefu = 200; // Muda wa kupepesa kwa LED, ms. int ledState = CHINI; // hali ya awali ya LED ambayo haijasajiliwa kwa muda mrefuMillis = 0; // kuhifadhi wakati wa uanzishaji wa awali wa LED usanidi utupu () ( pinMode(soundPin, OUTPUT); // weka pini 3 kama pato. pinMode(ledPin, OUTPUT); // weka pini 13 kama pato. } kitanzi utupu() (// Udhibiti wa sauti: tone (soundPin, 700); kuchelewa (200); tone(soundPin, 500); kuchelewa (200); tone(soundPin, 300); kuchelewa (200); tone(soundPin, 200); kuchelewa (200); // Flashing LED: // muda tangu Arduino iwashwe, ms: unsigned long currentMillis = millis(); // Ikiwa wakati umefika wa kufumba macho, ikiwa (currentMillis - previousMillis >= ledInterval) ( previousMillis = currentMillis; // basi kumbuka wakati wa sasa ikiwa (ledState == LOW) ( // na kugeuza hali ya LED ledState = JUU; ) mwingine ( ledState = LOW; ) digitalWrite(ledPin, ledState); // badilisha hali ya LED) }

Ubaya mkubwa wa njia hii ni kwamba sehemu ya msimbo kabla ya kizuizi cha udhibiti wa LED lazima itekelezwe kwa kasi zaidi kuliko muda wa kupepesa wa LED "ledInterval". Vinginevyo, blinking itatokea mara chache zaidi kuliko lazima, na hatutapata athari za utekelezaji sambamba wa kazi. Hasa, katika mchoro wetu, muda wa mabadiliko ya sauti ya siren ni 200+200+200+200 = 800 ms, na tunaweka muda wa kuangaza kwa LED hadi 200 ms. Lakini LED itaangaza kwa muda wa 800 ms, ambayo ni mara 4 zaidi kuliko tuliyoweka.

Kwa ujumla, ikiwa msimbo hutumia operator kuchelewesha (), katika kesi hii ni vigumu kuiga pseudo-parallelism, hivyo ni vyema kuepuka.

Katika kesi hii, itakuwa muhimu kwa kitengo cha kudhibiti sauti ya siren pia kuangalia ikiwa wakati umefika au la, na sio kutumia. kuchelewesha (). Lakini hii ingeongeza idadi ya nambari na kufanya programu isisomeke.

4 Kutumia Maktaba ya ArduinoThread ili kuunda nyuzi zinazofanana

Ili kutatua tatizo, tutatumia maktaba ya ajabu Uzi wa Arduino, ambayo inakuwezesha kuunda michakato ya pseudo-sambamba kwa urahisi. Inafanya kazi kwa njia sawa, lakini hukuruhusu kuzuia kuandika nambari ili kuangalia wakati - ikiwa unahitaji kufanya kazi katika kitanzi hiki au la. Hii inapunguza kiasi cha msimbo na inaboresha usomaji wa mchoro. Wacha tuangalie maktaba inavyofanya kazi.


Kwanza kabisa, pakua kumbukumbu ya maktaba kutoka kwa tovuti rasmi na uifungue kwenye saraka maktaba/ Mazingira ya maendeleo ya Arduino IDE. Kisha badilisha jina la folda ArduinoThread-master V Uzi wa Arduino.

Mchoro wa uunganisho utabaki sawa. Msimbo wa programu pekee ndio utabadilika.

#pamoja na // kuunganisha maktaba ya ArduinoThread const int soundPin = 3; // kutofautiana na nambari ya siri ya kipengele cha piezoelectric const int ledPin = 13; // kutofautiana na nambari ya siri ya LED Thread ledThread = Thread(); // tengeneza thread ya kudhibiti LED Thread soundThread = Thread (); // unda thread ya kudhibiti siren usanidi utupu () ( pinMode(soundPin, OUTPUT); // tangaza pini 3 kama pato. pinMode(ledPin, OUTPUT); // tangaza pini 13 kama pato. ledThread.onRun(ledBlink); // toa kazi kwa thread ledThread.setInterval(1000); // weka muda wa majibu, ms soundThread.onRun(sauti); // toa kazi kwa thread soundThread.setInterval(20); // weka muda wa majibu, ms } kitanzi utupu() (// Angalia ikiwa ni wakati wa LED kubadili: ikiwa (ledThread.shouldRun()) ledThread.run(); // anza uzi // Angalia ikiwa ni wakati wa kubadilisha sauti ya siren: ikiwa (soundThread.shouldRun()) soundThread.run(); // anzisha thread } // Mkondo wa LED: led utupuBlink() ( tuli bool ledStatus = uongo; // Hali ya LED Imewashwa/Zima ledStatus = !ledHali; // Geuza hali ya digitalWrite(ledPin, ledStatus); // kuzima / kuzima LED } // Mkondo wa king'ora: sauti tupu () ( tuli int tone = 100; // sauti ya sauti, toni ya Hz (soundPin, tani); // washa king'ora kwa "tani" Hz ikiwa (tani)

Katika programu tunaunda nyuzi mbili - ledTread Na Uzi wa sauti, kila mmoja hufanya operesheni yake mwenyewe: mtu hupiga LED, pili hudhibiti sauti ya siren. Katika kila iteration ya kitanzi, kwa kila thread sisi kuangalia kama wakati umefika kwa ajili ya utekelezaji wake au la. Ikifika, inazinduliwa kwa ajili ya utekelezaji kwa kutumia njia kukimbia (). Jambo kuu sio kutumia operator kuchelewesha (). Kanuni hutoa maelezo ya kina zaidi.


Wacha tupakie nambari kwenye kumbukumbu ya Arduino na tuiendeshe. Sasa kila kitu kinafanya kazi kama inavyopaswa!

Boresha programu zako za Arduino kwa kukatizwa - njia rahisi kujibu matukio katika muda halisi!

Tunakatisha usambazaji wetu...

Kama inavyobadilika, kuna utaratibu mzuri (lakini haujatumika) uliojengwa ndani ya Arduinos zote ambao ni bora kwa kufuatilia matukio kwa wakati halisi. Utaratibu huu inayoitwa usumbufu. Kazi ya kukatiza ni kuhakikisha kuwa kichakataji kinajibu haraka kwa matukio muhimu. Wakati mawimbi mahususi yanapogunduliwa, kukatiza (kama jina linavyopendekeza) kutatiza chochote ambacho kichakataji kilikuwa kikifanya na kutekeleza msimbo fulani ulioundwa kujibu mawimbi iliyosababisha. sababu ya nje, inayoathiri Arduino. Baada ya nambari hii kutekelezwa, processor inarudi kwa kile iliyokuwa ikifanya hapo awali kana kwamba hakuna kilichotokea!

Cha kustaajabisha kuhusu hili ni kwamba kukatizwa hukuruhusu kupanga programu yako ili kujibu kwa haraka na kwa ufanisi matukio muhimu ambayo hayatarajiwi kwa urahisi katika kitanzi cha programu. Zaidi ya yote, kukatizwa huruhusu kichakataji kufanya mambo mengine badala ya kupoteza muda kusubiri tukio litendeke.

Kitufe kinakatiza

Hebu tuanze na mfano rahisi: Tumia ukatizaji kufuatilia mibonyezo ya vitufe. Kuanza, tutachukua mchoro ambao labda umeona tayari: mfano wa "Kitufe" kilichojumuishwa kwenye IDE ya Arduino (unaweza kuipata kwenye saraka ya "Mifano", angalia menyu Faili → Mifano → 02. Digital → Button )

Const int buttonPin = 2; // nambari ya siri iliyo na kitufe const int ledPin = 13; // nambari ya siri na kifungo cha int cha LEDState = 0; // kutofautisha kwa kusoma hali ya usanidi wa utupu wa kitufe() ( // weka pini ya LED kutoa: pinMode(ledPin, OUTPUT); // weka pini ya kitufe ili kuingiza: pinMode(buttonPin, INPUT); ) kitanzi tupu () ( // soma hali ya kitufe: buttonState = digitalRead(buttonPin); // angalia ikiwa kitufe kimebonyezwa. // ikiwa imebonyezwa, basi kitufeJimbo ni JUU: ikiwa (buttonState == HIGH) ( // washa LED : digitalWrite(ledPin, HIGH); ) vinginevyo ( // zima LED: digitalWrite(ledPin, LOW); ) )

Hakuna kitu cha kushangaza au cha kushangaza kuhusu kile unachokiona hapa: programu yote hufanya mara kwa mara ni kupitia loop() na kusoma thamani ya buttonPin . Wacha tufikirie kwa sekunde moja kuwa ungependa kufanya kitu zaidi na loop(), kitu zaidi ya kusoma tu hali ya pato. Hapa ndipo usumbufu unapopatikana. Badala ya kufuatilia kila mara hali ya pini, tunaweza kukabidhi kazi hii kwa kitanzi cha kukatiza na kisicholipishwa ili kufanya kile tunachohitaji kwa sasa! Msimbo mpya itaonekana kama hii:

Const int buttonPin = 2; // nambari ya siri iliyo na kitufe const int ledPin = 13; // nambari ya siri iliyo na kitufe cha int tete cha LEDState = 0; // kutofautisha kwa kusoma hali ya usanidi wa utupu wa kitufe() ( // weka pini ya LED kutoa: pinMode(ledPin, OUTPUT); // weka pini ya kitufe ili kuingiza: pinMode(buttonPin, INPUT); // ambatisha kukatiza kwa kiambatisho cha vekta ya ISRKukatiza (0, pin_ISR, CHANGE); ) kitanzi batili() ( // Hakuna kitu hapa! ) pini batili_ISR() ( buttonState = digitalRead(buttonPin); digitalWrite(ledPin, buttonState); )

Mizunguko na njia za kukatiza

Utaona mabadiliko machache hapa. Ya kwanza na dhahiri zaidi ni kwamba loop() sasa haina maagizo! Tunaweza kufanya bila wao, kwa kuwa kazi yote ambayo ilifanywa hapo awali katika taarifa ya if/engine sasa imefanywa ndani kipengele kipya pin_ISR() . Aina hii ya kazi inaitwa kishughulikiaji cha usumbufu: kazi yake ni kukimbia haraka, kushughulikia usumbufu, na kuruhusu processor kurudi nyuma kwenye programu kuu (yaani, yaliyomo kwenye kitanzi ()). Kuna mambo kadhaa ya kuzingatia wakati wa kuandika kidhibiti cha kukatiza: pointi muhimu, ambayo unaweza kuona ikionyeshwa kwenye nambari iliyo hapo juu:

  • washughulikiaji wanapaswa kuwa mfupi na mafupi. Hutaki kukatiza kitanzi kikuu kwa muda mrefu!
  • washikaji hawana vigezo vya pembejeo na maadili ya kurudi. Mabadiliko yote lazima yafanywe kwa vigezo vya kimataifa.

Labda unashangaa: tunajuaje wakati usumbufu utawaka? Inasababishwa na nini? Kazi ya tatu, inayoitwa katika setup() kazi, huweka usumbufu kwa mfumo mzima. Kazi hii attachInterrupt() inachukua hoja tatu:

  1. vekta ya kukatiza ambayo huamua ni pini gani inaweza kutoa usumbufu. Hii sio nambari ya pini yenyewe, lakini ni rejeleo la eneo kwenye kumbukumbu ambalo kichakataji cha Arduino lazima kitazame ili kuona ikiwa usumbufu umetokea. Nafasi hii katika vector hii inalingana na maalum pato la nje, na sio pini zote zinaweza kutoa usumbufu! Kwenye Arduino Uno, pini 2 na 3 na vidhibiti vya kukatiza 0 na 1, mtawaliwa, vinaweza kutoa usumbufu. Kwa orodha ya pini zinazoweza kuzalisha ukatizaji, angalia hati za utendaji wa Arduino ambatishaInterrupt;
  2. kukatiza jina la utendaji wa kidhibiti: hufafanua msimbo ambao utatekelezwa wakati hali ya kichochezi cha kukatiza inatimizwa;
  3. hali ya kukatiza, ambayo huamua ni kitendo gani cha kipini kinachosababisha kukatiza. Arduino Uno inasaidia njia nne za kukatiza:
    • RISING - huamsha usumbufu wa makali ya kuongezeka kwenye pini ya usumbufu;
    • KUANGUKA - huamsha usumbufu unaoanguka;
    • BADILISHA - humenyuka kwa mabadiliko yoyote katika thamani ya pini ya kukatiza;
    • LOW - Hupiga simu wakati pin iko chini.

Na ili kurejea, usanidi wetu wa attachInterrupt() unalingana na kufuatilia kukatiza vekta 0 (pin 2) ili kujibu usumbufu kwa pin_ISR() , na kupiga pin_ISR() wakati wowote. kutakuwa na mabadiliko hadhi kwenye pini 2.

Tete

Hoja nyingine inayofaa kuashiria ni kwamba kidhibiti chetu cha kukatiza hutumia kibadilishaji cha hali ya kifungo kuhifadhi hali ya matokeo. Angalia ufafanuzi wa buttonState: badala yake chapa int, tuliifafanua kama aina tete ya int. Kuna nini hapa? tete ni neno kuu la lugha C ambalo hutumika kwa vigeuzo. Ina maana kwamba thamani ya kutofautiana haiko chini udhibiti kamili programu. Hiyo ni, thamani ya kifungoState inaweza kubadilika na kubadilisha kitu ambacho programu yenyewe haiwezi kutabiri - katika kesi hii, pembejeo ya mtumiaji.

Mwingine jambo la manufaa katika neno kuu tete ni kulinda dhidi ya uboreshaji wowote wa bahati mbaya. Wakusanyaji, zinageuka, fanya chache zaidi kazi za ziada wakati wa kubadilisha msimbo wa chanzo wa programu kuwa msimbo wa mashine kanuni inayoweza kutekelezwa. Moja ya kazi hizi ni kuondoa isiyotumiwa msimbo wa chanzo vigezo kutoka kanuni ya mashine. Kwa kuwa kibadilishaji cha hali ya kifungo hakitumiki au kuitwa moja kwa moja ndani kazi za kitanzi() au setup() , kuna hatari kwamba mkusanyaji anaweza kuiondoa kama kigezo kisichotumika. Ni wazi kuwa hii sio sawa - tunahitaji utaftaji huu! Neno muhimu tete ina athari ya upande, kumwambia mkusanyaji kwamba utofauti huu unapaswa kuachwa peke yake.

Kuondoa vigeu visivyotumika kutoka kwa nambari ni kipengele cha kazi, sio kosa la mkusanyaji. Watu wakati mwingine huacha vigeu visivyotumika katika msimbo wao ambavyo huchukua kumbukumbu. Sio hivyo tatizo kubwa, ikiwa unaandika programu ya C kwa kompyuta yenye gigabytes ya RAM. Walakini, kwenye Arduino RAM mdogo na hutaki kuipoteza! Hata wakusanyaji wa C kwa kompyuta watafanya vivyo hivyo, licha ya wingi wa kupatikana kumbukumbu ya mfumo. Kwa ajili ya nini? Kwa sababu hiyo hiyo kwamba watu husafisha baada ya wao wenyewe baada ya picnic - ni mazoezi mazuri, usiache takataka nyuma.

Kwa muhtasari

Kukatiza ni njia rahisi ya kufanya mfumo wako kujibu kwa haraka kazi zinazotegemea wakati. Pia wana faida ya ziada- kufungia kitanzi kikuu () kitanzi, kikiruhusu kuzingatia kazi kuu ya mfumo (mimi naona kuwa kutumia visumbufu huelekea kuweka nambari yangu kupangwa zaidi: ni rahisi kuona kile kipande kikuu cha nambari kimeundwa kwa ajili ya na ni matukio gani ya muda hushughulikiwa na kukatizwa). Mfano ulioonyeshwa hapa ni kesi ya msingi zaidi ya utumiaji wa kukatiza; unaweza kutumia kusoma data kutoka kwa kifaa cha I2C, usambazaji wa wireless na kupokea data, au hata kuwasha au kusimamisha injini.

Miradi yoyote nzuri ya usumbufu? Acha maoni yako hapa chini!