wielozadaniowość doprowadziła komputery do rewolucji, w której jeden lub więcej programów może działać jednocześnie, co zwiększa wydajność, elastyczność, zdolność adaptacji i produktywność. W systemach wbudowanych mikrokontrolery mogą również obsługiwać wielozadaniowość i wykonywać dwa lub więcej zadań jednocześnie bez zatrzymywania bieżących instrukcji.

tutaj w tym samouczku dowiemy się, jak Arduino wykonuje wielozadaniowość z funkcją Arduino Milis. Zazwyczaj funkcja delay () jest używana w Arduino do okresowych zadań, takich jak miganie diod LED, ale ta funkcja delay() zatrzymuje program na jakiś ostateczny czas i nie pozwala na wykonywanie innych operacji. W tym artykule wyjaśniono, w jaki sposób możemy uniknąć użycia funkcji delay() i zastąpić ją funkcją millis (), aby wykonywać więcej niż jedno zadanie jednocześnie i uczynić Arduino kontrolerem wielozadaniowym. Zanim przejdziemy do szczegółów, zacznijmy od zaniżania wielozadaniowości.

Co To jest wielozadaniowość?

Wielozadaniowość oznacza po prostu wykonywanie więcej niż jednego zadania lub programu jednocześnie. Prawie wszystkie systemy operacyjne posiadają wielozadaniowość. Tego rodzaju systemy operacyjne są znane jako Mos (wielozadaniowy system operacyjny). MOS może być mobilnym lub stacjonarnym systemem operacyjnym PC. Dobrym przykładem wielozadaniowości w komputerach są, gdy użytkownicy uruchamiają aplikację e-mail, przeglądarkę internetową, odtwarzacz multimedialny, gry, w tym samym czasie, a jeśli użytkownicy nie chcą korzystać z aplikacji, która działa w tle, jeśli nie jest zamknięta. Użytkownik końcowy korzysta z wszystkich tych aplikacji w tym samym czasie, ale system operacyjny traktuje tę koncepcję nieco inaczej. Porozmawiajmy o tym, jak system operacyjny zarządza wielozadaniowością.

Co To jest wielozadaniowość w Arduino

jak widać na zdjęciu, procesor dzieli czas na trzy równe części i przypisuje każdą część do każdego zadania / aplikacji. W ten sposób wykonuje się wielozadaniowość w większości systemów. Koncepcja będzie prawie taka sama dla wielozadaniowości Arduino, z wyjątkiem dystrybucji czasu będzie nieco inna. Ponieważ Arduino działa w niskiej częstotliwości i pamięci RAM w porównaniu do laptopa / telefonu komórkowego / komputera, więc czas poświęcony każdemu zadaniu będzie również inny. Arduino ma również funkcję delay (), która jest szeroko stosowana. Ale przed rozpoczęciem omówmy, dlaczego nie powinniśmy używać funkcji delay () w żadnym projekcie.

dlaczego pomijać delay () w Arduino?

Jeśli rozważana jest dokumentacja referencyjna Arduino, to istnieją dwa rodzaje funkcji opóźniających, pierwsza to delaymicroseconds (), a druga to delayMicroseconds(). Obie funkcje są identyczne pod względem opóźnienia generowania. Jedyną różnicą jest to, że w funkcji delay () przekazany parametr integer jest wyrażony w milisekundach, tzn. jeśli zapiszemy delay (1000), to opóźnienie będzie wynosić 1000 milisekund, tzn. 1 sekundę. Podobnie w funkcji delayMicroseconds () parametr przekazywany jest w mikrosekundach tzn. jeżeli zapiszemy delayMicroseconds(1000), wtedy opóźnienie będzie wynosić 1000 mikrosekund tzn. 1 milisekund.

tu chodzi o to, że obie funkcje wstrzymują program na czas upływający w funkcji opóźnienia. Jeśli więc dajemy opóźnienie o 1 sekundę, procesor nie może przejść do następnej instrukcji, dopóki nie upłynie 1 sekunda. Podobnie, jeśli opóźnienie wynosi 10 sekund, program zatrzyma się na 10 sekund, a procesor nie pozwoli przejść do następnych instrukcji, dopóki nie upłynie 10 sekund. Utrudnia to działanie mikrokontrolera pod względem szybkości i wykonania instrukcji.

najlepszym przykładem na Wyjaśnienie wad funkcji opóźnienia jest użycie dwóch przycisków. Rozważmy, że chcemy przełączać dwie diody LED za pomocą dwóch przycisków. Jeśli więc jeden przycisk jest wciśnięty, odpowiednia DIODA powinna świecić przez 2 sekundy, podobnie jeśli drugi jest wciśnięty, DIODA powinna świecić przez 4 sekundy. Ale jeśli użyjemy delay(), jeśli użytkownik naciśnie pierwszy przycisk, program zatrzyma się na 2 sekundy, a jeśli użytkownik naciśnie drugi przycisk przed 2 sekundowym opóźnieniem, to mikrokontroler nie zaakceptuje danych wejściowych, ponieważ program jest w fazie halt.

