W technologii mikroprocesorowej zadania działające równolegle nazywane są Wątkami. Jest to bardzo wygodne, ponieważ często konieczne jest wykonanie kilku operacji jednocześnie. Czy można sprawić, by mikrokontroler Arduino wykonywał kilka zadań jednocześnie, jak prawdziwy procesor? Zobaczmy.
Czy to jest to konieczne
- - Arduino;
- - 1 dioda;
- - 1 brzęczyk piezo.
Instrukcje
Krok 1
Ogólnie rzecz biorąc, Arduino nie obsługuje prawdziwej równoległości ani wielowątkowości.
Ale możesz powiedzieć mikrokontrolerowi, aby sprawdził, czy nadszedł czas na wykonanie jakiegoś dodatkowego zadania w tle przy każdym powtórzeniu cyklu "pętli ()". W takim przypadku użytkownikowi będzie się wydawać, że kilka zadań jest wykonywanych jednocześnie.
Na przykład mrugnijmy diodą LED z określoną częstotliwością i równolegle emitujmy dźwięki, które wznoszą się i opadają jak syrena z emitera piezoelektrycznego.
Wielokrotnie podłączaliśmy zarówno diodę LED, jak i emiter piezoelektryczny do Arduino. Złóżmy obwód, jak pokazano na rysunku. Jeśli podłączasz diodę LED do pinu cyfrowego innego niż „13”, pamiętaj, aby mieć rezystor ograniczający prąd około 220 omów.
Krok 2
Napiszmy taki szkic i wgrajmy go do Arduino.
Po załadowaniu płytki widać, że szkic nie jest wykonywany dokładnie tak, jak tego potrzebujemy: dopóki syrena nie będzie w pełni sprawna, dioda nie będzie migać, a my chcielibyśmy, aby dioda migała PODCZAS brzęczenia syreny. Jaki jest tutaj problem?
Faktem jest, że tego problemu nie da się rozwiązać w zwykły sposób. Zadania wykonywane są przez mikrokontroler ściśle sekwencyjnie. Operator "opóźnienie ()" opóźnia wykonanie programu o określony czas i dopóki ten czas nie upłynie, następujące polecenia programu nie zostaną wykonane. Z tego powodu nie możemy ustawić innego czasu wykonania dla każdego zadania w „pętli ()” programu.
Dlatego musisz jakoś symulować wielozadaniowość.
Krok 3
Opcja, w której Arduino będzie wykonywać zadania w pseudorównolegle, jest sugerowana przez programistów Arduino w artykule
Istotą metody jest to, że przy każdym powtórzeniu pętli „loop()” sprawdzamy, czy nadszedł czas, aby mrugnąć diodą (aby wykonać zadanie w tle), czy nie. A jeśli tak, to odwracamy stan diody LED. Jest to rodzaj ominięcia operatora „opóźnienie ()”.
Istotną wadą tej metody jest to, że sekcja kodu przed jednostką sterującą LED musi być wykonywana szybciej niż odstęp czasu migania diody „ledInterval”. W przeciwnym razie mruganie będzie występowało rzadziej niż to konieczne, a nie uzyskamy efektu równoległego wykonywania zadań. W szczególności na naszym szkicu czas trwania zmiany dźwięku syreny wynosi 200 + 200 + 200 + 200 = 800 ms, a interwał migania diody ustawiamy na 200 ms. Ale dioda LED będzie migać z okresem 800 ms, czyli 4 razy innym od tego, który ustawiliśmy. Ogólnie rzecz biorąc, jeśli w kodzie używany jest operator „opóźnienie ()”, wówczas trudno jest zasymulować pseudorównoległość, dlatego warto go unikać.
W takim przypadku konieczne byłoby, aby centrala dźwiękowa syreny również sprawdzała, czy nadszedł czas, czy nie, i nie używała funkcji „opóźnienie ()”. Ale to zwiększyłoby ilość kodu i pogorszyło czytelność programu.
Krok 4
Do rozwiązania tego problemu wykorzystamy wspaniałą bibliotekę ArduinoThread, która pozwala w łatwy sposób tworzyć pseudo-równoległe procesy. Działa to w podobny sposób, ale pozwala nie pisać kodu sprawdzającego czas - czy trzeba wykonać zadanie w tej pętli, czy nie. Zmniejsza to ilość kodu i poprawia czytelność szkicu. Sprawdźmy bibliotekę w akcji.
Przede wszystkim pobierz archiwum biblioteki z oficjalnej strony https://github.com/ivanseidel/ArduinoThread/archive/master.zip i rozpakuj je do katalogu „biblioteki” Arduino IDE. Następnie zmień nazwę folderu „ArduinoThread-master” na „ArduinoThread”.
Krok 5
Schemat połączeń pozostanie taki sam. Zmieni się tylko kod programu. Teraz będzie tak samo jak na pasku bocznym.
W programie tworzymy dwa strumienie, każdy wykonuje swoją własną operację: jeden miga diodą LED, drugi steruje dźwiękiem syreny. W każdej iteracji pętli, dla każdego wątku, sprawdzamy, czy nadszedł czas na jego wykonanie, czy nie. Jeśli nadejdzie, jest uruchamiany do wykonania przy użyciu metody „run()”. Najważniejsze, aby nie używać operatora „opóźnienie ()”.
Bardziej szczegółowe wyjaśnienia znajdują się w kodzie.
Załadujmy kod do pamięci Arduino, uruchom go. Teraz wszystko działa dokładnie tak, jak powinno!