Pętle Arduino. Pętle FOR i WHILE w Arduino Zagnieżdżone pętle w Arduino

Dzisiaj będziemy uczyć się równie ważnej części języka programowania, jak pętle. Do czego są potrzebne. Na przykład postawmy sobie cel. Należy zapalić kolejno sześć diod LED z okresem 50 ms, a następnie wyłączyć je kolejno w tym samym odstępie czasu. Cóż może być prostszego? Piszemy następujący kod:
void setup() ( pinMode(2, WYJŚCIE); pinMode(3, WYJŚCIE); pinMode(4, WYJŚCIE); pinMode(5, WYJŚCIE); pinMode(6, WYJŚCIE); pinMode(7, WYJŚCIE); ) pusta pętla () ( digitalWrite(2, WYSOKIE); opóźnienie(50); digitalWrite(3, WYSOKIE); opóźnienie(50); digitalWrite(4, WYSOKIE); opóźnienie(50); digitalWrite(5, WYSOKIE); opóźnienie(50) ; digitalWrite (6, WYSOKI); opóźnienie (50); digitalWrite (7, WYSOKI); opóźnienie (50); digitalWrite (2, NISKI); opóźnienie (50); digitalWrite (3, NISKI); opóźnienie (50); digitalWrite (4, LOW); opóźnienie (50); digitalWrite (5, LOW); opóźnienie (50); digitalWrite (6, LOW); opóźnienie (50); digitalWrite (7, LOW); opóźnienie (50); ) Najpierw Zainicjowaliśmy sześć pinów cyfrowych od drugiego do siódmego jako wyjścia, a w programie głównym napisaliśmy naprzemienne włączanie diody LED, opóźnienie i tak dalej sześć razy. Potem to samo, ale za każdym razem dioda gaśnie. Teraz wgrywamy go do Arduino i cieszymy się pracą. Ale nadal coś tu jest nie tak. Jeśli przyjrzysz się uważnie kodowi programu, zauważysz, że niektóre fragmenty kodu powtarzają się w całym programie. Na przykład powtórzenie pauzy powinno natychmiast przykuć twoją uwagę. A podczas inicjalizacji kodu PIN zmienia się tylko jego numer. Po włączeniu i wyłączeniu zmienia się tylko liczba. Dla tak małego programu oczywiście można tak zostawić, kontroler to zje i się nie zadławi, ale jeśli trzeba będzie wykonać kod powtarzany np. 1000 razy. Myślę, że mam dość cierpliwości, aby go wypełnić, ale czy MK ma wystarczającą ilość pamięci? Oczywiście możesz zapytać, po co nam do cholery 1000 identycznych operacji? Cóż, tak, trudno to sobie wyobrazić.) Ale to nie jest problem, ale jeśli mamy tablicę 1000 komórek. Często się to zdarza, na przykład kilka czujników zapisuje parametry do tablicy i jak wymyślić, jak uporządkować ten bałagan. Trzeba by to jakoś przeanalizować według jakichś parametrów. Właśnie dla takich zdarzeń wymyślono cykle. Pętla to fragment kodu wykonywany określoną liczbę razy. Jedna wykonana część programu w pętli nazywana jest iteracją. Liczba iteracji może wynosić od 0 do nieskończoności. Aby wykonać pętle w języku programowania, dostępne są aż trzy opcje pętli. Uwierz mi, to wystarczy do każdego wyrafinowanego kodowania. Przyjrzyjmy się temu wszystkiemu bardziej szczegółowo.
  • podczas gdy(warunek) ()
  • wykonaj() podczas gdy(warunek);
  • for(zmienna licznika; warunek; zwiększ zmienną licznika) ()