oficjalna dokumentacja Arduino wyraźnie wspomina o tym w swoich uwagach i ostrzeżeniach o opisie funkcji delay (). Możesz przejść i sprawdzić to, aby było bardziej jasne.

Dlaczego używać millis() ?

aby przezwyciężyć problem spowodowany przez użycie delay, programista powinien użyć funkcji Milis (), która jest łatwa w użyciu, gdy już się przyzwyczaisz i użyje 100% wydajności procesora bez generowania żadnych opóźnień w wykonaniu instrukcji. millis() jest funkcją, która zwraca ilość milisekund, które upłynęły od czasu, gdy tablica Arduino rozpoczęła uruchamianie bieżącego programu bez zamrażania programu. Ta liczba czasowa zostanie przepełniona (tzn. powróci do zera), po około 50 dniach.

podobnie jak Arduino ma delayMicroseconds(), ma również mikro wersję Milis() jako micros(). Różnica między micros i Milis polega na tym, że Micros() przepełni się po około 70 minutach, w porównaniu do Milis (), która wynosi 50 dni. Tak więc w zależności od aplikacji można użyć millis () lub micros ().

Using millis() instead of delay():

aby użyć funkcji Milis() do pomiaru czasu i opóźnienia, musisz zarejestrować i zapisać czas, w którym miało miejsce działanie, aby rozpocząć czas, a następnie sprawdzać w odstępach czasu, czy określony czas minął. Tak jak podano, przechowuj bieżący czas w zmiennej.

unsigned long currentMillis = millis();

potrzebujemy jeszcze dwóch zmiennych, aby dowiedzieć się, czy wymagany czas minął. Zapisaliśmy aktualny czas w zmiennej currentMillis, ale musimy również wiedzieć, że kiedy rozpoczął się okres czasu i jak długi jest okres. W ten sposób deklarowany jest interwał i previousMillis. Interwał poinformuje nas o opóźnieniu czasowym, a previosMillis zapisze ostatni raz, gdy zdarzenie miało miejsce.

unsigned long previousMillis;unsigned long period = 1000;

aby to zrozumieć, weźmy przykład prostej migającej DIODY LED. Period = 1000 powie nam, że dioda LED będzie migać przez 1 sekundę lub 1000ms.

const int ledPin = 4; // the LED pin number connectedint ledState = LOW; // used to set the LED stateunsigned long previousMillis = 0; //will store last time LED was blinkedconst long period = 1000; // period at which to blink in msvoid setup() { pinMode(ledPin, OUTPUT); // set ledpin as output}void loop() { unsigned long currentMillis = millis(); // store the current time if (currentMillis - previousMillis >= period) { // check if 1000ms passed previousMillis = currentMillis; // save the last time you blinked the LED if (ledState == LOW) { // if the LED is off turn it on and vice-versa ledState = HIGH; } else {ledState = LOW;} digitalWrite(ledPin, ledState);//set LED with ledState to blink again }}

tutaj znajduje się polecenie <if (currentMillis – previousMillis >= period)> sprawdza, czy 1000ms minęło. Jeśli minęło 1000ms, dioda LED miga i ponownie przechodzi w ten sam stan. I tak dalej. To wszystko, nauczyliśmy się używać Milis zamiast opóźnienia. W ten sposób nie zatrzyma programu na określony przedział czasu.

przerwania w Arduino działają tak samo jak w innych mikrokontrolerach. Płyta Arduino UNO ma dwa oddzielne piny do mocowania przerwań na pinie GPIO 2 i 3. Omówiliśmy to szczegółowo w samouczku przerwań Arduino, gdzie możesz dowiedzieć się więcej o Przerwaniach i ich użyciu.

Tutaj pokażemy Wielozadaniowość Arduino, obsługując dwa zadania w tym samym czasie. Zadania będą obejmować miganie dwóch Diod Led z różnym opóźnieniem czasowym wraz z przyciskiem, który będzie używany do sterowania stanem włączania / wyłączania diody LED. Tak więc trzy zadania będą wykonywane jednocześnie.

schemat obwodu do wielozadaniowości Arduino

wymagane komponenty

  • Arduino UNO
  • trzy diody LED(dowolny kolor)
  • rezystancje (470, 10k)
  • Zworki
  • płyta chlebowa

Obwód diagram

schemat obwodu demonstrujący użycie funkcji Arduino Millis() jest bardzo łatwy i nie ma zbyt wielu komponentów do dołączenia, jak pokazano poniżej.

schemat obwodu dla wielozadaniowości Arduino za pomocą funkcji Arduino Millis ()

Programowanie Arduino UNO dla wielozadaniowości

