Arduino Delay [Tutorial]

în acest tutorial veți învăța cum să utilizați în mod corespunzător delay() funcția pentru a adăuga unele întârziere între 2 acțiuni în programele Arduino. Apoi, veți descoperi de ce utilizarea delay() nu este adesea o idee bună atunci când doriți să vă scalați programele și cum să remediați acest lucru.

bine, să începem!

cuprins

de ce aveți nevoie de întârzieri în programele Arduino?

Ei bine, un program Arduino se bazează foarte mult pe intrări/ieșiri externe pentru a funcționa.

luând un exemplu simplu: poate doriți să monitorizați starea unui buton de 100 de ori pe secundă sau să faceți un LED să clipească la fiecare 0,5 secunde.

acum, cum poți realiza asta? Un program Arduino funcționează astfel:

  • în primul rând, funcția setup() este executată o singură dată.
  • apoi loop() funcția este executată din nou și din nou, până când opriți Arduino.

orice program pe care îl scrieți va fi executat la viteză maximă. Deci, dacă faceți o clipire LED în codul dvs., ceea ce se va întâmpla este că LED-ul va clipi la o rată foarte mare (cel puțin de mii de ori pe secundă).

înveți cum să folosești Arduino pentru a-ți construi propriile proiecte?

verificați Arduino pentru începători și învățați pas cu pas.

dacă doriți să controlați timpul – adică asigurați – vă că LED-ul clipește doar la fiecare 0,5 secunde și nu la viteză maximă-trebuie să adăugați o întârziere în codul dvs.

implementarea întârzierii Arduino în codul dvs.

funcția Arduino delay ()

Iată un cod pentru a face o clipire LED (aici alegem LED-ul încorporat, nu este nevoie să adăugați niciun LED extern) la fiecare 0,5 secunde – acesta este unul dintre cele mai frecvente exemple pe care le veți vedea dacă începeți cu Arduino.

#define LED_PIN 13void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { digitalWrite(LED_PIN, HIGH); delay(500); digitalWrite(LED_PIN, LOW); delay(500);}

deci, cum funcționează acest cod?

în primul rând utilizați un „define”, astfel încât să nu trebuie să hard-Cod numărul „13” de mai multe ori în codul și face programul mai ușor de citit.

configurați modul de ieșire a pinului cu funcția pinMode().

apoi, în funcția loop(), tu:

  1. porniți LED-ul
  2. utilizațidelay(500) pentru a face programul să doarmă timp de 500 de milisecunde sau 0,5 secunde
  3. opriți LED-ul
  4. utilizațidelay(500) pentru a face programul să doarmă din nou timp de 0,5 secunde
  5. și reveniți la Pasul 1, deoarece funcția loop() continuă să fie executată din nou și din nou.

funcția delay() vă așteaptă să acordați un număr de milisecunde – nu secunde – pentru a dormi. Deci, dacă vă gândiți în câteva secunde, înmulțiți numărul cu 1000 și aveți valoarea de care aveți nevoie.

faceți o întârziere Arduino timp de 1 minut

dacă doriți să faceți Arduino să doarmă timp de 1 minut sau mai multe minute, atunci este destul de ușor.

luați numărul de minute, înmulțiți-l cu 60 pentru a obține numărul de secunde, apoi înmulțiți-l cu 1000 pentru a obține numărul de milisecunde.

Ex: delay(3 * 60 * 1000); va face programul să doarmă timp de 3 minute.

funcția Arduino delayMicroseconds ()

dacă trebuie să fiți mai precis, poate fi necesar să utilizați funcția delayMicroseconds(). Cu delayMicroseconds() puteți oferi un număr de microsecunde pentru a dormi. Durata minimă pentru delay() este de 1 milisecundă, deci dacă trebuie să dormiți doar 400 de microsecunde, aici aveți o soluție nouă.

această funcție poate fi foarte utilă atunci când comunicați cu unele componente hardware. De exemplu, Arduino trebuie să trimită unele date componentei și apoi să citească un răspuns. Să presupunem că componenta are nevoie de 6 microsecunde pentru a procesa cererea și a furniza date exacte.

apoi, în programul dvs. este posibil să aveți ceva de genul asta:

