- Co je to multitasking?
- Proč přeskočit delay () v Arduinu?
- Proč používat millis ()?
- Požadované komponenty
- Kruhový diagram
- Programování Arduino UNO pro multitasking
Multitasking vedlo počítačů k revoluci, kde jeden nebo více programů může běžet současně, což zvyšuje účinnost, pružnost, přizpůsobivost a produktivitu. V integrovaných systémech mohou mikrokontroléry zpracovávat také multitasking a provádět dva nebo více úkolů současně, aniž by zastavily aktuální pokyny.
Tady v tomto tutoriálu se naučíme, jak Arduino provádí multitasking s funkcí Arduino millis. Obecně se v Arduinu používá funkce delay () pro periodický úkol, jako je blikání LED, ale tato funkce delay () zastaví program na nějaký definitivní čas a nedovolí provádět jiné operace. Tento článek tedy vysvětluje, jak se můžeme vyhnout použití funkce delay () a nahradit ji millis (), abychom mohli provádět více než jeden úkol současně a udělat z Arduina řadič Multitasking. Než se pustíme do podrobností, začneme s podhodnocením Multitaskingu.
Co je to multitasking?
Multitasking jednoduše znamená vykonávat více než jeden úkol nebo program současně. Téměř všechny operační systémy mají multitasking. Tento druh operačních systémů se označuje jako MOS (multitasking operating system). MOS může být mobilní nebo stolní počítač s operačním systémem. Dobrým příkladem multitaskingu v počítačích je, když uživatelé současně spouští e-mailovou aplikaci, internetový prohlížeč, přehrávač médií, hry a pokud uživatelé nechtějí aplikaci používat, běží na pozadí, pokud nejsou zavřeni. Koncový uživatel používá všechny tyto aplikace současně, ale OS bere tento koncept trochu jinak. Pojďme diskutovat o tom, jak OS zvládá multitasking.
Jak je vidět na obrázku, CPU rozdělí čas na tři stejné části a přiřadí každou část každé úloze / aplikaci. Takto se multitasking provádí ve většině systémů. Koncept bude pro Arduino Multitasking téměř stejný, až na to, že časové rozdělení bude trochu jiné. Vzhledem k tomu, že Arduino běží na nízké frekvenci a RAM ve srovnání s notebookem / mobilem / PC, bude se čas věnovaný každému úkolu také lišit. Arduino má také funkci delay (), která je široce používána. Ale před začátkem pojďme diskutovat o tom, proč bychom v žádném projektu neměli používat funkci delay () .
Proč přeskočit delay () v Arduinu?
Pokud vezmeme v úvahu referenční dokumentaci Arduina, pak existují dva typy zpožďovacích funkcí, první je delay () a druhá je delayMicroseconds (). Obě funkce jsou identické z hlediska generování zpoždění. Jediný rozdíl je v tom, že ve funkci delay () je předané celé číslo parametru v milisekundách, tj. Pokud napíšeme delay (1000), pak bude zpoždění 1000 milisekund, tj. 1 sekundu. Podobně ve funkci delayMicroseconds () je předávaný parametr v mikrosekundách, tj. Pokud napíšeme delayMicroseconds (1000), pak bude zpoždění 1000 mikrosekund, tj. 1 milisekundu.
Zde přichází bod, obě funkce pozastaví program na dobu, která uběhla ve funkci zpoždění. Pokud tedy dáváme zpoždění 1 sekundu, procesor nemůže přejít na další instrukci, dokud neuplyne 1 sekunda. Podobně, pokud je zpoždění 10 sekund, program se na 10 sekund zastaví a procesor nedovolí přejít na další pokyny, dokud neuplyne 10 sekund. To omezuje výkon mikrokontroléru z hlediska rychlosti a provádění pokynů.
Nejlepším příkladem vysvětlujícím nevýhodu funkce zpoždění je použití dvou tlačítek. Zvažte, že chceme přepínat dvě LED pomocí dvou tlačítek. Pokud je tedy stisknuto jedno tlačítko, měla by příslušná LED svítit po dobu 2 sekund, podobně je-li stisknuto druhé, měla by LED svítit po dobu 4 sekund. Ale když použijeme delay (), pokud uživatel stiskne první tlačítko, program se zastaví na 2 sekundy a pokud uživatel stiskne druhé tlačítko před 2 sekundovým zpožděním, mikrokontrolér nepřijme vstup, protože program je ve zastavené fázi.
Oficiální dokumentace Arduina to jasně zmiňuje v popisu funkce Poznámky a varování zpoždění (). Můžete to projít a zkontrolovat, aby to bylo jasnější.
Proč používat millis ()?
K překonání problému způsobeného použitím zpoždění by měl vývojář použít funkci millis (), která se snadno použije, jakmile si zvyknete, a použije 100% výkon CPU, aniž by generovala jakékoli zpoždění při provádění pokynů. millis () je funkce, která pouze vrací počet milisekund, které uplynuly od doby, kdy deska Arduino začala spouštět aktuální program bez zmrazení programu. Toto časové číslo přeteče (tj. Vrátí se na nulu) přibližně po 50 dnech.
Stejně jako Arduino má delayMicroseconds (), má také mikro verzi millis () jako micro (). Rozdíl mezi mikro a millis spočívá v tom, že micro () přeteče po přibližně 70 minutách, ve srovnání s millis (), což je 50 dní. Takže v závislosti na aplikaci můžete použít millis () nebo micros ().
Použití millis () namísto delay ():
Chcete-li použít millis () pro načasování a zpoždění, musíte zaznamenat a uložit čas, kdy se akce uskutečnila, aby se spustil čas, a poté v intervalech kontrolovat, zda uplynul definovaný čas. Jak je uvedeno, uložte aktuální čas do proměnné.
nepodepsaný dlouhý proud Millis = millis ();
Potřebujeme další dvě proměnné, abychom zjistili, zda uplynul požadovaný čas. Uložili jsme aktuální čas do proměnné currentMillis, ale také potřebujeme vědět, že kdy začalo časové období a jak dlouhé je období. Takže je deklarován Interval a previousMillis . Interval nám sdělí časové zpoždění a previosMillis uloží poslední čas, kdy k události došlo.
nepodepsaný dlouhý předchozí Millis; dlouhé období bez znaménka = 1000;
Abychom tomu porozuměli, vezměme si příklad jednoduché blikající LED. Perioda = 1000 nám řekne, že LED bude blikat po dobu 1 sekundy nebo 1 000 ms.
const int ledPin = 4; // číslo PIN LED připojeno int ledState = LOW; // slouží k nastavení stavu LED bez znaménka long previousMillis = 0; // uloží naposledy LED dioda bliká const long period = 1000; // období, ve kterém bude blikat v ms void setup () { pinMode (ledPin, OUTPUT); // nastavit ledpin jako výstup } void loop () { unsigned long currentMillis = millis (); // uloží aktuální čas if (currentMillis - previousMillis> = perioda) {// zkontroluje, zda předalo 1 000 ms previousMillis = currentMillis; // uložení posledního bliknutí LED, pokud (ledState == LOW) {// pokud LED zhasne, zapněte ji a naopak ledState = HIGH; } else { ledState = LOW; } digitalWrite (ledPin, ledState); // nastaví LED s ledState na opětovné blikání } }
Tady prohlášení
Přerušení v Arduinu funguje stejně jako v jiných mikrokontrolérech. Deska Arduino UNO má dva samostatné piny pro připojení přerušení na pin GPIO 2 a 3. Podrobně jsme ji popsali v výukovém programu Arduino Interrupts, kde se můžete dozvědět více o přerušeních a jejich použití.
Zde si ukážeme multitasking Arduina zpracováním dvou úkolů současně. Mezi úkoly bude patřit blikání dvou LED diod v různém časovém zpoždění spolu s tlačítkem, kterým se bude ovládat stav zapnutí / vypnutí LED diod. Budou tedy provedeny tři úkoly současně.
Požadované komponenty
- Arduino UNO
- Tři LED diody (libovolná barva)
- Odpory (470, 10k)
- Svetry
- Nepájivá deska
Kruhový diagram
Schéma zapojení pro demonstraci použití funkce Arduino Millis () je velmi snadné a nemá příliš mnoho komponent k připojení, jak je znázorněno níže.
Programování Arduino UNO pro multitasking
Programování Arduino UNO pro multitasking bude vyžadovat pouze logiku fungování millis (), která je vysvětlena výše. Před zahájením programování Arduino UNO pro multitasking se doporučuje opakované procvičování blikání LED pomocí millis, aby byla logika jasná a aby vám bylo dobře millis (). V tomto kurzu se přerušení také používá s millis () současně pro multitasking. Tlačítko bude přerušeno. Takže kdykoli je generováno přerušení, tj. Stisknutí tlačítka, LED se přepne do stavu ZAPNUTO nebo VYPNUTO.Programování začíná deklarováním čísel pinů, kde jsou připojeny LED a tlačítko.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
Dále napíšeme proměnnou pro uložení stavu LED pro budoucí použití.
int ledState1 = LOW; int ledState2 = LOW;
Jak je vysvětleno výše v příkladu blikání, proměnné pro období a předchozí milimetr jsou deklarovány pro srovnání a generování zpoždění pro LED. První LED bliká každou 1 sekundu a další LED bliká po 200 ms.
bez znaménka long previousMillis1 = 0; const dlouhé období1 = 1000; bez znaménka long previousMillis2 = 0; const dlouhé období2 = 200;
K vygenerování zpoždění odskoku se použije další funkce millis, aby se zabránilo opakovanému stisknutí tlačítka. Bude existovat podobný přístup jako výše.
int debouncePeriod = 20; int debounceMillis = 0;
Tyto tři proměnné se použijí k uložení stavu tlačítka jako přerušení, přepínací LED a stavu tlačítka.
bool buttonPushed = false; int ledChange = LOW; int lastState = HIGH;
Definujte akci kolíku, který bude fungovat jako VSTUP nebo VÝSTUP.
pinMode (led1, VÝSTUP); pinMode (led2, VÝSTUP); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Nyní definujte přerušovací kolík připojením přerušení s definicí ISR a režimu přerušení. Všimněte si, že při deklaraci funkce attachInterrupt () se doporučuje použít digitalPinToInterrupt (pin_number) k překladu skutečného digitálního kolíku na konkrétní číslo přerušení.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Podprogram přerušení je zapsán a změní pouze příznak buttonPushed. Pamatujte si, že přerušovací podprogram by měl být co nejkratší, zkuste jej tedy napsat a minimalizujte další pokyny.
void pushButton_ISR () { buttonPush = true; }
Smyčka začíná uložením hodnoty millis do proměnné currentMillis, která uloží hodnotu uplynulého času pokaždé, když smyčka iteruje.
nepodepsaný dlouhý proud Millis = millis ();
V multitaskingu jsou celkem tři funkce, blikat jednu LED na 1 sekundu, blikat druhá LED na 200ms a Pokud je stisknuto tlačítko, pak vypnout / zapnout LED. K provedení tohoto úkolu tedy napíšeme tři části.
První se přepíná LED stav po každém 1 sekundu porovnáním Millis uplynulo.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }
Podobně za druhé přepíná LED po každých 200 ms porovnáním uplynulých milisekund. Vysvětlení je již vysvětleno dříve v tomto článku.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }
V neposlední řadě je buttonPushed vlajka je monitorován a po generování vstupní zpoždění o 20ms to jen přepíná stav LED odpovídá tlačítku, připojené jako přerušení.
if (buttonPushed = true) // zkontrolovat, zda se volá ISR { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // vygenerovat 20ms zpoždění odskoku, aby nedocházelo k opakovaným stiskům { debounceMillis = currentMillis; // uložit poslední zpoždění debounce if (digitalRead (pushButton) == LOW && lastState == HIGH) // změnit LED po stisknutí tlačítka { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Tím je ukončena výuka Arduino millis (). Všimněte si, že za účelem získání zvyku s millis () si jen procvičte implementaci této logiky v některých dalších aplikacích. Můžete jej také rozšířit o použití motorů, servomotorů, senzorů a dalších periferií. V případě jakýchkoli pochybností napište na naše fórum nebo komentář níže.
Níže je uveden kompletní kód a video pro demonstraci použití funkce millis v Arduinu.