Programowanie Arduino UNO dla wielozadaniowości będzie wymagało tylko logiki działania Milis (), która została wyjaśniona powyżej. Przed rozpoczęciem programowania Arduino UNO dla wielozadaniowości zaleca się przećwiczyć mruganie diodami LED za pomocą metody Milis, aby logika była jasna i wygodna przy użyciu metody Milis (). W tym samouczku przerwanie jest również używane z Millis () jednocześnie do wielozadaniowości. Przycisk będzie przerwaniem. Tak więc za każdym razem, gdy generowane jest przerwanie, tj. naciśnięcie przycisku, DIODA LED przełącza się w stan włączenia lub wyłączenia.

programowanie rozpoczyna się od zadeklarowania numerów pinów, do których podłączone są diody LED i przycisk.

int led1 = 6;int led2 = 7;int toggleLed = 5;int pushButton = 2;

następnie piszemy zmienną, która przechowuje stan Diod Led do wykorzystania w przyszłości.

int ledState1 = LOW;int ledState2 = LOW;

tak jak wyjaśniono powyżej w przykładzie blink, zmienne dla period I previousmillis są zadeklarowane do porównywania i generowania Opóźnienia dla diod LED. Pierwsza DIODA LED miga co 1 sekundę, a kolejna po 200 ms.

unsigned long previousMillis1 = 0; const long period1 = 1000;unsigned long previousMillis2 = 0;const long period2 = 200; 

do wygenerowania opóźnienia debounce zostanie użyta inna funkcja Milis, aby uniknąć wielokrotnego naciśnięcia przycisku. Będzie podobne podejście jak powyżej.

int debouncePeriod = 20; int debounceMillis = 0;

trzy zmienne będą używane do przechowywania stanu przycisku jako przerwania, przełączania diody LED i stanu przycisku.

bool buttonPushed = false;int ledChange = LOW; int lastState = HIGH;

Zdefiniuj działanie Pina, który będzie działał jako wejście lub wyjście.

 pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(toggleLed, OUTPUT); pinMode(pushButton, INPUT);

teraz zdefiniuj pin przerwania, dołączając przerwanie z definicją ISR i tryb przerwania. Zauważ, że zaleca się użycie digitalPinToInterrupt(pin_number) podczas deklarowania funkcji attachInterrupt (), aby przetłumaczyć rzeczywisty cyfrowy pin na określony numer przerwania.

attachInterrupt(digitalPinToInterrupt(pushButton), pushButton_ISR, CHANGE); 

podprogram przerwań jest zapisywany i zmieni jedynie flagę przycisku. Zwróć uwagę, że podprogram przerwania powinien być jak najkrótszy, więc spróbuj go napisać i zminimalizować dodatkowe instrukcje.

void pushButton_ISR(){ buttonPushed = true; }

pętla rozpoczyna się od zapisania wartości Milis w zmiennej currentMillis, która będzie przechowywać wartość czasu, jaki upłynął przy każdej iteracji pętli.

unsigned long currentMillis = millis();

w wielozadaniowości są w sumie trzy funkcje, mrugnięcie jedną diodą LED na 1 sekundę, mrugnięcie drugą DIODĄ LED na 200ms i po naciśnięciu przycisku Wyłącz / Włącz diodę LED. Napiszemy więc trzy części, aby wykonać to zadanie.

pierwszym z nich jest przełączanie stanu LED po każdej 1 sekundzie, porównując Milis upłynął.

 if (currentMillis - previousMillis1 >= period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite(led1, ledState1); }

podobnie przełącza diodę LED po każdym 200ms porównując upływający Milis. Wyjaśnienie zostało już wyjaśnione wcześniej w tym artykule.

 if (currentMillis - previousMillis2 >= period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite(led2, ledState2); }

wreszcie flaga przycisku jest monitorowana i po wygenerowaniu opóźnienia debounce 20ms po prostu włącza stan Diody LED odpowiada przyciskowi dołączonemu jako przerwanie.

 if (buttonPushed = true) // check if ISR is called { if ((currentMillis - debounceMillis) > debouncePeriod && buttonPushed) // generate 20ms debounce delay to avoid multiple presses { debounceMillis = currentMillis; // save the last debounce delay time if (digitalRead(pushButton) == LOW && lastState == HIGH) // change the led after push button is pressed { ledChange = ! ledChange; digitalWrite(toggleLed, ledChange); lastState = LOW; } else if (digitalRead(pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }

To kończy samouczek Arduino millis (). Zauważ, że aby uzyskać nawyk z Millis(), po prostu ćwicz implementację tej logiki w niektórych innych aplikacjach. Można również rozszerzyć go do korzystania z silników, serwosilników, czujników i innych urządzeń peryferyjnych. W razie jakichkolwiek wątpliwości prosimy pisać na naszym forum lub komentować poniżej.

kompletny kod i film demonstrujący użycie funkcji Milis w Arduino znajduje się poniżej.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.