- Què és la multitarea?
- Per què saltar delay () a Arduino?
- Per què utilitzar millis ()?
- Components necessaris
- Esquema de connexions
- Programació Arduino UNO per a la multitarea
La multitarea ha portat els ordinadors a una revolució on un o més programes es poden executar simultàniament, cosa que augmenta l'eficiència, la flexibilitat, l'adaptabilitat i la productivitat. En sistemes incrustats, els microcontroladors també poden gestionar la multitarea i realitzen dues o més tasques simultàniament sense aturar les instruccions actuals.
Aquí en aquest tutorial aprendrem com Arduino realitza la multitasca amb la funció Arduino millis. Generalment, a Arduino s’utilitza una funció delay () per a tasques periòdiques com el LED Parpellejant, però aquesta funció delay () atura el programa durant un temps definitiu i no permet realitzar altres operacions. Per tant, en aquest article s’explica com podem evitar l’ús de la funció delay () i substituir-la per millis () per realitzar més d’una tasca simultàniament i convertir l’Arduino en un controlador multitasca. Abans d’entrar en els detalls, comencem per subestimar la multitarea.
Què és la multitarea?
La multitarea significa simplement executar més d’una tasca o programa simultàniament. Gairebé tots els sistemes operatius disposen de multitarea. Aquest tipus de sistemes operatius es coneixen com a MOS (sistema operatiu multitasca). El MOS pot ser un sistema operatiu per a ordinadors mòbils o d'escriptori. El bon exemple de la multitarea a les computadores és quan els usuaris executen l’aplicació de correu electrònic, el navegador d’Internet, el reproductor multimèdia i els jocs alhora i si els usuaris no volen utilitzar l’aplicació, s’executa en segon pla si no està tancada. L'usuari final utilitza totes aquestes aplicacions al mateix temps, però el sistema operatiu pren aquest concepte una mica diferent. Analitzem com el sistema operatiu gestiona la multitarea.

