- Čo je to multitasking?
- Prečo preskočiť delay () v Arduine?
- Prečo používať millis ()?
- Súčasti sú povinné
- Schéma zapojenia
- Programovanie Arduino UNO pre multitasking
Multitasking viedlo počítačov k revolúcii, kde jeden alebo viac programov môže bežať súčasne, čo zvyšuje účinnosť, pružnosť, prispôsobivosť a produktivitu. Vo vstavaných systémoch môžu mikrokontroléry zvládnuť aj multitasking a vykonávať dve alebo viac úloh súčasne bez zastavenia aktuálnych pokynov.
Tu v tomto výučbe sa dozvieme, ako Arduino vykonáva multitasking s funkciou Arduino millis. Všeobecne sa v Arduine používa funkcia delay () na periodické úlohy, ako je blikanie LED, ale táto funkcia delay () zastaví program na určitý definitívny čas a neumožní vykonávanie ďalších operácií. Tento článok teda vysvetľuje, ako sa môžeme vyhnúť použitiu funkcie delay () a nahradiť ju millis (), aby sme mohli vykonávať viac ako jednu úlohu súčasne a urobiť z Arduina radič pre viac úloh. Predtým, ako sa pustíme do podrobností, začnime s podceňovaním Multitaskingu.
Čo je to multitasking?
Multitasking jednoducho znamená vykonávanie viacerých úloh alebo programov súčasne. Takmer všetky operačné systémy obsahujú multitasking. Tento druh operačných systémov je známy ako MOS (multitasking operating system). MOS môže byť mobilný alebo stolný operačný systém pre PC. Dobrým príkladom multitaskingu v počítačoch je, keď používatelia súčasne spúšťajú e-mailovú aplikáciu, internetový prehliadač, prehrávač médií, hry a ak používatelia aplikáciu nechcú používať, sú spustené na pozadí, ak nie sú zatvorené. Koncový používateľ používa všetky tieto aplikácie súčasne, ale OS berie tento koncept trochu inak. Poďme diskutovať o tom, ako OS zvláda multitasking.
Ako je vidieť na obrázku, CPU rozdelí čas na tri rovnaké časti a každej časti priradí každú úlohu / aplikáciu. Takto sa vykonáva multitasking vo väčšine systémov. Koncept bude pre Arduino Multitasking takmer rovnaký, až na to, že časové rozdelenie bude trochu iné. Pretože Arduino beží na nízkej frekvencii a RAM v porovnaní s notebookom / mobilným telefónom / počítačom, tak aj čas venovaný jednotlivým úlohám bude iný. Arduino má tiež funkciu delay (), ktorá sa často používa. Pred začatím si ale prediskutujme, prečo by sme v žiadnom projekte nemali používať funkciu delay () .
Prečo preskočiť delay () v Arduine?
Ak sa vezme do úvahy referenčná dokumentácia Arduina, potom existujú dva typy funkcií oneskorenia, prvý je delay () a druhý je delayMicroseconds (). Obe funkcie sú z hľadiska generovania oneskorenia identické. Rozdiel je iba v tom, že vo funkcii delay () je odovzdané celé číslo parametra v milisekundách, tj. Ak napíšeme oneskorenie (1000), potom bude oneskorenie 1 000 milisekúnd, tj 1 sekunda. Podobne vo funkcii delayMicroseconds () je odovzdaný parameter v mikrosekundách, tj. Ak napíšeme delayMicroseconds (1000), potom bude oneskorenie 1 000 mikrosekúnd, tj 1 milisekunda.
Tu nastáva bod, obe funkcie pozastavia program na dobu uplynutú vo funkcii oneskorenia. Takže ak dáme oneskorenie 1 s, potom procesor nemôže prejsť na ďalšiu inštrukciu, kým neuplynie 1 s. Podobne, ak je oneskorenie 10 sekúnd, program sa na 10 sekúnd zastaví a procesor nedovolí prejsť na ďalšie pokyny, kým neuplynie 10 sekúnd. To brzdí výkon mikrokontroléra, pokiaľ ide o rýchlosť a vykonávanie pokynov.
Najlepším príkladom na vysvetlenie nevýhody funkcie oneskorenia je použitie dvoch tlačidiel. Zvážte, že chceme prepnúť dve LED pomocou dvoch tlačidiel. Takže ak je stlačené jedno tlačidlo, potom by mala zodpovedajúca LED svietiť na 2 sekundy, podobne ak je stlačené druhé, potom by LED mala svietiť na 4 sekundy. Ale keď použijeme delay (), ak používateľ stlačí prvé tlačidlo, program sa zastaví na 2 sekundy a ak užívateľ stlačí druhé tlačidlo pred oneskorením 2 sekundy, mikrokontrolér neakceptuje vstup, pretože program je v zastavenom stave.
Oficiálna dokumentácia Arduina to jasne uvádza v popise funkcie Notes and Warnings of delay (). Môžete to skontrolovať a skontrolovať to, aby bolo jasnejšie.
Prečo používať millis ()?
Na prekonanie problému spôsobeného použitím oneskorenia by mal vývojár použiť funkciu millis (), ktorá sa ľahko použije, keď si zvyknete a použije 100% výkon procesora bez toho, aby pri vykonávaní pokynov generovala akékoľvek oneskorenie. millis () je funkcia, ktorá vráti iba počet milisekúnd, ktoré uplynuli od chvíle, keď doska Arduino spustila aktuálny program bez zmrazenia programu. Toto časové číslo pretečie (tj sa vráti na nulu) asi po 50 dňoch.
Rovnako ako Arduino má delayMicroseconds (), má aj mikro verziu millis () ako micro (). Rozdiel medzi mikro a millis je v tom, že mikro () pretečie po približne 70 minútach v porovnaní s millis (), čo je 50 dní. Takže v závislosti od aplikácie môžete použiť millis () alebo micros ().
Použitie millis () namiesto delay ():
Ak chcete použiť millis () na načasovanie a oneskorenie, musíte zaznamenať a uložiť čas, v ktorom sa akcia uskutočnila, aby sa spustil čas, a potom v intervaloch kontrolovať, či uplynul definovaný čas. Ako je uvedené, uložte aktuálny čas do premennej.
nepodpísaný dlhý prúd Millis = millis ();
Potrebujeme ďalšie dve premenné, aby sme zistili, či uplynul požadovaný čas. Aktuálny čas sme uložili do premennej currentMillis, potrebujeme však tiež vedieť, kedy a ako dlho začalo časové obdobie. Deklaruje sa teda Interval a previousMillis . Interval nám oznámi časové oneskorenie a previosMillis uloží poslednýkrát, kedy k udalosti došlo.
nepodpísaný dlhý predchádzajúciMillis; nepodpísané dlhé obdobie = 1000;
Aby sme to pochopili, vezmime si príklad jednoduchej blikajúcej LED. Perióda = 1 000 nám oznámi, že LED bude blikať po dobu 1 sekundy alebo 1 000 ms.
const int ledPin = 4; // číslo PIN LED pripojené int ledState = LOW; // slúži na nastavenie stavu LED bez znamenia long previousMillis = 0; // uloží naposledy LED dióda bliká konštantne dlho = 1000; // perióda, kedy bude blikať v ms void setup () { pinMode (ledPin, OUTPUT); // nastaviť ledpin ako výstup } void loop () { unsigned long currentMillis = millis (); // uložiť aktuálny čas if (currentMillis - previousMillis> = obdobie) {// skontrolovať, či uplynulo 1 000 ms previousMillis = currentMillis; // uložte, kedy ste naposledy blikli LED, ak (ledState == LOW) {// ak LED nesvieti, zapnite ju a naopak ledState = HIGH; } else { ledState = LOW; } digitalWrite (ledPin, ledState); // nastavenie LED s ledState na ďalšie blikanie } }
Tu vyhlásenie
Prerušenia v Arduine fungujú rovnako ako v iných mikrokontroléroch. Doska Arduino UNO má dva samostatné kolíky na pripojenie prerušenia na pin GPIO 2 a 3. Podrobne sme sa jej venovali v príručke Arduino Interrupts Tutorial, kde sa dozviete viac o prerušeniach a o tom, ako ich používať.
Tu si ukážeme multitasking Arduina spracovaním dvoch úloh naraz. Medzi úlohy bude patriť blikanie dvoch LED diód v rôznom časovom oneskorení spolu s tlačidlom, ktoré sa použije na ovládanie stavu LED zapnutia / vypnutia. Budú sa teda vykonávať tri úlohy súčasne.
Súčasti sú povinné
- Arduino UNO
- Tri LED diódy (ľubovoľná farba)
- Odpory (470, 10k)
- Skokani
- Nepál
Schéma zapojenia
Schéma zapojenia demonštrujúce použitie funkcie Arduino Millis () je veľmi jednoduchá a nemá veľa komponentov na pripevnenie, ako je uvedené nižšie.
Programovanie Arduino UNO pre multitasking
Programovanie Arduino UNO pre multitasking bude vyžadovať iba logiku fungovania millis (), ktorá je vysvetlená vyššie. Pred začatím programovania Arduino UNO pre multitasking sa odporúča opakované precvičovanie blikania LED pomocou millis, aby bola logika jasná a aby ste sa cítili pohodlne s millis (). V tomto výučbe sa prerušenie používa aj s millis () súčasne na multitasking. Tlačidlo bude prerušením. Takže kedykoľvek sa vygeneruje prerušenie, tj. Stlačíte tlačidlo, LED sa prepne do stavu ZAPNUTÉ alebo VYPNUTÉ.Programovanie začína vyhlásením čísel pinov, kde sú pripojené LED diódy a tlačidlo.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
Ďalej napíšeme premennú na uloženie stavu LED diód pre ďalšie použitie.
int ledState1 = LOW; int ledState2 = LOW;
Ako je vysvetlené vyššie v príklade blikania, premenné periódy a predošlých rokov sa deklarujú na porovnanie a generovanie oneskorenia pre LED. Prvá LED dióda bliká po každej 1 sekunde a ďalšia LED bliká po 200 ms.
bez znamienka dlho previousMillis1 = 0; konštantné dlhé obdobie1 = 1 000; bez znamienka dlho previousMillis2 = 0; konštantné dlhé obdobie2 = 200;
Na vygenerovanie oneskorenia odskoku bude použitá ďalšia funkcia millis, aby sa zabránilo opakovanému stlačeniu tlačidla. Bude existovať podobný prístup ako vyššie.
int debouncePeriod = 20; int debounceMillis = 0;
Tieto tri premenné sa použijú na uloženie stavu tlačidla ako prerušenia, prepínania LED a stavu tlačidla.
bool buttonPushed = false; int ledChange = LOW; int lastState = HIGH;
Definujte činnosť špendlíka, ktorý bude fungovať ako VSTUP alebo VÝSTUP.
pinMode (led1, VÝSTUP); pinMode (led2, VÝSTUP); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Teraz definujte prerušovací kolík pripojením prerušenia s definíciou ISR a režimu prerušenia. Upozorňujeme, že pri deklarovaní funkcie attachInterrupt () na preklad skutočného digitálneho kolíka na konkrétne číslo prerušenia sa odporúča použiť digitalPinToInterrupt (pin_number) .
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Je napísaný prerušovací podprogram a zmení sa iba príznak buttonPushed. Upozorňujeme, že prerušovací podprogram by mal byť čo najkratší, takže sa ho pokúste napísať a minimalizujte ďalšie pokyny.
void pushButton_ISR () { buttonPush = true; }
Smyčka začína uložením hodnoty millis do premennej currentMillis, ktorá uloží hodnotu času uplynulého pri každej iterácii slučky.
nepodpísaný dlhý prúd Millis = millis ();
V multitaskingu sú celkovo tri funkcie, blikanie jednej LED na 1 sekundu, blikanie druhej LED na 200ms a po stlačení tlačidla potom vypnúť / zapnúť LED. Na vykonanie tejto úlohy teda napíšeme tri časti.
Prvý sa prepína LED stav po každom 1 sekundu porovnaním Millis uplynulo.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }
Podobne ako druhé prepína LED po každých 200 ms porovnaním uplynulých milis. Vysvetlenie je už vysvetlené vyššie v tomto článku.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }
V neposlednom rade je buttonPushed vlajka je monitorovaný a po generovanie vstupné oneskorenie o 20ms to len prepína stav LED zodpovedá tlačidle, pripojené ako prerušenia.
if (buttonPushed = true) // skontrolovať, či sa volá ISR { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // vygenerovať oneskorenie 20 ms odskoku, aby sa zabránilo opakovanému stlačeniu { debounceMillis = currentMillis; // uložte čas oneskorenia posledného debounce if (digitalRead (pushButton) == LOW && lastState == HIGH) // zmeniť led po stlačení tlačidla { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Týmto je ukončená výučba Arduino millis (). Všimnite si, že aby ste si zvykli na millis (), stačí si vyskúšať implementáciu tejto logiky v niektorých ďalších aplikáciách. Môžete ho tiež rozšíriť o motory, servomotory, snímače a ďalšie periférie. V prípade akýchkoľvek pochybností napíšte na naše fórum alebo komentár nižšie.
Kompletný kód a video na demonštráciu použitia funkcie millis v Arduine sú uvedené nižšie.