Popularny post ethanak Napisano Kwiecień 10, 2021 Popularny post Udostępnij Napisano Kwiecień 10, 2021 Ten artykuł jest częścią serii "Arduino dla początkujących: instrukcje sterujące w C/C++" #1 - if, bloki #2 - while i coś jeszcze #3 - for, break, switch Po przebrnięciu przez pierwszą część możemy założyć, że instrukcja if nie sprawi nam już trudności. Zanim jednak przejdziemy dalej, musimy uświadomić sobie, że istnieje pewna instrukcja która z reguły nie jest omawiana w kursach i tutorialach, i stosowanie jej poza bardzo wyjątkowymi przypadkami nie jest wskazane. Instrukcja ta zaburza bowiem naturalne wykonanie programu, sprawia trudności przy czytaniu a w niektórych przypadkach albo jej wykonanie w ogóle nie będzie możliwe (kompilator od razu stwierdzi że "tak nie można"), albo może spowodować różne dziwne i niepożądane skutki uboczne. Jednak kompilator przekładając nasz program na kod maszynowy musi z niej korzystać. Czyli przed nami Podstawa ukryta, czyli "goto" W dawnych czasach, kiedy języki programowania były bardzo proste i nie zawierały w ogóle żadnych instrukcji sterujących poza ifem, stosowanie goto było po prostu koniecznością. Dobrym przykładem jest tu język BASIC, a szczególnie jego odmiana na ośmiobitowe Commodore czy Atari: jedyną możliwością zrealizowania jakichś bardziej skomplikowanych algorytmów była właśnie instrukcja skoku połączona z instrukcją if. Jednak wraz z rozwojem języków instrukcja ta odchodziła w cień i w końcu doszło do tego, że niektóre nowoczesne języki (np. Python) w ogóle takiej instrukcji ani żadnego odpowiednika nie zawierają. W C/C++ jednak pozostała, i do celów demonstracji zachowania instrukcji sterujących możemy jej użyć. Zapis tej instrukcji jest prosty: goto etykieta; // kontynuujemy wykonanie programu od innego miejsca // tu jakiś fragment programu etykieta: // program po wykonaniu goto "przeskoczy w to miejsce" // dalsza część programu Wyobraźmy teraz sobie, że instrukcja if nie może zawierać innej instrukcji niż goto. Spróbujmy rozpisać sobie prostą instrukcję if zawierającą obie gałęzie: if (WARUNEK) goto etykieta1; // skaczemy do fragmentu wykonywanego po spełnieniu warunku // tu fragment wykonywany w else, czyli przy niespełnionym warunku goto etykieta2; // po wykonaniu musimy pominąć fragment programu etykieta1: // tu fragment programu wykonywany przy spełnionym warunku etykieta2: // i koniec instrukcji if Skomplikowane? Niestety, trochę. Ale bez zrozumienia tej konstrukcji nie możemy zrozumieć kolejnych, a taką będzie Najprostsza pętla, czyli instukcja "while" Instrukcja zapisywana jest jako: while (WARUNEK) INSTRUKCJA; Wykonuje się ona bardzo prosto: jeśli warunek jest spełniony, następuje wykonanie INSTRUKCJA i powrót do testowania warunku. Jeśli warunek nie jest wpełniony, wykonanie instrukcji kończy się. Diagram wykonania takiej instrukcji jest stosunkowo prosty: Aby lepiej zrozumieć działanie, rozpiszmy to sobie z użyciem instrukcji goto: etykieta: if (WARUNEK) { INSTRUKCJA; goto etykieta; } I tu uwaga: trzeba pamiętać o tym, że WARUNEK musi być zależny od czynników zewnętrznych, albo INSTRUKCJA w jakiś sposób musi wpływać na to, czy w następnym obrocie pętli warunek jest spełniony. Takim sztandarowym przykładem będzie tu odczytanie stanu pinu (np. wciśnięcia klawisza): while (digitalRead(BUTTON_PIN) == LOW) { // tu jakiś fragment wykonywany dopóki klawisz jest wciśnięty } Możemy spróbować napisać jakiś program, który będzie wykorzystywać tę instrukcję, przykładowo: #define BUTTON_PIN 2 #define LED_PIN 13 void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); // ustawiamy pin jako wejście z podciągnięciem do Vcc pinMode(LED_PIN, OUTPUT); //ustawiamy pin jako wyjście digitalWrite(LED_PIN, LOW); // i ustawiamy stan niski na pinie } void loop() { while (digitalRead(BUTTON_PIN) == LOW) { dopóki przycisk jest wciśnięty digitalWrite(LED_PIN, HIGH); // zapalamy ledę delay(250); // czekamy ćwierć sekundy digitalWrite(LED_PIN, LOW); // gasimy ledę delay(250); // czekamy ponownie } } Odmianą instrukcji while jest instrukcja do. Podstawową różnicą jest ta, że sprawdzenie warunku odbywa się po wykonaniu "wnętrza" instrukcji, czyli nasza INSTRUKCJA będzie wykonana co najmniej raz. Ze względu na podobieństwo nie będziemy się teraz bliżej nią interesować. Ale przy okazji możemy dowiedzieć się nowej rzeczy. Otóż - jak wspomniano na początku - WARUNEK musi być wyrażeniem zwracającym wartość. Trzeba wiedzieć, że instrukcja podstawienia w C/C++ również zwraca wartość - tę mianowicie, która została podstawiona. W wielu przypadkach może to uprościć program. Przykładowo - chcemy, aby jakiś fragment programu wykonywał się dopóki wynik odczytany z wejścia analogowego przekracza jakąś wartość, ale we wnętrzu pętli chcielibyśmy mieć dostęp do tego wyniku. Możemy to zapisać w ten sposób: void setup() { Serial.begin(9600); } void loop() { int x; while ((x = analogRead(A0)) > 500) { Serial.println(x); delay(500); } } Jeśli teraz podłączymy potencjometr do naszego Arduino, obracając jego ośką zobaczymy, że na monitorze będą wypisywane wyłącznie wartości większe od 500. Tyle w części drugiej, w następnej rozpracujemy działanie pętli for oraz instrukcji wyboru switch. 7
Treker (Damian Szymański) Kwiecień 12, 2021 Udostępnij Kwiecień 12, 2021 @ethanak wpis został właśnie zaakceptowany i jest już widoczny publicznie
Gieneq Kwiecień 12, 2021 Udostępnij Kwiecień 12, 2021 @ethanak też ciekawy artykuł, masz może w planach napisać coś o nazywanym przez początkujących "tworzeniu podprogramów w Arduino". Coś dosadnego że jak chcesz mieć 2 "programy" to zrób if/switch-case w pętli głównej i sobie przełącznikiem zmieniaj - raz ten raz ten. I wtedy kontynuacja z użyciem millis/timerów i tworzenia zadań jakby równoległych.
ethanak Kwiecień 12, 2021 Autor tematu Udostępnij Kwiecień 12, 2021 @Gieneq Można by było spróbować - zobaczymy. To taki trochę obszerny temat - podprogramy, quasi-równoległe wykonywanie zadań. Chyba raczej jako "następny etap wtajemniczenia po początkującym" No, ale tu muszę trochę pomyśleć, jak (a przede wszystkim co) pokazać tak, aby każdy mógł to bez problemu zrozumieć. 1
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »