Skocz do zawartości

Kurs Arduino - #2 - podstawy programowania, porty I/O


Pomocna odpowiedź

17 godzin temu, dastawowy napisał:

le czy to oznacza że jak się wychodzi z pętli while to program "pamięta" ostatnią komendę pętli?

@dastawowy nie tyle co "pamięta", tylko jeśli nie zmieniłeś nigdzie stanu diody to dlaczego miałaby zgasnąć? 😉 Ostatnim Twoim poleceniem w pętli jest "włącz diodę". Więc przed wyjściem z pętli jest ona włączana i tyle. Nigdzie poza pętlą jej nie gasisz, więc nie ma żadnych podstaw, aby była ona wyłączana. Jeśli chcesz, abyś się gasiła to musisz odwrócić kolejność poleceń w pętli (najlepiej) lub po prostu gasić diodę po wyjściu z pętli while.

  • Pomogłeś! 1

Podczas uruchamiania programu bazującego po części na światłach drogowych z kursu (moja wersja za naciśnięciem jednego z dwóch przycisków przełącza pojedyncze ledy cyklicznie w jednym lub drugim kierunku) na innym sprzęcie niż Arduino (konkretnie NodeMCU v3) zauważyłem ciekawe problemy, jestem ciekaw czy występują również w przypadku Arduino (niestety nie posiadam jeszcze płytki Arduino, tak że sam nie mam jak przetestować):

- pusta pętla while powoduje zawieszenie się i reset płytki (na wyjściu szeregowym widać ciągłe restarty poprzedzone komunikatem błędu) - rozwiązaniem jest zaimplementowanie obsługi przycisków z użyciem if zamiast while

- rezystory podciągające dla niektórych pinów na płytce są zbyt słabe, przez co input przycisku ma losowe wartości mimo użycia INPUT_PULLUP - pomaga dołączenie własnego rezystora podciągającego

- niektóre piny w trakcie uruchamiania się płytki mają wymuszone startowe wartości (lub wręcz inne działanie), przez co próba uruchomienia płytki w pewnych teoretycznie poprawnych konfiguracjach może się zakończyć niepowodzeniem (np. jeśli płytka podczas startu na danym pinie wymusza stan niski, a logika naszego układu wymusza wysoki, to płytka/program się w ogóle nie uruchomi)

4 godziny temu, Przemat napisał:

pusta pętla while powoduje zawieszenie się i reset płytki (na wyjściu szeregowym widać ciągłe restarty poprzedzone komunikatem błędu)

Poszukaj sobie coś na temat funkcji yield().

Watchdog jest resetowany za każdym wyjściem z loop oraz przy delay i yield. Jeśli przez jakiś czas foop wykonuje się zbyt długo - watchdog stwierdza że coś się pewnie zawiesiło i robi reset. Można oczywiście wyłączyć watchdoga, ale prościej jest zapisać pętlę jako:

while (cośtam) delay(1);

albo

while (cośtam) yield();

 

4 godziny temu, Przemat napisał:

rezystory podciągające dla niektórych pinów na płytce są zbyt słabe,

Jak mniemam chodzi o GPIO16 (czyli D0)?

4 godziny temu, Przemat napisał:

niektóre piny w trakcie uruchamiania się płytki mają wymuszone startowe wartości (lub wręcz inne działanie)

I dlatego zanim zacznie się pisać program na daną płytkę warto poczytać, jak ona działa. Na forum wszystko było wyjaśniane po pięć razy.

 

1 godzinę temu, ethanak napisał:

Poszukaj sobie coś na temat funkcji yield().

Ooo, tego nie znałem, dzięki, przyda się 🙂

1 godzinę temu, ethanak napisał:

Jak mniemam chodzi o GPIO16 (czyli D0)?

1 godzinę temu, ethanak napisał:

I dlatego zanim zacznie się pisać program na daną płytkę warto poczytać, jak ona działa. Na forum wszystko było wyjaśniane po pięć razy.

 

I tak zrobiłem 😉 O D0 wiedziałem już wcześniej (korzystam z tej ściągawki), problemy z INPUT_PULLUP sprawił mi port D8 (GPIO15) - pomocny okazał się wpis na Arduino Stackexchange.

 

  • 2 miesiące później...

nie wiem czy coś mi nie działa czy co, ale nie widzę różnicy pomiędzy działaniem programu  z nawiasami klamrowymi które miały powodować czekanie programu czy bez nich - dla pewności, że mam dobrze napisany program skopiowałem go z kursu

Aktualizacja:

Pytanko:

jak to się dzieje, że na tym obrazku jest przycisk i jeśli go wciśniemy to mamy stan niski, a jeśli nie wciśniemy to wysoki - nie rozumiem skąd się bierze różnica potencjałów = 5V gdy przycisk nie jest wciśnięty (gdy napięcie mierzymy między jednym a drugim wyprowadzeniem przycisku).

obraz.png

@YURYS witam na forum 🙂 Jeśli chodzi o pierwsze pytanie to umieść proszę dokładny kod oraz pokaż swój układ (wystarczy zdjęcie) - łatwiej będzie pomóc. Jeśli chodzi o drugą kwestię to wynika to z faktu konfiguracji danego wejścia jak INPUT_PULLUP, oznacza to, że włączony został wewnętrzny rezystor podciągający - w takiej sytuacji brak zwarcia wejścia do masy będzie intepretowany właśnie jako 5 V. Pomocny w zrozumieniu tego tematu może być ten krótki wpis, który wyjaśnia czym jest rezystor pull-up.

  • Pomogłeś! 1