Com es veu a la imatge, la CPU divideix el temps en les tres parts iguals i assigna cada part a cada tasca / aplicació. Així es fa la multitarea a la majoria dels sistemes. El concepte serà gairebé el mateix per a la multitarea d’Arduino, excepte que la distribució horària serà una mica diferent. Atès que l'Arduino funciona amb baixa freqüència i la RAM es compara amb l'ordinador portàtil / mòbil / PC, de manera que el temps assignat a cada tasca també serà diferent. Arduino també té una funció delay () que s’utilitza àmpliament. Abans de començar, discutim per què no hem d’utilitzar la funció delay () en cap projecte.
Per què saltar delay () a Arduino?
Si es considera la documentació de referència d’Arduino, hi ha dos tipus de funcions de retard, la primera és delay () i la segona és delayMicroseconds (). Ambdues funcions són idèntiques pel que fa al retard de generació. L'única diferència és que, en la funció delay (), el paràmetre enter passat és en mil·lisegons, és a dir, si escrivim delay (1000), el retard serà de 1000 milisegons, és a dir, 1 segon. De manera similar, a la funció delayMicroseconds (), el paràmetre passat es troba en microsegons, és a dir, si escrivim delayMicroseconds (1000), el retard serà de 1000 microsegons, és a dir, 1 milisegon.
Aquí arriba el punt, ambdues funcions posen en pausa el programa per la quantitat de temps que passa la funció de retard. Per tant, si donem un retard d'1 segon, el processador no podrà anar a la següent instrucció fins que no passi 1 segon. De la mateixa manera, si el retard és de 10 segons, el programa s'aturarà durant 10 segons i el processador no permetrà anar a les següents instruccions fins que passin els 10 segons. Això dificulta el rendiment del microcontrolador en termes de velocitat i execució de les instruccions.
El millor exemple per explicar l’ inconvenient de la funció de retard és utilitzar dos botons. Penseu que volem canviar dos LED mitjançant dos botons polsadors. Per tant, si es prem un botó, el LED corresponent haurà de brillar durant 2 segons, de manera similar si es prem un segon, el LED haurà de brillar durant 4 segons. Però quan fem servir delay (), si l’usuari està pressionant el primer botó, el programa s’aturarà durant 2 segons i si l’usuari prem el segon botó abans de 2 segons de retard, el microcontrolador no acceptarà l’entrada ja que el programa és en fase de parada.
La documentació oficial d'Arduino ho menciona clarament a la descripció de la funció Notes i advertiments de delay (). Podeu continuar i comprovar això per deixar-ho més clar.
Per què utilitzar millis ()?
Per superar el problema causat per l’ús de delay, un desenvolupador hauria d’utilitzar la funció millis () , que és fàcil d’utilitzar un cop us hàgiu convertit en habitual i utilitzarà el rendiment de la CPU al 100% sense generar cap retard en l’execució de les instruccions. millis () és una funció que només retorna la quantitat de mil·lisegons que han transcorregut des que la placa Arduino va començar a executar el programa actual sense congelar-lo. Aquest número de temps es desbordarà (és a dir, tornarà a zero), al cap d’uns 50 dies aproximadament.
Igual que Arduino té delayMicroseconds (), també té la versió micro de millis () com a micros (). La diferència entre micros i millis és que els micros () es desbordaran al cap d’uns 70 minuts aproximadament, en comparació amb els millis () que són 50 dies. Per tant, segons l’aplicació podeu utilitzar millis () o micros ().
Utilitzant millis () en lloc de delay ():
Per utilitzar el milis () per a la sincronització i el retard, heu de registrar i emmagatzemar l'hora en què s'ha produït l'acció per iniciar l'hora i, a continuació, comprovar si ha passat el temps definit. Així, com s’ha dit, emmagatzemeu l’hora actual en una variable.
corrent llarg sense signar Millis = millis ();
Necessitem dues variables més per saber si ha passat el temps requerit. Hem emmagatzemat l’hora actual a la variable currentMillis , però també hem de saber que quan va començar el període de temps i quant de temps és. Per tant, es declara l’interval i l’ anterior Millis. L'interval ens indicarà el retard de temps i previosMillis emmagatzemarà l'última vegada que s'ha produït l'esdeveniment.
unsigned long previousMillis; període llarg sense signar = 1000;
Per entendre-ho, posem un exemple d’un simple LED parpellejant. El període = 1000 ens indicarà que el LED parpellejarà durant 1 segon o 1000 ms.
const int ledPin = 4; // el número de pin LED connectat int ledState = LOW; // s’utilitza per establir l’estat del LED sense signar llarg anteriorMillis = 0; // emmagatzemarà l'última vegada que el LED va parpellejar const llarg període = 1000; // període en què parpellejar en ms void setup () { pinMode (ledPin, OUTPUT); // estableix ledpin com a sortida } void loop () { unsigned long currentMillis = millis (); // emmagatzema l'hora actual si (currentMillis - previousMillis> = període) {// comproveu si 1000ms van passar anteriorMillis = currentMillis; // deseu la darrera vegada que vau parpellejar el LED si (ledState == LOW) {// si el LED està apagat, enceneu-lo i viceversa ledState = HIGH; } else { ledState = BAIX; } digitalWrite (ledPin, ledState); // estableix el LED amb ledState perquè torne a parpellejar } }
Aquí, la declaració
Les interrupcions a Arduino funcionen igual que en altres microcontroladors. La placa Arduino UNO té dos pins separats per connectar interrupcions als pins 2 i 3. GPIO. L’hem tractat amb detall al Tutorial Arduino Interrupts, on podeu obtenir més informació sobre les interrupcions i com utilitzar-les.
Aquí mostrarem Arduino Multitasking gestionant dues tasques alhora. Les tasques inclouran parpellejar dos LEDs amb un retard de temps diferent junt amb un polsador que s’utilitzarà per controlar l’estat ON / OFF del LED. Per tant, es realitzaran tres tasques simultàniament.

Components necessaris
- Arduino UNO
- Tres LEDs (qualsevol color)
- Resistències (470, 10k)
- Saltadors
- Taula de pa
Esquema de connexions
El diagrama de circuits per demostrar l'ús de la producció d' Arduino Millis () és molt fàcil i no té molts components per connectar, tal com es mostra a continuació.