...void loop() { // send data to component delayMicroseconds(6); // reach out to component again to read data}

întârziere fără blocare – de ce ar trebui să evitați utilizarea întârzierii ()

deci, acum că înțelegeți ce este o întârziere în Arduino și cum să o implementați cu delay() și delayMicroseconds(), să vedem cum să folosim funcționalitatea de întârziere – dar fără aceste funcții.

de ce?

când utilizați delay(), executarea programului dvs. se va opri și se va relua numai după terminarea întârzierii.

acest lucru este OK dacă aveți o singură acțiune de făcut – exemplu: clipește un singur LED-dar ce se întâmplă dacă trebuie să ai grijă de mai multe componente hardware sau să comunici cu alte dispozitive, cum ar fi plăcile Arduino sau propriul computer?

folosind exemplul anterior, cum ai putea face un LED să clipească la fiecare 0,5 secunde și altul să clipească la fiecare 0,8 secunde?

în acest caz, veți fi blocat destul de repede. Dacă totuși doriți să utilizați delay(), este posibil să găsiți o soluție în care să utilizați întârzieri mai scurte între mai multe acțiuni, dar acest lucru va face programul dvs. mai complicat de fiecare dată când adăugați o acțiune nouă.

soluția la aceasta este pur și simplu monitorizarea timpului fără a utiliza funcția delay(), practic pentru a găsi o modalitate de a reproduce comportamentul delay() fără a-l utiliza.

exemplu de cod – Arduino delay fără întârziere ()

să rescriem exemplul nostru LED blink fără a utiliza delay().

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); if (timeNow - lastTimeLedBlinked > delayBetweenBlink) { if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState); lastTimeLedBlinked = timeNow; }}

Să analizăm acest cod linie cu linie.

inițializare

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;

în primul rând, inițializați 3 variabile în domeniul global:

  • lastTimeLedBlinked: această variabilă va fi utilizată pentru a stoca ultima dată când LED-ul a clipit. Practic, de fiecare dată când vom face LED – ul să clipească, vom actualiza această variabilă cu ora curentă-folosind funcția millis ().
  • delayBetweenBlink: acesta este momentul în care doriți să așteptați între 2 acțiuni – aici acțiunea este să clipească LED-ul.
  • ledState: va trebui să stocăm starea curentă a LED-ului (înaltă sau joasă), astfel încât să putem ști care a fost starea anterioară și să luăm măsuri în consecință.

de ce în domeniul de aplicare global? Ei bine, ceea ce intenționăm să facem este să actualizăm acele variabile în funcția loop() și să le accesăm din nou data viitoare când intrăm în loop(). Dacă creăm variabilele în interiorul loop(), variabilele vor fi variabile locale și astfel vor fi distruse atunci când ieșiți din funcția loop(). Astfel, data viitoare loop() este numit din nou, toate valorile vor fi pierdute și veți crea variabile din nou, cu nici o valoare anterioară în interiorul. Aici, prin crearea variabilelor în afara funcției, le putem face să „supraviețuiască” și să-și păstreze valoarea de fiecare dată când intrăm în loop().

implementarea funcționalității Arduino delay în funcția buclă

acum, să vedem ce se întâmplă în funcția loop().

void loop() { unsigned int timeNow = millis();

mai întâi, citiți ora curentă cu funcția millis().

 if (timeNow - lastTimeLedBlinked > delayBetweenBlink) {

și acum comparați ora curentă pe care tocmai ați citit-o, cu data anterioară când LED-ul a clipit. Dacă a trecut suficient timp (mai mult decât valoarea stocată în delayBetweenBlink), atunci înseamnă că puteți introduce if().

această structură de cod – citind ora și comparând – o cu data anterioară când ați făcut o acțiune-este modul în care înlocuiți funcția delay(). Practic, calculezi doar o durată aici. Și, după cum puteți vedea, înseamnă că programul dvs. conține mai multe linii pentru o aplicație simplă, dar vă oferă mult mai mult control și este mult mai scalabil.

deci, ce se va întâmpla? Ei bine, loop() va continua să fie executat la viteză maximă. De fiecare dată, programul dvs. va verifica dacă a trecut suficient timp. Dacă nu, atunci loop() se termină aici, deoarece nu va intra în structura if.

și, când a trecut suficient timp, intrăm în if().

executarea acțiunii

 if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState);

OK, tocmai ați intrat în if() și aici veți face orice acțiune trebuie să faceți.

aici facem LED-ul să clipească. Și pentru că nu putem ști direct care a fost starea anterioară pentru LED (de când am intrat în loop() de multe ori și am pierdut toate variabilele locale create în interior), obținem acea stare dintr-o variabilă globală.

ce facem cu această variabilă globală este simplu: dacă era scăzută, o setăm la mare, iar dacă era ridicată, o setăm la mică. Și apoi, desigur, actualizăm starea fizică LED în consecință, cu digitalWrite().

 lastTimeLedBlinked = timeNow; }}