Pierwszy cykl podczas gdy(warunek) (). Jak on pracuje. Po słowie chwila w nawiasach musi znajdować się warunek. Warunek może być dowolny, byle był prawdziwy. Gdy tylko warunek stanie się fałszywy, pętla zatrzyma się, a program będzie kontynuował działanie od następnego wiersza po pętli. Użyjmy przykładu.
znak i = 0; podczas gdy ja Właściwie to, co tu jest napisane. Najpierw inicjujemy zmienną count I i zresetuj go. Następnie wchodzimy do pętli i zaczynamy sprawdzać warunek w nawiasach. Jeśli wartość I jest mniejsza niż 10, następnie wykonaj treść pętli. W treści pętli po prostu zwiększamy wartość zmiennej zliczającej o jeden i ponownie sprawdzamy warunek. W naszym przypadku pętla zostanie wykonana 10 razy. To znaczy, najpierw znaczenie I równa się zeru. Zero jest mniejsze niż dziesięć. Następnie zwiększyliśmy zmienną o jeden i dla porównania jeden jest mniejszy niż dziesięć i tak dalej. Gdy tylko zmienna licząca stanie się równa dziesięciu, sprawdzamy, czy dziesięć jest mniejsze niż dziesięć? Oczywiście, że nie i po sprawdzeniu cykl przestanie działać. Tak działa ten cykl. Co powinieneś zrobić, jeśli musisz wykonać kod znajdujący się w treści pętli tylko raz, nawet jeśli nie spełnia to warunku? Jest na to inny cykl, tzw wykonaj() podczas(warunek). Działa dokładnie tak samo jak poprzedni cykl, z jedną różnicą. W tej pętli najpierw wykonywany jest jej korpus, a następnie następuje test. Zobaczmy jak to wygląda w kodzie.
znak i = 0; wykonaj ( i++; ) while((i > 0) & (tj Zobacz jakie to interesujące. Najpierw, podobnie jak ostatnim razem, inicjujemy zmienną zliczającą na zero, ale pod warunkiem, że to zapisujemy I była większa od zera i mniejsza niż dziesięć. Oznacza to, że wartość zmiennej musi mieścić się w przedziale od jednego do dziewięciu. Gdybyśmy napisali to w ten sposób, korzystając z poprzedniej pętli, nigdy nie zostałaby wykonana. Ale mamy magiczne słowo Do. To znaczy, co się stanie. Po pierwsze, w treści pętli wartość zmiennej zliczającej wzrośnie i osiągnie jeden, a to będzie więcej niż zero, warunek stanie się prawdziwy. W związku z tym pętla będzie wykonywana, dopóki zmienna zliczająca nie osiągnie wartości dziesięciu. I wreszcie trzecia wersja cyklu. Jak on działa:
znak i; dla (i = 0; tj Jak to działa. Najpierw ponownie inicjujemy zmienną zliczającą, ale bez określonej wartości. Następnie piszemy słowo Do, ale w nawiasie najpierw zapisujemy naszą zmienną zliczającą i przypisujemy jej wartość początkową. Następnie sprawdzamy warunek i jeśli jest prawdziwy to wykonujemy ciało pętli i zwiększamy wartość zmiennej zliczającej. Zasadniczo jest to to samo, co chwila()() więc który cykl wybrać, zależy od Ciebie. Kilka słów o niektórych punktach. Na przykład, jeśli piszesz podczas gdy(1);, wtedy pętla będzie działać w nieskończoność. Lub jeśli z Do, wtedy będzie to wyglądać tak Do(;;);. Bądź ostrożny. Czasami podczas wykonywania cyklu naprawdę chcesz rzucić wszystko i wyjść z niego, ale warunek na to nie pozwala. Co powinienem zrobić? Jest na to inne polecenie przerwa;. Gdy tylko MK natknie się na to polecenie w treści pętli, natychmiast opuści pętlę i będzie kontynuował wykonywanie programu od następnego wiersza po pętli. Co jednak, jeśli w trakcie działania pętli pojawi się warunek nie spełniający warunku lub np. moment, w którym nie musimy już kontynuować wykonywania końca ciała pętli? Zespół nam tutaj pomoże Kontynuować;. Gdy tylko MK natknie się na to polecenie, porzuca wszystko i przechodzi do następnej iteracji pętli. Mam nadzieję, że wszystko jasno wyjaśniłem. Teraz, mając tę ​​wiedzę, napiszmy nasz program od nowa, ale z wykorzystaniem pętli.
void setup() (bajt i = 2; // Zmienna zliczająca while(i // Jeśli i jest mniejsze niż 8, wykonaj treść pętli ( pinMode(i, OUTPUT); // Zainicjuj piny zaczynając od 2 ja++; //Zwiększ zmienną zliczającą o jeden) ) void pętla() ( bajt i = 2; while(i Przyjrzyjmy się bliżej. Najpierw zainicjowaliśmy zmienną zliczającą I i przypisano mu wartość dwa. Dlaczego dwa? Ale ponieważ specjalnie dobrałem piny od drugiego do siódmego, żeby mieć pewność, że wartość początkowa nie ma żadnego znaczenia. Okazało się, że to jakaś gra słów) Cóż, oczywiście, że tak. Następnie zapisujemy warunek pętli. Musimy wykonać sześć iteracji, ponieważ mamy sześć diod LED. Świetnie, uważamy, że dwa plus sześć równa się osiem. Tak, więc musimy sprawdzić zmienną zliczającą, aż będzie mniejsza niż osiem. Tak napisali while(i . Teraz nasza pętla wykona się sześć razy. Co musimy zrobić w ciele pętli? Nic skomplikowanego, wystarczy wpisać na wyjściu funkcję inicjalizacji wyjścia, po prostu podstawić zmienną zliczającą zamiast numeru wyjścia. Co to jest sztuczka.Jak tylko MK wejdzie do pętli body, to przed wykonaniem funkcji inicjalizacji wyjścia przyjrzyjmy się przekazywanym argumentom.Jeden z nich powinien zawierać numer wyjścia i mamy tam zmienną zliczającą.Co powinniśmy zrobić Ale nic, mądry MK sprawdzi, jaka tam jest zmienna i dumnie wyciągnie z niej liczbę. I mamy tam dwójkę. No cóż, świetnie, zainicjujmy drugie wyjście. Potem zwiększymy wartość zmienną zliczającą przez inną i sprawdź warunek. Tak, trzy jest mniejsze niż osiem, zróbmy to jeszcze raz, tylko zmienna ma teraz trzy. Oznacza to, że zainicjujemy wyjście po raz trzeci, a następnie zwiększymy zliczanie zmiennej o jeden.W ten sposób przechodząc przez pętlę ustawimy wszystkie potrzebne nam wyjścia.Co więcej, zwiększenie zmiennej zliczającej o jeden nie jest warunkiem ścisłym. Nikt Ci nie przeszkadza, żebyś napisał coś takiego: i = ((127*i)/31) & 0xF4; To zadziała również, jeśli warunek będzie spełniony po wykonaniu. Dla pętli nie ma znaczenia, co dzieje się w ciele; interesuje ją, czy warunek jest prawdziwy, czy nie. To wszystko. W następnej lekcji przyjrzymy się funkcjom, dlaczego są potrzebne i spróbujemy napisać własne.

Każdy język programowania posiada zestaw instrukcji sterujących, które umożliwiają wielokrotne wykonanie tego samego kodu (pętla), wybór odpowiedniego fragmentu kodu (warunki) oraz instrukcje wyjścia z bieżącego fragmentu kodu.

Arduino IDE zapożycza większość niezbędnych elementów sterujących z C/C++. Ich składnia jest identyczna jak w C. Poniżej pokrótce opiszemy ich składnię.

jeśli stwierdzenie

Instrukcja if umożliwia wykonanie określonego fragmentu programu w zależności od wyniku sprawdzenia określonego warunku. Jeśli warunek jest spełniony, kod programu zostanie wykonany, natomiast jeśli warunek nie zostanie spełniony, kod programu zostanie pominięty. Składnia polecenia if jest następująca:

If(warunek) ( instrukcja1; instrukcja2; )

Warunek może być dowolnym porównaniem zmiennej lub wartości zwracanej przez funkcję. Głównym kryterium warunku if jest to, że odpowiedź musi zawsze być prawdziwa lub fałszywa. Przykładowe warunki instrukcji if:

Jeśli(a!=2) ( ) jeśli(x<10) { } if(znak==’B’) { }

W nawiasach zapisanych w warunku możesz wykonać kod.

Osoby rozpoczynające naukę programowania często popełniają błąd polegający na zrównywaniu wartości określonej zmiennej za pomocą pojedynczego znaku „=”. Taki zapis wyraźnie wskazuje na przypisanie wartości zmiennej, dlatego warunek zawsze będzie „prawdziwy”, czyli spełniony. Sprawdzanie, czy zmienna jest równa określonej wartości, jest zawsze oznaczone podwójnym znakiem równości (==).

Możesz użyć stanu funkcji jako warunku, na przykład:

If(init()) ( Serial.print("ok"); )

Powyższy przykład zostanie wykonany w następujący sposób: W pierwszym kroku wywoływana jest funkcja init(). Ta funkcja zwraca wartość, która będzie interpretowana jako „prawda” lub „fałsz”. W zależności od wyniku porównania zostanie wysłana wiadomość „OK” lub nie zostanie wysłany żaden komunikat.

Jeśli...inne stwierdzenie

Rozszerzona instrukcja if to instrukcja if….else. Zapewnia wykonanie jednego fragmentu kodu, gdy warunek jest prawdziwy (prawda), a drugiego fragmentu kodu, gdy warunek nie jest spełniony (fałsz). Składnia instrukcji f if….else jest następująca:

If (warunek) ( // polecenie A ) else ( // polecenie B )

Polecenia „A” zostaną wykonane tylko wtedy, gdy warunek zostanie spełniony, polecenie „B” zostanie wykonane, gdy warunek nie zostanie spełniony. Jednoczesne wykonanie polecenia „A” i „B” nie jest możliwe. Poniższy przykład pokazuje, jak używać składni if...else:

If (init()) ( Serial.print("ok"); ) else ( Serial.print("błąd"); )

Można w ten sposób sprawdzić poprawność wykonania funkcji i poinformować o tym użytkownika.

Powszechną praktyką jest zaprzeczanie temu schorzeniu. Dzieje się tak dlatego, że funkcja, która została wykonana poprawnie, zwraca wartość 0, a funkcja, która z jakiegoś powodu została wykonana błędnie, zwraca wartość niezerową.

Wyjaśnienie tej „komplikacji życiowej” jest proste. Jeśli funkcja zostanie wykonana poprawnie, to jest to jedyna informacja, której potrzebujemy. W przypadku błędu czasem warto zrozumieć co poszło nie tak i dlaczego funkcja nie została wykonana poprawnie. I tu z pomocą przychodzą liczby inne niż zero, czyli za pomocą kodów cyfrowych możemy określić rodzaj błędu. Np. 1 - problem z odczytaniem jakiejś wartości, 2 - brak miejsca w pamięci lub na dysku, itp.

Ostatni zmodyfikowany przykład pokazuje, jak wywołać funkcję, która po poprawnym wykonaniu zwraca zero:

If (!init()) ( Serial.print("ok"); ) else ( Serial.print("błąd"); )

Przełącz instrukcję przypadku

Instrukcja if pozwala przetestować tylko jeden warunek. Czasami konieczne jest wykonanie jednej z akcji w zależności od zwróconej lub odczytanej wartości. Operator wielokrotnego wyboru przełącznika jest do tego idealny. Poniżej przedstawiono składnię polecenia switch:

Switch (var) (przypadek 1: //instrukcja dla var=1 break; przypadek 2: //instrukcja dla var=2 break; domyślnie: //instrukcja domyślna (jeśli var różni się od 1 i 2) )

W zależności od wartości zmiennej var wykonywane są instrukcje w poszczególnych blokach. Etykieta przypadku wskazuje początek bloku dla określonej wartości. Przykładowo przypadek 1: oznacza, że ​​blok ten zostanie wykonany dla wartości var równej jeden.

Każdy blok musi zostać zakończony komendą break. Przerywa dalsze wykonywanie instrukcji switch. W przypadku pominięcia polecenia break, instrukcje zostaną wykonane w kolejnych blokach przed poleceniem break. Domyślna etykieta jest opcjonalna, podobnie jak w przypadku instrukcji if. Instrukcje znajdujące się w bloku default wykonywane są tylko wtedy, gdy wartość zmiennej var nie pasuje do żadnego wzorca.

Często zdarza się, że te same instrukcje muszą zostać wykonane dla jednej z kilku wartości. Można to osiągnąć w następujący sposób:

Switch (x) ( przypadek 1: //instrukcja dla przerwy x=1; przypadek 2: przypadek 3: przypadek 5: //instrukcja dla przerwy x=2 lub 3 lub 4; przypadek 4: //instrukcja dla przerwy x=4 ; przypadek 6: // instrukcja dla x=6 break; domyślnie: // instrukcja domyślna (jeśli x jest różne od 1,2,3,4,5,6) )

W zależności od wartości zmiennej x zostanie wykonany odpowiedni blok instrukcji. Powtarzanie przypadku 2: przypadku 3: przypadku 5: informuje kompilator, że jeśli zmienna x ma wartość 2, 3 lub 5, to zostanie wykonany ten sam fragment kodu.

za oświadczenie

Instrukcja for służy do wielokrotnego wykonywania tego samego kodu. Często konieczne jest wykonanie tych samych instrukcji, zmieniając jedynie wartość jakiejś zmiennej. Pętla for jest do tego idealna. Składnia polecenia jest następująca:

Wewnętrzne; dla (i=0;tj<10;i++) { // инструкции для выполнения в цикле }

Pierwszym parametrem podanym w instrukcji for jest wartość początkowa zmiennej. Kolejnym elementem jest sprawdzenie warunku kontynuacji wykonywania pętli. Pętla działa tak długo, jak warunek jest spełniony. Ostatnim elementem jest zmiana wartości zmiennej. Najczęściej zwiększamy lub zmniejszamy jego wartość (w miarę potrzeby). W tym przykładzie instrukcje zawarte w pętli zostaną wykonane w punkcie i=0...9.

Często deklarowana jest tam zmienna używana w pętli:

For(int i=0;i<10;i++) { // инструкции для выполнения в цикле }

Zmienną służącą do zliczania kolejnych kroków pętli można w niej wykorzystać do wywołania funkcji z odpowiednimi parametrami.

For(int i=10;i>0;i—) ( Serial.print(i); // zostaną wysłane liczby 10,9,8,7,6,5,4,3,2,1)

podczas gdy oświadczenie

Pętla for jest idealna, gdy chcemy policzyć. W sytuacji, gdy musimy wykonać określone działania w wyniku jakiegoś zdarzenia, które niekoniecznie jest przewidywalne (np. czekamy na naciśnięcie przycisku), wówczas możemy skorzystać z instrukcji while, która wykonuje blok instrukcji jako o ile warunek jest spełniony. Składnia instrukcji while jest następująca:

While(warunek) ( // blok instrukcji do wykonania)

Ważne jest, aby kontrola stanu nastąpiła na początku cyklu. Może się zdarzyć, że instrukcje znajdujące się w pętli while nigdy nie zostaną wykonane. Możliwe jest również utworzenie nieskończonej pętli. Spójrzmy na dwa przykłady:

Int x=2; while(x>5) ( Serial.print(x); ) —————————————- int y=5; while(y>0) ( Serial.print(y); )

Pierwszy blok instrukcji znajdujący się wewnątrz while nigdy nie zostanie wykonany. Zmienna x ma wartość dwa i nie będzie większa niż 5. W drugim przykładzie mamy do czynienia z pętlą nieskończoną. Zmienna „y” ma wartość 5, czyli większą od zera. Nie ma zmian w zmiennej „y” wewnątrz pętli, więc pętla nigdy się nie zakończy.

Jest to częsty błąd, gdy zapominamy zmienić parametr, który powoduje zakończenie pętli. Poniżej znajdują się dwa poprawne przykłady użycia pętli while:

Intx=0; podczas (x<10) { //блок инструкций x++; } —————————————- while(true) { if(условие) break; // блок инструкций }

W pierwszym przykładzie zajęliśmy się zmianą wartości zmiennej sprawdzanej w warunku. W rezultacie cykl ostatecznie się zakończy. W drugim przykładzie celowo utworzono nieskończoną pętlę. Ta pętla jest odpowiednikiem funkcji pętli() w Arduino IDE. Dodatkowo wewnątrz pętli wprowadzono sprawdzanie warunku, po którym pętla kończy się komendą break.

wykonaj… instrukcję

Odmianą pętli while jest pętla do...while. Oprócz składni różni się on miejscem sprawdzania warunku. W przypadku do...while warunek sprawdzany jest po wykonaniu bloku instrukcji. Oznacza to, że blok instrukcji znajdujący się w ciele pętli zostanie wykonany przynajmniej raz. Poniżej znajduje się składnia polecenia do...while:

Wykonaj ( // blok instrukcji ) while(warunek)

Wszystko, co napisano o operatorze while, dotyczy również operatora do...while. Poniżej znajduje się przykład użycia pętli do...while:

Int x=10; do ( // blok instrukcji x—; ) while(x>0); —————————————- do ( // blok instrukcji if (warunek) break; ) while(true);

oświadczenie o złamaniu

Instrukcja break umożliwia wyjście z pętli (do...while, for, while) i wyjście z opcji switch. W poniższym przykładzie rozważ wykonanie polecenia break:

Dla(i=0;tj<10;i++) { if(i==5) break; Serial.print(i); }

Pętla musi zostać wykonana dla liczb od 0 do 9, natomiast dla liczby 5 spełniony jest warunek wywołujący instrukcję break. Spowoduje to wyjście z pętli. W rezultacie do portu szeregowego (Serial.print) zostaną wysłane tylko liczby 0,1,2,3,4.

Kontynuuj operatora

Operator kontynuowania powoduje zatrzymanie wykonywania instrukcji pętli (do...while, for, while) dla bieżącej wartości i przejście do następnego kroku pętli. Poniższy przykład pokazuje, jak działa instrukcjacontinue:

Dla(i=0;tj<10;i++) { if(i==5) continue; Serial.print(i); }

Jak nie trudno zauważyć, pętla zostanie wykonana dla wartości od 0 do 9. Dla wartości 5 zostanie wykonana komendacontinue, w wyniku czego instrukcje następujące po tej komendzie nie zostaną wykonane. W rezultacie liczby 0,1,2,3,4,6,7,8,9 zostaną przesłane do portu szeregowego (Serial.print).

oświadczenie zwrotne

Instrukcja return kończy wykonywanie wywoływanej funkcji i zwraca wartość określonego typu. Jako parametr polecenia można określić liczbę, symbol lub zmienną określonego typu. Ważne jest, aby zwracana wartość była zgodna z typem zadeklarowanej funkcji. Poniższy przykład pokazuje, jak używać instrukcji return:

Int checkSensor())( if (analogRead(0) > 400) ( // odczyt wejścia analogowego return 1; // Dla wartości większych niż 400 zwracane jest 1 else( return 0; // dla pozostałych 0 to wrócił) )

Jak widać, możesz użyć wielu instrukcji return w jednej funkcji, ale tylko jedna z nich zawsze będzie działać. Dopuszczalne jest użycie operatora powrotu bez parametrów. Pozwala to na przedwczesne zakończenie funkcji, która nie zwraca żadnej wartości.

Void nazwa_funkcji() ( instrukcja1; if(x==0) return; instrukcja2; instrukcja3; )

W powyższym przykładzie instrukcja 1 zostanie wykonana przy każdym wywołaniu funkcji. Wykonanie instrukcji2 i instrukcji3 zależy od wyniku polecenia if. Jeżeli warunek jest spełniony (true) to polecenie return zostanie wykonane i funkcja zakończy działanie.

W przypadku niespełnienia warunku polecenie return również nie jest wykonywane, lecz wykonywane są instrukcje instrukcja2 i instrukcja3, po czym funkcja kończy swoje działanie.

muszę oświadczenie

Ze względów ideologicznych należy pominąć ten opis... Instrukcja goto jest poleceniem, którego nie należy używać w normalnym programowaniu. Powoduje złożoność kodu i jest złym nawykiem programistycznym. Zdecydowanie zalecamy, aby nie używać tego polecenia w swoich programach. Ponieważ goto jest zawarte w oficjalnej dokumentacji na stronie arduino.cc, oto jego krótki opis. składnia polecenia goto:

…. muszę zaznaczyć; // przejdź do linii oznaczonej „metka” ...... .... …. metka: // etykieta, z którą program będzie kontynuował pracę...

Polecenie pozwala przejść do wyznaczonego znacznika, czyli do miejsca w programie.

Pętle wykorzystujące instrukcje Do I chwila to jedna z najważniejszych konstrukcji języka C++ leżącego u podstaw Arduino. Można je znaleźć w absolutnie każdym szkicu, nawet jeśli o tym nie wiesz. W tym artykule przyjrzymy się bliżej pętlom, dowiemy się, jaka jest różnica między for i while, jak można za ich pomocą uprościć pisanie programu i jakich błędów należy unikać.

Jeśli nadal jesteś początkującym programistą i chcesz zrozumieć, czym jest pętla i dlaczego jest potrzebna, zapoznaj się z kolejną sekcją tego artykułu ze szczegółowym opisem.

Operator WHILE jest używany w C++ i Arduino do powtarzania tych samych poleceń dowolną liczbę razy. W porównaniu z pętlą FOR pętla WHILE wygląda na prostszą; zwykle stosuje się ją tam, gdzie nie musimy liczyć iteracji zmiennej, a wystarczy powtarzać kod, aż coś się zmieni lub nastąpi jakieś zdarzenie.

Składnia WHILE

chwila(<условие или список условий>)
{
<программный блок, который будет повторяться>
}

Jako warunków można użyć dowolnej konstrukcji językowej, która zwraca wartość logiczną. Warunki mogą być operacjami porównania, funkcjami, stałymi, zmiennymi. Podobnie jak w przypadku każdej innej operacji logicznej w Arduino, każda wartość różna od zera będzie postrzegana jako prawda, zero – fałsz.

// Niekończąca się pętla while(true)( Serial.println("Waiting..."); ) // Pętla działająca do momentu zmiany wartości funkcji checkSignal() while(!checkSignal())( Serial.println ("Czekanie..."); )

Należy zauważyć, że instrukcji while można użyć bez blokowania bloku nawiasami klamrowymi, w takim przypadku powtórzone zostanie pierwsze polecenie napotkane po pętli. Zdecydowanie nie zaleca się używania bez nawiasów klamrowych, ponieważ w tym przypadku bardzo łatwo jest popełnić błąd. Przykład:

While(true) Serial.print("Oczekiwanie na przerwanie"); opóźnienie (1000);

W tym przypadku napis będzie wyświetlany w nieskończonej pętli bez pauz, gdyż polecenie opóźnienia(1000) nie zostanie powtórzone. Można spędzić dużo czasu na wyłapywaniu takich błędów - dużo łatwiej jest użyć nawiasu klamrowego.

Przykład użycia pętli while

Najczęściej while służy do oczekiwania na jakieś wydarzenie. Na przykład gotowość obiektu Serial do pracy.

Serial.begin(9600); while (!Serial) ( ; // Niektóre płyty Arduino wymagają zaczekania, aż port szeregowy będzie wolny)

Przykład oczekiwania na przyjście znaku z urządzeń zewnętrznych poprzez UART:

While(Serial.available())( int byteInput = Seria.read(); // Inne akcje)

W tym przypadku będziemy czytać wartości​​o ile Serial.available() zwróci wartość różną od zera. Gdy wszystkie dane w buforze się wyczerpią, pętla zostanie zatrzymana.

Pętla FOR w Arduino

W pętli FOR mamy możliwość nie tylko ustawienia warunków brzegowych, ale także od razu zdefiniowania zmiennej dla licznika i wskazania jak będą zmieniać się jej wartości przy każdej iteracji.

Składnia pętli FOR

Tutaj projekt będzie nieco bardziej skomplikowany:
Do (<начальное значение счетчика>;<условие продолжения выполнения цикла>;<изменение значения счетчика на каждом шаге>){
<список_команд>
}

Najprostszy przykład:

Dla(int i=5;tj<10;i++){ // Конструкция «3 в одном» pinMode(i, OUTPUT); }

Od razu utworzyliśmy zmienną, zainicjowaliśmy ją i wskazaliśmy, że na koniec każdego cyklu wartość licznika należy zwiększyć o jeden. I to wszystko - teraz możesz używać zmiennej wewnątrz pętli.

Krok zmienny może być inny. Oto przykłady:

  • for(int i=0; tj<10; i=i+2) // Шаг 2
  • for(int i=0; tj<10; i+=2) // Аналогичен предыдущему
  • for(int i=10; i>0; i–) // Wróć – od 10 do 1

wykonaj pętlę while

W niektórych przypadkach musimy tak zorganizować pętlę, aby instrukcje bloku zostały wykonane przynajmniej raz, a następnie przeprowadzono sprawdzenie. W przypadku takich algorytmów można użyć konstrukcji do while. Przykład:

Wykonaj ( Serial.println("Praca"); ) while (checkCoś());

Ta wersja pętli nie nastręcza żadnych trudności - po prostu przesunęliśmy blok z warunkami w dół, więc cała zawartość w nawiasach klamrowych po operatorze do zostanie wykonana przed pierwszym sprawdzeniem.

Kontynuuj i przerwij instrukcje

Są sytuacje, w których trzeba pilnie przerwać wykonywanie pętli wewnątrz bloku pętli, bez czekania na przejście do bloku sprawdzania warunku. Aby to zrobić, możesz użyć operatora przerwa:

Podczas gdy (true) ( ​​​​if (checkSomething()) ( break; ) )

Jeśli chcemy po prostu zatrzymać postęp bieżącej iteracji, ale nie wychodzić z pętli, ale przejść do bloku sprawdzania warunku, to musimy użyć operatora Kontynuować:

Chociaż (true) ( ​​​​if (checkSomething()) (kontynuuj; ) )

Instrukcjecontinu i break mogą być używane ze wszystkimi wariantami pętli FOR i WHILE.

Zagnieżdżone pętle w Arduino

Dowolne warianty pętli można łatwo ze sobą łączyć, tworząc struktury zagnieżdżone. Zmienne zdefiniowane w bloku pętli „nakładającej się” będą dostępne w bloku wewnętrznym. Najczęstszym przykładem tego rodzaju pętli jest przechodzenie przez tablice dwuwymiarowe. W poniższym przykładzie używamy podwójnej pętli: pierwsza będzie iterować po wierszach (zmienna i), druga, zagnieżdżona, będzie przechodzić przez kolumny (zmienna j) tablicy, którą zdefiniowaliśmy w zmiennej arr.

Int arr; void setup() ( for (int i = 0; i< 10; i++) { for (int j = 0; j < 3; j++) { arr[i][j] = i * j; Serial.println(arr[i][j]); } } }

Więcej o cyklach

Jeśli nigdy nie pracowałeś z pętlami, zanurzmy się trochę w świat teorii i dowiedzmy się, czym są pętle i dlaczego potrzebujemy tych tajemniczych konstrukcji językowych.

Dlaczego potrzebujemy pętli?

Tak naprawdę głównym zadaniem pętli jest kilkukrotne powtórzenie tej samej konstrukcji językowej. Taka potrzeba pojawia się niemal w każdym programie, a już na pewno żaden szkic Arduino nie obejdzie się bez pętli – funkcja pętli() jest też wywoływana w nieskończonej pętli.

Spójrzmy na następujący przykład. Należy jednocześnie zasilić 5 diod LED podłączonych do płytki Arduino od pinów 5 do 9. Najbardziej oczywistą opcją byłoby umieszczenie pięciu instrukcji w rzędzie:

digitalWrite(5, WYSOKI);

digitalWrite(6, WYSOKI);

digitalWrite(7, WYSOKI);

digitalWrite(8, WYSOKI);

digitalWrite(9, WYSOKI);

Pomińmy na razie kwestię ryzykowności takiego działania, gdyż jednoczesne włączenie takiej ilości diod LED powoduje zwiększone obciążenie obwodu zasilającego płytki. Najważniejsze dla nas jest teraz to, że stworzyliśmy pięć linii kodu, z których każda różni się od pozostałych tylko jedną cyfrą. To podejście ma następujące wady:

  • Przy każdej zmianie będziesz musiał dokonać zmian w wielu liniach jednocześnie. Przykładowo, jeśli będziemy musieli przełączyć diody na piny od 2 do 6 lub wyłączyć napięcie zamiast je włączać, będziemy musieli dokonać 5 zmian w kodzie. A co jeśli będzie więcej instrukcji i zmian?
  • Duży kod z dużą liczbą podobnych instrukcji jest niewygodny i nieprzyjemny w czytaniu. Pięć identycznych linii nie jest zbyt strasznych. Jednak nawyk brudnego kodu ostatecznie doprowadzi do powstania dziesiątek i setek dodatkowych stron w wykazie, co wprawi zarówno Ciebie, jak i Twoich współpracowników w przygnębienie.
  • W procesie „kopiuj-wklej” niemal identyczne instrukcje można łatwo popełnić błąd, np. zapominając o zmianie numeru PIN: digitalWrite(5, HIGH); digitalWrite(5, WYSOKI);
  • Możesz łatwo nie przejść rozmowy kwalifikacyjnej w dowolnej normalnej firmie produkującej oprogramowanie, pokazując osobie przeprowadzającej rozmowę kwalifikacyjną ten kod.

Z tego wszystkiego możemy wyciągnąć wniosek, że prawie zawsze należy unikać wielokrotnego używania tych samych ciągów znaków i zastępować je pętlami. Co więcej, w wielu sytuacjach nie da się obejść bez cykli, nic ich nie zastąpi. Nie można zmienić liczby powtórzeń kodu podczas działania programu. Na przykład musisz przetworzyć każdy element tablica danych, otrzymane z urządzeń zewnętrznych. Nigdy nie przewidzisz, ile będzie danych, ile razy przetwarzanie zostanie powtórzone, dlatego nie będziesz w stanie wstawić wymaganej liczby instrukcji w momencie pisania artykułu.

I tu z pomocą przychodzą nam cykle.

Reguły składni

Pętla w Arduino to specjalny blok programu, który będzie wywoływany określoną liczbę razy podczas wykonywania programu. W tym bloku opisujemy same polecenia, które zostaną wywołane oraz zasady, według których kontroler określi, ile razy należy je wywołać.

W powyższym przykładzie możemy powiedzieć kontrolerowi, co następuje:

Powtórz polecenie cyfrowyZapisz 5 razy

W idealnym świecie z programistami robotów prawdopodobnie by to wystarczyło, ale skoro rozmawiamy z komputerem w C++, to musimy przetłumaczyć to zdanie na ten język:

Powtórz polecenie – należy użyć specjalnych instrukcji, które powiedzą kontrolerowi, że zaraz zacznie się coś ciekawego od pętli while lub for

cyfrowy zapis – zostaw tak, jak jest, ale napisz raz i ujmij w nawiasy klamrowe. Co zrobić z numerami pinów - zaraz poniżej.

5 razy – użyj do tego licznika, który będzie zwiększał się z każdym powtórzeniem. Na początku (lub na końcu) bloku możesz porównać wartość tego licznika z wartością graniczną (w tym przypadku 5) za pomocą operacji porównania.

Spójrzmy na przykład takiego „przetłumaczonego” polecenia pętli z instrukcją while:

Licznik int = 0; // Zmienna przechowująca wartość licznika // Prosimy procesor o powtarzanie konstrukcji w nawiasach klamrowych, aż warunek w nawiasach zwróci wartość true. // W naszym przypadku licznik jest naszym licznikiem, 5 jest wartością graniczną, warunek jest taki, aby wartość licznika była mniejsza niż 5. // Ale możemy podać zupełnie inne operatory logiczne while (licznik< 5) { digitaWrite(5, HIGH); // Будем включать светодиод counter++; // Увеличиваем значение счетчика } // Дойдя до сюда, исполняющий процессор переместится в начало блока и опять займется проверкой условий. Если условия вернут истину, команды в блоке между { и } выполнятся еще раз. Если условие не выполнится - процессор переместится к концу блока и пойдет дальше. Этот цикл больше его не заинтересует.

Tym, którzy zauważyli błąd w podanym kodzie, dajemy piątkę i inaczej zapisujemy blok pętli:

Podczas (licznik< 5) { // Вот теперь мы будем включать разные светодиоды, с 5 (0+5) по 9 (4+5) digitalWrite(counter + 5, HIGH); counter++; }

Ten sam wynik można osiągnąć za pomocą pętli FOR:

For(int licznik =0; licznik<5; counter ++){ digitalWrite(counter+5, HIGH); }

Jak widać, w tym przypadku wszystkie niezbędne operacje z licznikiem od razu umieszczamy w jednej instrukcji FOR - jest to znacznie wygodniejsze, jeśli trzeba policzyć wymaganą kwotę.

Szczegółowe informacje na temat zasad korzystania z pętli znajdziesz w odpowiednich rozdziałach tego artykułu.

Wniosek

W tym artykule przyjrzeliśmy się bardzo ważnym konstrukcjom języka Arduino: pętlom FOR i WHILE. Operatory te można znaleźć niemal w każdym mniej lub bardziej skomplikowanym szkicu, gdyż bez pętli wiele operacji na danych byłoby niemożliwych. W składni pętli nie ma nic skomplikowanego - łatwo się do nich przyzwyczaić i aktywnie wykorzystywać je w swoich projektach.

Przyjrzyjmy się, jak operatory pętli for, while i do while działają w Arduino IDE, jak poprawnie używać pętli w szkicach i jakich błędów unikać. Na prostych przykładach pokażemy, jak zatrzymać pętlę lub przejść z jednej pętli do drugiej. Aby zrozumieć poprawność zapisu cykli należy przede wszystkim zapoznać się z rodzajami i właściwościami algorytmów w robotyce.

Jak działają pętle w Arduino IDE

Dowolna pętla w C++ i języku programowania Arduino to akcja, która powtarza się wiele lub nieskończoną liczbę razy. Żaden program dla mikrokontrolera Arduino nie jest kompletny bez pętli, na przykład pusta pętla jest wywoływana w nieskończonej pętli. Istnieją trzy typy operatorów pętli: for, while i do while — przyjrzyjmy się każdemu operatorowi i zobaczmy, jak działają na przykładach.

Zasadę działania for i while można wyjaśnić na poniższych prostych przykładach. Pętla for wykonywana jest skończoną liczbę razy (wskazaną w warunku operatora); stosuje się ją wtedy, gdy program wymaga na przykład kilkukrotnego mrugnięcia diody LED. Pętla while może działać w nieskończoność, np. gdy dioda LED na Arduino będzie migać do czasu zmiany danych z czujnika.

Opis pętli for w Arduino na przykładzie

Konstrukcja for w Arduino jest zdefiniowana w następujący sposób:

for (inicjalizacja; warunek; zmiana) ( )

Pętla for służy do powtarzania określonych poleceń ujętych w nawiasy klamrowe. Cykl ten nadaje się do wykonywania dowolnych powtarzalnych czynności.
Na inicjalizacja tworzona jest zmienna i przypisywana jest jej wartość początkowa.
W stan rejestrowana jest wartość zmiennej, przy której zostanie wykonana pętla.
W zmiana wskazuje, jak zmienna będzie się zmieniać na każdym etapie pętli.

for (bajt i=0; tj<=5; i++){ digitalWrite (13, HIGH ); delay (500); digitalWrite (13, LOW ); delay (500); }

Na przykładowym szkicu ustawiona jest zmienna o wartości początkowej ja=0, warunek stwierdza, że ​​pętla będzie działać, dopóki zmienna nie będzie równa lub większa niż pięć I<=5 . Zmiana polega na tym, że zmienna będzie zwiększana o jeden w każdym kroku pętli. Na koniec pętla for kończy działanie, gdy zmienna jest równa pięć, zatem dioda LED mignie pięć razy przed zakończeniem pętli.

Zmienny krok (zmiana) może być dowolny. Jeżeli konieczne jest zwiększenie zmiennej o dwie jednostki na raz, wówczas zmianę licznika należy zapisać w następujący sposób: ja=i+2. Pętli for można użyć w procedurze konfiguracji pustej, na przykład do wskazania trybu pracy kilku pinów jednocześnie. A także w procedurze pustej pętli, na przykład w programie do sekwencyjnego włączania diod LED w Arduino.



Opis programu Arduino z pętlami for i while

Opis pętli while Arduino z przykładem

Konstrukcja while w Arduino jest zdefiniowana w następujący sposób:

podczas gdy (warunek)( // polecenia, które będą powtarzane }

Pętla while będzie działać w sposób ciągły i nieskończony, dopóki warunek w nawiasach jest prawdziwy. Wyjście z pętli zostanie osiągnięte, gdy zmienna w warunku while ulegnie zmianie, więc coś musi zmieniać jej wartość. Zmiana zmiennej może nastąpić w kodzie programu wewnątrz pętli lub podczas odczytu wartości z dowolnego czujnika, na przykład z dalmierza ultradźwiękowego HC-SR04.

bajt i=0; // należy utworzyć zmienną przed pętlą podczas gdy ja<5){ // pętla działa tak długo, jak i jest mniejsze niż 5 digitalWrite(13, WYSOKI); opóźnienie (500); digitalWrite(13, NISKI); opóźnienie (500); ja++; // zmień zmienną }

W przypadku korzystania z funkcji while zmienna musi zostać utworzona przed rozpoczęciem pętli. Na przykładowym szkicu dioda LED zamiga pięć razy przed zakończeniem cyklu. Jeśli nie zmienisz zmiennej wewnątrz nawiasów klamrowych ja++, wówczas cykl będzie się powtarzał w nieskończoność. Drugim sposobem wyjścia z pętli while Arduino Uno jest odczytanie danych z czujnika i użycie instrukcji if w celu zmiany zmiennej.

Kolejną pętlą, którą można wykorzystać w Arduino IDE, jest pętla warunku końcowego. zrobić... podczas gdy. Korzystając z tej konstrukcji, polecenia w pętli zostaną wykonane co najmniej raz, niezależnie od warunku, ponieważ warunek jest sprawdzany po wykonaniu treści pętli. W poniższym przykładzie kodu dioda LED włączy się niezależnie od odczytów czujnika i dopiero wtedy sprawdzi stan końcowy.

int woda; // utwórz zmienną przed pętlą do ( digitalWrite (13, HIGH ); woda = analogRead (AO); ) while (woda<5) // sprawdź czujnik digitalWrite(13, NISKI);

Jak wyjść z pętli while lub for

W przypadku konieczności wyjścia z ciała pętli, niezależnie od określonych warunków, stosuje się operator przerwa Lub iść do. Instrukcja break umożliwia wyjście z pętli, a program będzie kontynuował wykonywanie następujących poleceń. Instrukcja goto pozwala nie tylko wyjść z pętli, ale także kontynuować wykonywanie programu od żądanego miejsca na etykiecie, można na przykład przejść do innej pętli w Arduino.