Programació Arduino UNO per a la multitarea
La programació d’Arduino UNO per a la multitarea només requerirà la lògica darrere del funcionament de millis () que s’explica més amunt. Es recomana practicar LED parpellejant fent servir millis una i altra vegada per deixar clara la lògica i fer-se còmode amb millis () abans de començar a programar Arduino UNO per a la multitarea. En aquest tutorial, la interrupció també s'utilitza amb millis () simultàniament per a la multitarea. El botó serà una interrupció. Per tant, sempre que es generi una interrupció, és a dir, que es prem el botó, el LED passarà a l'estat ON o OFF.La programació comença amb la declaració dels números de pin on es connecten els LED i el botó de pulsació.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
A continuació, escrivim una variable per emmagatzemar l'estat dels LED per al seu ús futur.
int ledState1 = BAIX; int ledState2 = BAIX;
Tal com s'ha explicat anteriorment a l'exemple de parpelleig, es declara que les variables per a període i millis anteriors es comparen i generen retard per als LED. El primer LED parpelleja després de cada 1 segon i un altre LED parpelleja després de 200 ms.
sense signar llarg anteriorMillis1 = 0; const llarg període1 = 1000; unsigned long previousMillis2 = 0; const llarg període2 = 200;
S’utilitzarà una altra funció de mil·lis per generar el retard de rebutge per evitar les múltiples pulsacions del botó. Hi haurà un enfocament similar a l’anterior.
int debouncePeriod = 20; int debounceMillis = 0;
Les tres variables s'utilitzaran per emmagatzemar l'estat del polsador com a interrupció, commutació del LED i estat del polsador.
button boolushPush = false; int ledChange = BAIX; int lastState = HIGH;
Definiu l'acció del pin que el pin funcionarà com INPUT o OUTPUT.
pinMode (led1, OUTPUT); pinMode (led2, OUTPUT); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Ara definiu el pin d'interrupció adjuntant interrupt amb la definició d'ISR i Mode d'interrupció. Tingueu en compte que es recomana utilitzar digitalPinToInterrupt (pin_number) en declarar la funció attachInterrupt () per traduir el pin digital real al número d'interrupció específic.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
La subrutina d'interrupció està escrita i només canviarà el senyalador buttonPush. Tingueu en compte que, la subrutina d'interrupcions ha de ser el més curta possible, així que intenteu escriure-la i minimitzar les instruccions addicionals.
void pushButton_ISR () { buttonPush = true; }
El bucle comença per emmagatzemar el valor de millis en una variable currentMillis que emmagatzemarà el valor del temps transcorregut cada vegada que el bucle itera.
corrent llarg sense signar Millis = millis ();
Hi ha en total tres funcions en la multitarea, parpellejar un LED a 1 segon, parpellejar un segon LED a 200 ms i, si es prem el botó, apagueu el LED APAGAT / ON. Per tant, escriurem tres parts per fer aquesta tasca.
El primer consisteix a alternar l'estat del LED després de cada 1 segon comparant els mil·lis transcorreguts.
if (actualMillis - anteriorMillis1> = període1) { anteriorMillis1 = actualMillis; if (ledState1 == BAIX) { ledState1 = HIGH; } else { ledState1 = BAIX; } digitalWrite (led1, ledState1); }
De la mateixa manera, en segon lloc commuta el LED després de cada 200 ms comparant els mil·lis transcorreguts. L’explicació ja s’explica anteriorment en aquest article.
if (actualMillis - anteriorMillis2> = període2) { anteriorMillis2 = actualMillis; if (ledState2 == BAIX) { ledState2 = HIGH; } else { ledState2 = BAIX; } digitalWrite (led2, ledState2); }
Finalment, es controla la bandera buttonPush i, després de generar un retard de rebut de 20 ms, només canvia l'estat del LED corresponent al botó de connexió connectat com a interrupció.
if (buttonPushed = true) // comprova si ISR es diu { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // genera un retard de rebounce de 20 ms per evitar diverses pulsacions { debounceMillis = currentMillis; // deseu el darrer temps de retard de rebut si (digitalRead (pushButton) == LOW && lastState == HIGH) // canvieu el led després de prémer el botó { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = BAIX; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Això acaba la Millis Arduino () Tutorial. Tingueu en compte que per fer-vos habituals amb millis (), només cal que practiqueu implementar aquesta lògica en algunes altres aplicacions. També podeu ampliar-lo per utilitzar motors, servomotors, sensors i altres perifèrics. En cas de dubte, escriviu al nostre fòrum o comenteu a continuació.
A continuació es proporciona un codi complet i un vídeo per demostrar l’ús de la funció millis a Arduino.