3 godziny temu, Treker napisał:

 

3 godziny temu, Treker napisał:

 Jeśli chodzi o drugą kwestię to wynika to z faktu konfiguracji danego wejścia jak INPUT_PULLUP, oznacza to, że włączony został wewnętrzny rezystor podciągający - w takiej sytuacji brak zwarcia wejścia do masy będzie intepretowany właśnie jako 5 V. Pomocny w zrozumieniu tego tematu może być ten krótki wpis, który wyjaśnia czym jest rezystor pull-up.

Witam. Reasumując część układu którą zaznaczyłem na czerwonoobraz.thumb.png.cf266616a584dd20f51cc8c2499c2380.png znajduje się w Arduino i automatycznie zaczyna działać gdy program dojdzie do rozkazu zawierającego "INPUT_PULLUP" ?

 

(Na pierwszy problem znalazłem odpowiedź)

(edytowany)

Chyba nie do konca rozumiem różnice między pętlą if a while, mógłbyś jakos inaczej "łopatologicznie" objaśnić?

Mianowicie chcialem przerobić program, by działał jak sygnalizacja świetlna z dodatkiem przycisku w ten sposób, aby przycisk działał na zasadzie, naciśnięcia go przez "przechodnia" by pojawiło mu się zielone światło na pasach. W programie mam, że światło zielone przez 10s, potem pomarańcz i zmiana na czerwone (i tak w kółko gdy przycisk nie został naciśnięty.) Nie wiem jak uzyc pętli, aby po naciśnięciu przycisku, po 5 sekundach światło zmieniło się na pomarańczowe i dalej na czerwone i na czerwonym było określony czas i po tym, aby program dalej sam działał poza pętla while.

Edytowano przez matiowoz98

@matiowoz98 witam na forum 🙂 

17 godzin temu, matiowoz98 napisał:

Chyba nie do konca rozumiem różnice między pętlą if a while,

Podstawowa różnica, to że if to warunek a while to pętla 😉 

If to takie rozdroże, zrób tak lub tak, a while to pętla z takim rozdrożem - coś jak zjazd z ronda - jedziesz w kółko szukając znaku Warszawa - znajdziesz, to zjeżdżasz na Warszawę.

@Gieneq Mimo wielu prób, to chyba nadal nie pojmuję.. próbowałem zastosować pętlę "goto" ale nie wiem jak zadeklarować w niej słowo, do którego ma program przejść i w tym słowie, aby program wiedział co ma robić.. Mianowicie próbuję do sygnalizacji świetlnej dodać, aby po kliknieciu przycisku, program zaczął wykonywać pewien program i po wykonaniu go jednorazowo, wrócił do  miejsca wykonywnania, gdzie przycisk nie został wcisniety.

W skrócie ( Światła działąją w odstępach czasowych, dopóki osoba przed pasami nie nacisnie przycisku, aby włączyć sobie zielone, by przejść. Po wcisnieciu przycisku chcialem, by po 5 sekundach program przeszedł do tego co mam w IF, po wykonaniu przeszedł spowrotem do ELSE.

Przepraszam też za moje trudności, w zrozumieniu tego.

void setup()
{
pinMode(7,INPUT_PULLUP); // przycisk

pinMode(8, OUTPUT); //dioda zielona
pinMode(9, OUTPUT); //dioda żółta
pinMode(10,OUTPUT); //dioda czerwona

digitalWrite(8, LOW); // \
digitalWrite(9, LOW); //  wyłączenie diod
digitalWrite(10,LOW); // /

}

void loop() 
{
    
if (digitalRead(7) == LOW) { //jesli przycisk wcisniety
 delay(5000);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,HIGH); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona
delay(2500);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,LOW); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona
delay(5000);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,HIGH); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona
delay(2500);

}

else (digitalRead(7) == HIGH); { //jesli przycisk NIE wcisniety
delay(2500);
digitalWrite(8,HIGH); //dioda zielona
digitalWrite(9,LOW); //dioda zolta
digitalWrite(10,LOW); //dioda czerwona
delay(5000);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,HIGH); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona
delay(2500);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,LOW); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona
delay(5000);
digitalWrite(8,LOW); //dioda zielona
digitalWrite(9,HIGH); //dioda zolta
digitalWrite(10,HIGH); //dioda czerwona

}
}


 
  

 

23 minuty temu, matiowoz98 napisał:

próbowałem zastosować pętlę "goto"

A tego nie wolno robić - od tego masz wszystkie ify, while, switche i tak dalej abyś nie musiał się w to bawić. W artykule użyłem "goto" aby pokazać jak działa np. while, i tylko po to.

Tak przy okazji:

else (digitalRead(7) == HIGH); { //jesli przycisk NIE wcisniety

Co to ma znaczyć?

Twój program działa tak:

  • jeśli przycisk jest wciśnięty, wykonaj pewną sekwencję; w przeciwnym wypadku nie rób nic, tylko porównaj sobie stan przycisku z wartością HIGH i natychmiast o tym zapomnij.
  • niezależnie od stanu przycisku wykonaj drugą sekwencję.

Jesteś pewien, że o to Ci chodziło?

Rozpisz sobie słownie to co ma robić program (tak jak ja parę linijek wyżej) a potem dopiero przełóż na kod.

  • Pomogłeś! 1

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ę »
×
×
  • Utwórz nowe...