- Kaj je večopravilnost?
- Zakaj preskočiti zamudo () v Arduinu?
- Zakaj uporabljati milis ()?
- Potrebne komponente
- Shema vezja
- Programiranje Arduino UNO za večopravilnost
Večopravilnost je vodil računalnike do revolucije, kjer lahko enega ali več programov teči hkrati, kar poveča učinkovitost, fleksibilnost, prilagodljivost in produktivnost. V vdelanih sistemih lahko mikrokrmilniki upravljajo tudi večopravilnost in hkrati izvajajo dve ali več nalog, ne da bi ustavili trenutna navodila.
V tej vadnici bomo izvedeli, kako Arduino izvaja večopravilnost s funkcijo Arduino millis. Na splošno zamudo () je funkcija uporabljena v Arduino periodične naloge, kot so LED utripati, vendar ta zamuda () funkcija ustavitve programa za nekaj dokončnega časa in ne dovolijo drugi postopki za izvedbo. V tem članku je razloženo, kako se lahko izognemo uporabi funkcije delay () in jo nadomestimo z milisami (), da hkrati izvajamo več nalog in Arduino naredimo za večopravilnost. Preden se spustimo v podrobnosti, začnimo s podcenjevanjem večopravilnosti.
Kaj je večopravilnost?
Večopravilnost pomeni preprosto izvajanje več nalog ali programov hkrati. Skoraj vsi operacijski sistemi imajo večopravilnost. Tovrstni operacijski sistemi so znani kot MOS (večopravilni operacijski sistem). MOS je lahko operacijski sistem za prenosni ali namizni računalnik. Dober primer večopravilnosti v računalnikih je, ko uporabniki hkrati zaženejo e-poštno aplikacijo, internetni brskalnik, predvajalnik medijev, igre in če uporabniki ne želijo uporabljati aplikacije, se ta izvaja v ozadju, če ni zaprta. Končni uporabnik uporablja vse te aplikacije hkrati, vendar OS jemlje ta koncept nekoliko drugače. Pogovorimo se o tem, kako OS upravlja večopravilnost.
Kot je razvidno iz slike, CPU čas deli na tri enake dele in vsak del dodeli vsaki nalogi / aplikaciji. Tako poteka večopravilnost v večini sistemov. Koncept bo skoraj enak za Arduino Multitasking, le da bo časovna razporeditev nekoliko drugačna. Ker Arduino deluje z nizko frekvenco in RAM-om se primerja s prenosnikom / prenosnikom / osebnim računalnikom, bo tudi čas, namenjen vsaki nalogi, drugačen. Arduino ima tudi funkcijo delay (), ki se pogosto uporablja. Toda preden začnemo, se pogovorimo o tem, zakaj v nobenem projektu ne bi smeli uporabljati funkcije delay () .
Zakaj preskočiti zamudo () v Arduinu?
Če upoštevamo referenčno dokumentacijo Arduina, potem obstajata dve vrsti funkcij zakasnitve, prva je delay () in druga delayMicroseconds (). Obe funkciji sta enaki glede generiranja zamude. Edina razlika je v tem, da je v funkciji delay () celo število parametra posredovano v milisekundah, tj. Če napišemo delay (1000), bo zakasnitev 1000 milisekund, tj. 1 sekundo. Podobno pri funkciji delayMicroseconds () je tudi parameter poslan v mikrosekundah, tj. Če napišemo delayMicroseconds (1000), bo zakasnitev 1000 mikrosekund, tj. 1 milisekund.
Tu pride bistvo, da obe funkciji zaustavita program za čas, ki je minil v funkciji zakasnitve. Torej, če dajemo zamudo 1 sekundo, potem procesor ne more preiti na naslednje navodilo, dokler ne mine 1 sekunda. Če je zamuda 10 sekund, se program ustavi za 10 sekund, procesor pa ne bo mogel nadaljevati z naslednjimi navodili, dokler ne mine 10 sekund. To ovira delovanje mikrokrmilnika v smislu hitrosti in izvrševanja navodil.
Najboljši primer za razlago pomanjkljivosti funkcije zakasnitve je uporaba dveh tipk. Razmislite, da želimo z dvema gumboma preklopiti dve LED. Torej, če pritisnete en gumb, potem mora ustrezna LED svetiti 2 sekundi, podobno, če pritisnete drugo, mora LED sveteti 4 sekunde. Ko pa uporabimo delay (), če uporabnik pritisne prvi gumb, se program ustavi za 2 sekundi in če uporabnik pritisne drugi gumb pred 2 sekundnim zamikom, potem mikrokrmilnik ne bo sprejel vnosa, kot je program v fazi zaustavitve.
Uradna dokumentacija Arduina to jasno omenja v opisu funkcije Notes in Warnings of delay (). To lahko preverite, da bo bolj jasno.
Zakaj uporabljati milis ()?
Če želite premagati težavo zaradi zakasnitve, mora razvijalec uporabiti funkcijo milis (), ki je enostavna za uporabo, ko postanete običajna, in bo uporabila 100-odstotno zmogljivost procesorja, ne da bi povzročila kakršno koli zamudo pri izvajanju navodil. millis () je funkcija, ki samo vrne količino milisekund, ki je pretekla, odkar je plošča Arduino začela izvajati trenutni program, ne da bi program zamrznila. Ta časovna številka se bo po približno 50 dneh prelila (tj. Vrnila na nič).
Tako kot ima Arduino delayMicroseconds (), ima tudi mikro različico millis () kot micros (). Razlika med mikro in milis je v tem, da se mikro () prelije po približno 70 minutah v primerjavi z milis (), ki je 50 dni. Torej, odvisno od aplikacije, lahko uporabite milis () ali mikro ().
Uporaba milise () namesto zakasnitve ():
Če želite milis () uporabiti za merjenje časa in zakasnitve, morate zabeležiti in shraniti čas, v katerem se je dejanje odvijalo, da začnete čas in nato v presledkih preverite, ali je določeni čas potekel. Kot rečeno, trenutni čas shranite v spremenljivko.
nepodpisan dolgi tokMillis = milis ();
Potrebujemo še dve spremenljivki, da ugotovimo, ali je potekel potrebni čas. Trenutni čas smo shranili v spremenljivko currentMillis, vendar moramo vedeti tudi, kdaj se je začelo časovno obdobje in kako dolgo je obdobje. Tako je razglašen Interval in previousMillis . Interval nam bo povedal časovno zakasnitev, in previosMillis bo shranil zadnjič, ko se je dogodek zgodil.
unsigned long previousMillis; nepodpisano dolgo obdobje = 1000;
Da bi to razumeli, vzemimo primer preproste utripajoče LED. Obdobje = 1000 nam bo povedalo, da bo LED utripala 1 sekundo ali 1000 ms.
const int ledPin = 4; // priključena številka LED-diode int ledState = LOW; // uporablja se za nastavitev stanja LED brez podpisa long longMillis = 0; // bo shranil zadnjič, ko je LED utripala const long period = 1000; // obdobje, v katerem naj utripa v ms void setup () { pinMode (ledPin, OUTPUT); // nastavimo ledpin kot izhod } void loop () { unsigned long currentMillis = millis (); // shranimo trenutni čas if (currentMillis - previousMillis> = period) {// preverimo, ali je 1000ms preteklo previousMillis = currentMillis; // shranimo zadnjič, ko ste utripali LED, če (ledState == LOW) {// če LED ne sveti, jo vklopite in obratno ledState = HIGH; } else { ledState = LOW; } digitalWrite (ledPin, ledState); // nastavimo, da LED z ledState ponovno utripa } }
Tukaj, izjava
Prekinitve v Arduinu delujejo enako kot pri drugih mikrokrmilnikih. Tabla Arduino UNO ima dva ločena nožica za pritrditev prekinitev na GPIO nožici 2 in 3. Podrobno smo jo obdelali v Vadnici za prekinitve Arduino, kjer lahko izveste več o prekinitvah in kako jih uporabljati.
Tu bomo prikazali večopravilnost Arduino z istočasno obdelavo dveh nalog. Naloge bodo vključevale utripanje dveh LED v različnih časovnih zamikih, skupaj s pritiskom na gumb, ki bo uporabljen za nadzor stanja vklopa / izklopa LED. Torej se bodo hkrati izvajale tri naloge.
Potrebne komponente
- Arduino UNO
- Tri LED (poljubne barve)
- Upori (470, 10k)
- Skakalci
- Breadboard
Shema vezja
Shema vezij za prikaz uporabe fukcije Arduino Millis () je zelo enostavna in nima veliko komponent za pritrditev, kot je prikazano spodaj.
Programiranje Arduino UNO za večopravilnost
Programiranje Arduino UNO za večopravilnost bo zahtevalo le logiko delovanja milisa (), ki je pojasnjena zgoraj. Preden začnete programirati Arduino UNO za večopravilnost, priporočamo, da z milisami znova in znova vadite utripajočo LED z milisami . V tej vadnici se prekinitev hkrati uporablja tudi z milis () za večopravilnost. Gumb bo prekinil. Torej, kadar koli se ustvari prekinitev, tj. Pritisne gumb, se LED preklopi v stanje ON ali OFF.Programiranje se začne z navedbo številk zatičev, kjer so priključene LED in tipka.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
Nato napišemo spremenljivko za shranjevanje stanja LED za prihodnjo uporabo.
int ledState1 = LOW; int ledState2 = LOW;
Kot je razloženo zgoraj v primeru utripanja, je spremenljivka za obdobje in prejšnje milise razglašena za primerjavo in ustvarjanje zamude za LED. Prva LED utripa po vsaki 1 sekundi, druga LED pa utripa po 200 ms.
nepodpisano dolgo previousMillis1 = 0; const dolgo obdobje1 = 1000; nepodpisano dolgo previousMillis2 = 0; const dolgo obdobje2 = 200;
Za ustvarjanje zakasnitve izklopa se bo uporabila še ena miliserska funkcija, da se izognemo večkratnim pritiskom na tipko. Pristop bo podoben kot zgoraj.
int debouncePeriod = 20; int debounceMillis = 0;
Za tri spremenljivke se uporablja za shranjevanje status pritiskom na gumb, kot je prekinitev, preklop LED in tipkala stanju.
bool buttonPushed = false; int ledChange = LOW; int lastState = VISOKO;
Določite delovanje zatiča, kateri zatič bo deloval kot VHOD ali IZHOD.
pinMode (led1, IZHOD); pinMode (led2, IZHOD); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Zdaj definirajte prekinitveni zatič tako, da pritrdite prekinitev z definicijo ISR in način prekinitve. Upoštevajte, da je za deklariranje funkcije attachInterrupt () priporočljivo uporabiti digitalPinToInterrupt (pin_number) za prevajanje dejanskega digitalnega pin-a na določeno številko prekinitve.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Podprogram prekinitve je zapisan in spremenil bo samo zastavico buttonPushed. Upoštevajte, da mora biti prekinitveni podprogram čim krajši, zato ga poskusite napisati in zmanjšati dodatna navodila.
void pushButton_ISR () { buttonPushed = true; }
Loop se začne s shranjevanjem vrednosti milis v spremenljivko currentMillis, ki bo shranila vrednost pretečenega časa vsakič, ko se zanka ponovi.
nepodpisan dolgi tokMillis = milis ();
V večopravilnosti so skupno tri funkcije, utripajte eno LED v 1 sekundi, utripajte drugo LED v 200 ms in če pritisnete gumb, nato izklopite / vklopite LED. Torej bomo za to nalogo napisali tri dele.
Prvi je preklaplja LED stanje po vsaki 1 sekundo s primerjavo milisekundah minilo.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; če (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }
Podobno drugič preklopi LED po vsakih 200 ms s primerjavo pretečenih milisov. Razlaga je že pojasnjena v tem članku.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; če (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }
Nazadnje je buttonPushed se zastave spremljajo in po ustvarjajo debounce zakasnitev 20ms to samo preklaplja stanje LED sklada z pritiskom na gumb, ki je kot prekinitev.
if (buttonPushed = true) // preverimo, ali se ISR prikliče { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // ustvari 20ms zakasnitve debounce, da se izognemo večkratnim pritiskom { debounceMillis = currentMillis; // shranimo zadnji čas zakasnitve izklopa, če (digitalRead (pushButton) == LOW && lastState == HIGH) // spremenimo led po pritisku na gumb { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } sicer če (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
S tem je končana vadnica za Arduino millis (). Upoštevajte, da če želite postati običajno z milisami (), samo vadite to logiko v nekaterih drugih aplikacijah. Lahko ga razširite tudi tako, da uporablja motorje, servo motorje, senzorje in drugo zunanjo opremo. V primeru kakršnega koli dvoma pišite na naš forum ali komentirajte spodaj.
Popolna koda in video za predstavitev uporabe funkcije milis v Arduinu sta navedena spodaj.