- Ce este Multitasking-ul?
- De ce să omiteți delay () în Arduino?
- De ce să folosiți millis ()?
- Componente necesare
- Diagrama circuitului
- Programarea Arduino UNO pentru multitasking
Multitasking a condus calculatoarele la o revoluție în cazul în care una sau mai multe programe pot rula simultan, ceea ce mărește eficiența, flexibilitatea, adaptabilitatea și productivitatea. În sistemele încorporate, microcontrolerele pot gestiona, de asemenea, Multitasking și îndeplinesc simultan două sau mai multe sarcini fără a opri instrucțiunile actuale.
Aici, în acest tutorial, vom afla cum efectuează Arduino funcția Multitasking cu funcția Arduino millis. În general, o funcție delay () este utilizată în Arduino pentru o sarcină periodică precum LED-ul intermitent, dar această funcție delay () oprește programul pentru o perioadă definitivă de timp și nu permite efectuarea altor operații. Deci, acest articol explică modul în care putem evita utilizarea funcției delay () și înlocuim-o cu millis () pentru a efectua mai multe sarcini simultan și pentru a face din Arduino un controler de multitasking. Înainte de a intra în detalii, să începem cu multitaskingul subevaluat.
Ce este Multitasking-ul?
Multitasking înseamnă pur și simplu executarea simultană a mai multor sarcini sau programe. Aproape toate sistemele de operare dispun de multitasking. Acest tip de sisteme de operare sunt cunoscute sub numele de MOS (sistem de operare multitasking). MOS poate fi un sistem de operare pentru computer mobil sau desktop. Exemplul bun de multitasking în computere este atunci când utilizatorii rulează simultan aplicația de e-mail, browserul de internet, playerul media, jocurile și dacă utilizatorii nu doresc să utilizeze aplicația, aceasta rulează în fundal dacă nu este închisă. Utilizatorul final folosește toate aceste aplicații în același timp, dar sistemul de operare ia acest concept puțin diferit. Să discutăm despre modul în care sistemul de operare gestionează multitasking-ul.
După cum se vede în imagine, CPU împarte timpul în cele trei părți egale și atribuie fiecare parte fiecărei sarcini / aplicații. Așa se face multitasking-ul în majoritatea sistemelor. Conceptul va fi aproape același pentru Arduino Multitasking, cu excepția faptului că distribuția timpului va fi puțin diferită. Deoarece Arduino rulează în frecvență joasă și RAM se compară cu laptopul / mobilul / PC-ul, astfel timpul acordat fiecărei sarcini va fi, de asemenea, diferit. Arduino are, de asemenea, o funcție delay () care este utilizată pe scară largă. Dar înainte de a începe să discutăm de ce nu ar trebui să folosim funcția delay () în niciun proiect.
De ce să omiteți delay () în Arduino?
Dacă se ia în considerare documentația de referință a Arduino, există două tipuri de funcții de întârziere, prima este delay () și a doua este delayMicroseconds (). Ambele funcții sunt identice în ceea ce privește generarea întârzierii. Singura diferență este că, în funcția delay (), parametrul întreg trecut este în milisecunde, adică dacă scriem delay (1000), atunci întârzierea va fi de 1000 milisecunde, adică 1 secundă. În mod similar în funcția delayMicroseconds (), parametrul trecut este în microsecunde, adică dacă scriem delayMicroseconds (1000), atunci întârzierea va fi de 1000 microsecunde, adică 1 milisecundă.
Aici vine punctul, ambele funcții întrerup programul pentru perioada de timp trecută în funcția de întârziere. Deci, dacă oferim o întârziere de 1 secundă, atunci procesorul nu poate trece la următoarea instrucțiune până nu trece 1 secundă. În mod similar, dacă întârzierea este de 10 secunde, atunci programul se va opri timp de 10 secunde, iar procesorul nu va permite să urmeze instrucțiunile următoare până la trecerea celor 10 secunde. Acest lucru împiedică performanța microcontrolerului în ceea ce privește viteza și executarea instrucțiunilor.
Cel mai bun exemplu pentru a explica dezavantajul funcției de întârziere este utilizarea a două butoane. Luați în considerare faptul că dorim să comutăm două LED-uri folosind două butoane. Deci, dacă este apăsat un buton, LED-ul corespunzător ar trebui să lumineze timp de 2 secunde, în mod similar, dacă este apăsat al doilea, LED-ul ar trebui să lumineze timp de 4 secunde. Dar când folosim delay (), dacă utilizatorul apasă primul buton, atunci programul se va opri timp de 2 secunde și dacă utilizatorul apasă al doilea buton înainte de 2 secunde întârziere, atunci microcontrolerul nu va accepta intrarea, deoarece programul este în stadiul de oprire.
Documentația oficială a Arduino menționează clar acest lucru în descrierea funcției Note și avertismente de întârziere (). Puteți parcurge și verifica acest lucru pentru a fi mai clar.
De ce să folosiți millis ()?
Pentru a depăși problema cauzată de utilizarea întârzierii, un dezvoltator ar trebui să utilizeze funcția millis () care este ușor de utilizat odată ce ați devenit obișnuit și va utiliza 100% performanța procesorului fără a genera întârzieri în executarea instrucțiunilor. millis () este o funcție care returnează doar cantitatea de milisecunde care s-au scurs de când placa Arduino a început să ruleze programul curent fără a îngheța programul. Acest număr de timp se va revărsa (adică va reveni la zero), după aproximativ 50 de zile.
La fel cum Arduino are delayMicroseconds (), are și versiunea micro a millis () ca micros (). Diferența dintre micros și milis este că micros () se va revărsa după aproximativ 70 de minute, comparativ cu milis () care este de 50 de zile. Deci, în funcție de aplicație, puteți utiliza millis () sau micros ().
Folosind millis () în loc de delay ():
Pentru a utiliza milis () pentru sincronizare și întârziere, trebuie să înregistrați și să stocați ora la care a avut loc acțiunea pentru a începe ora și apoi verificați la intervale dacă timpul definit a trecut. Așa cum am menționat, stocați ora curentă într-o variabilă.
curent lung nesemnat Millis = millis ();
Avem nevoie de încă două variabile pentru a afla dacă timpul necesar a trecut. Am stocat ora curentă în variabila currentMillis , dar trebuie să știm și când a început perioada de sincronizare și cât de lungă este perioada. Deci Intervalul și precedentul Millis sunt declarate. Intervalul ne va spune întârzierea și previosMillis va stoca ultima dată când a avut loc evenimentul.
nesemnat mult timp anteriorMillis; perioadă lungă nesemnată = 1000;
Pentru a înțelege acest lucru, să luăm un exemplu de LED simplu intermitent. Perioada = 1000 ne va spune că LED-ul va clipi 1 secundă sau 1000ms.
const int ledPin = 4; // numărul pinului LED conectat int ledState = LOW; // folosit pentru a seta starea LED-ului nesemnat mult timp anteriorMillis = 0; // va stoca ultima oară când LED-ul a clipit constant perioadă lungă = 1000; // perioada la care să clipească în ms void setup () { pinMode (ledPin, OUTPUT); // set ledpin as output } void loop () { unsigned long currentMillis = millis (); // stochează ora curentă dacă (currentMillis - previousMillis> = period) {// verifică dacă 1000ms au trecut anteriorMillis = currentMillis; // salvați ultima dată când ați clipit LED-ul dacă (ledState == LOW) {// dacă LED-ul este oprit, porniți-l și viceversa ledState = HIGH; } else { ledState = LOW; } digitalWrite (ledPin, ledState); // setați LED-ul cu ledState să clipească din nou } }
Aici, afirmația
Întreruperile din Arduino funcționează la fel ca în alte microcontrolere. Placa Arduino UNO are doi pini separați pentru atașarea întreruperilor pe pinul 2 și 3. GPIO. Am tratat-o în detaliu în Arduino Interrupts Tutorial, unde puteți afla mai multe despre întreruperi și cum să le utilizați.
Aici vom arăta Arduino Multitasking gestionând două sarcini în același timp. Sarcinile vor include clipirea a două LED-uri cu întârziere diferită, împreună cu un buton care va fi utilizat pentru a controla starea ON / OFF a LED-ului. Deci, trei sarcini vor fi îndeplinite simultan.
Componente necesare
- Arduino UNO
- Trei LED-uri (orice culoare)
- Rezistențe (470, 10k)
- Jumpers
- Breadboard
Diagrama circuitului
Diagrama circuitului pentru demonstrarea utilizării funcției Arduino Millis () este foarte ușoară și nu are prea multe componente de atașat așa cum se arată mai jos.
Programarea Arduino UNO pentru multitasking
Programarea Arduino UNO pentru multitasking va necesita doar logica din spatele modului în care funcționează millis (), care este explicată mai sus. Se recomandă practica clipire cu LED - uri, folosind Millis din nou și din nou pentru a face logica clară și fă - te confortabil cu Millis () înainte de a începe programul Arduino UNO pentru multitasking. În acest tutorial, întreruperea este utilizată simultan cu millis () simultan pentru multitasking. Butonul va fi o întrerupere. Deci, ori de câte ori este generată o întrerupere, adică este apăsat butonul, LED-ul va trece la starea ON sau OFF.Programarea începe cu declararea numerelor de pin în care sunt conectate LED-urile și butonul Push.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
Apoi scriem o variabilă pentru a stoca starea LED-urilor pentru utilizare ulterioară.
int ledState1 = LOW; int ledState2 = LOW;
Așa cum s-a explicat mai sus în exemplul intermitent, variabilele pentru perioada și miliul anterior sunt declarate pentru a compara și genera întârziere pentru LED-uri. Primul LED clipește după fiecare 1 secundă și un alt LED clipește după 200ms.
nesemnat lung precedentMillis1 = 0; const lungă perioadă1 = 1000; nesemnat lung precedentMillis2 = 0; const lungă perioadă2 = 200;
O altă funcție de milis va fi utilizată pentru a genera întârzierea de respingere pentru a evita apăsările multiple ale butonului. Va exista o abordare similară cu cea de mai sus.
int debouncePeriod = 20; int debounceMillis = 0;
Cele trei variabile vor fi utilizate pentru a stoca starea butonului ca întrerupere, comutare LED și starea butonului.
buton boolPush = false; int ledChange = LOW; int lastState = HIGH;
Definiți acțiunea pinului care PIN va funcționa ca INPUT sau OUTPUT.
pinMode (led1, OUTPUT); pinMode (led2, OUTPUT); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Acum definiți pinul de întrerupere atașând întreruperea cu definiția ISR și modul de întrerupere. Rețineți că se recomandă utilizarea digitalPinToInterrupt (pin_number) atunci când declarați funcția attachInterrupt () pentru a traduce pinul digital real la numărul de întrerupere specific.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Subrutina de întrerupere este scrisă și va schimba doar steagul buttonPush. Rețineți că, subrutina de întrerupere trebuie să fie cât mai scurtă, așa că încercați să o scrieți și să minimizați instrucțiunile suplimentare.
void pushButton_ISR () { buttonPush = true; }
Bucla începe cu stocarea valorii de milis într-o variabilă currentMillis, care va stoca valoarea timpului scurs de fiecare dată când iterează bucla.
curent lung nesemnat Millis = millis ();
Există în total trei funcții în multitasking, clipesc un LED la 1 secundă, clipesc al doilea LED la 200ms și Dacă butonul este apăsat, apoi opriți LED-ul OFF / ON. Deci vom scrie trei părți pentru a realiza această sarcină.
Primul este Comuta de stat cu LED - uri după fiecare 1 secundă prin compararea Millis trecut.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }
În mod similar, în al doilea rând, comută LED-ul după fiecare 200 ms comparând milis-urile trecute. Explicația este deja explicată mai devreme în acest articol.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }
În cele din urmă, indicatorul buttonPush este monitorizat și după generarea unei întârzieri de retrogradare de 20 ms, comută doar starea LED-ului corespunde butonului atașat ca întrerupere.
if (buttonPushed = true) // verificați dacă ISR se numește { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // generați o întârziere de 20 ms pentru a evita apăsările multiple { debounceMillis = currentMillis; // salvați ultimul timp de întârziere a retragerii dacă (digitalRead (pushButton) == LOW && lastState == HIGH) // schimbați ledul după apăsarea butonului { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Aceasta termină tutorialul Arduino millis (). Rețineți că, pentru a deveni obișnuit cu millis (), practicați-vă să implementați această logică în alte aplicații. De asemenea, îl puteți extinde pentru a utiliza motoare, servomotoare, senzori și alte periferice. În caz de îndoială, vă rugăm să scrieți pe forumul nostru sau să comentați mai jos.
Codul complet și video pentru a demonstra utilizarea funcției millis în Arduino sunt furnizate mai jos.