în cele din urmă, și acest lucru este foarte important, salvăm ora curentă ca ultima dată când am clipit LED-ul. Dacă nu facem asta, atunci programul va clipi LED-ul la viteză maximă, deoarece starea din interiorul if() va fi întotdeauna adevărată.

setând ora anterioară la ora curentă, „resetăm cronometrul”.

Deci, în acest exemplu, if() va fi introdus doar la fiecare 500 de milisecunde sau 0,5 secunde.

și acum acest lucru este minunat, deoarece programul dvs. nu se oprește, astfel încât să puteți continua să executați diferite acțiuni independente în timp ce încă „așteptați” să clipească LED-ul.

2 acțiuni „în același timp”

de exemplu, să presupunem că doriți să clipiți un LED la fiecare 0.5 secunde și încă una la fiecare 0,8 secunde.

#define LED_1_PIN 13#define LED_2_PIN 10unsigned int lastTimeLed1Blinked = millis();unsigned int delayBetweenBlink1 = 500;byte led1State = LOW;unsigned int lastTimeLed2Blinked = millis();unsigned int delayBetweenBlink2 = 800;byte led2State = LOW;void setup() { pinMode(LED_1_PIN, OUTPUT); pinMode(LED_2_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); // Action 1 - Blink LED 1 if (timeNow - lastTimeLed1Blinked > delayBetweenBlink1) { if (led1State == LOW) { led1State = HIGH; } else { led1State = LOW; } digitalWrite(LED_1_PIN, led1State); lastTimeLed1Blinked = timeNow; } // Action 2 - Blink LED 2 if (timeNow - lastTimeLed2Blinked > delayBetweenBlink2) { if (led2State == LOW) { led2State = HIGH; } else { led2State = LOW; } digitalWrite(LED_2_PIN, led2State); lastTimeLed2Blinked = timeNow; }}

după cum puteți vedea, repetăm structura codului pentru a doua acțiune pe care am adăugat-o. Și ambele acțiuni nu se vor deranja reciproc!

recapitulare

dacă doriți să faceți o întârziere Arduino fără a utiliza delay():

  1. creați o variabilă globală pentru a stoca ultima dată când ați făcut o acțiune specifică.
  2. creați o altă variabilă globală pentru a stoca durata dorită între 2 acțiuni.
  3. în funcția loop(), citiți ora curentă cu millis().
  4. imediat după aceea, utilizați o structură if și utilizați condiția (timeNow - lastTimeActionWasExecuted > delayBetweenActions).
  5. după ce ați intrat în if(), faceți acțiunea.
  6. și încă în if(), stocați ora curentă ca ora anterioară.

puteți repeta acești pași pentru fiecare acțiune pentru care aveți nevoie de o întârziere Arduino.

când este ok să utilizați delay() și delayMicroseconds ()

există ocazii specifice când utilizați delay() în codul dvs. este încă OK.

Iată 2 dintre acestea:

  • trebuie să inițializați o componentă în timpul configurării programului, iar această componentă are nevoie de ceva timp pentru a fi inițializată – de exemplu 1,5 secunde. În acest caz, utilizarea delay(1500) în funcția setup() este perfect în regulă. Practic, orice delay() în setup() funcția programului Arduino nu va fi o problemă.
  • după cum se explică în partea delayMicroseconds(), trebuie să așteptați câteva microsecunde (nu milisecunde!) atunci când comunicați cu o componentă externă. Dacă descoperiți că utilizarea delayMicroseconds() cu un număr mic (de exemplu 10) nu deranjează restul programului, îl puteți utiliza în continuare fără a fi nevoie să vă faceți griji prea mult. Dar considerați-o ca o excepție, nu regula comună.

concluzie – utilizați Arduino delay() cu grijă

datorită naturii programelor Arduino, va trebui adesea să adăugați întârzieri în codul dvs., astfel încât să puteți alege când să executați unele acțiuni și cât de des doriți să le executați.

funcțiile delay() și delayMicroseconds() sunt funcții foarte simple de utilizat și au fost adăugate la limba Arduino, astfel încât începătorii compleți să poată începe cu ceva simplu.

cu toate acestea, după cum ați văzut în acest tutorial, utilizarea delay() vă poate face să vă blocați foarte repede. Deci, cel mai bine este să înțelegeți mai întâi de ce aveți nevoie de ea, cum să o utilizați și apoi cum să obțineți același comportament fără a utiliza direct funcția Arduino delay().

odată ce ați înțeles structura codului pentru a scăpa de delay(), veți putea să vă îmbunătățiți foarte mult programele Arduino, iar multitasking-ul va deveni destul de ușor.

Lasă un răspuns

Adresa ta de email nu va fi publicată.