Skocz do zawartości
Komentator

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

Pomocna odpowiedź

Napisałem program demonstrujący działanie świateł, chodzi o to aby światła można było wyłączyć i włączyć w trakcie pracy przyciskiem. Zastanawiam się czy można by go jeszcze ulepszyć główny mankament według mnie to aby wyłączyć światła trzeba czekać na zakończenie działania pętli czy da się to zrobić tak aby móc wyłączyć światła w dowolnym momencie? Ciekawi mnie również czy da się napisać taki program z wykorzystaniem dwóch pętli zamiast trzech 🙂 Poniżej zamieszczam kopie kodu.

void setup() {

pinMode(10, OUTPUT); //Dioda czerwona

pinMode(9, OUTPUT); //Dioda żółta

pinMode(8, OUTPUT); //Dioda zielona

pinMode(2, INPUT_PULLUP); //Przycisk

digitalWrite(10, LOW); //Wyłączenie diod

digitalWrite(9, LOW);

digitalWrite(8, LOW);

}

void loop()

{

while(digitalRead(2)==HIGH){

digitalWrite(10, LOW); //Czerwona

digitalWrite(9, LOW); //Pomarańczowa

digitalWrite(8, LOW); //Zielona}

}delay(1000);

while(digitalRead(2)==HIGH){

digitalWrite(10, LOW); //Czerwona

digitalWrite(9, LOW); //Pomarańczowa

digitalWrite(8, HIGH); //Zielona

delay(1000); //Czekamy 3 sekundę

digitalWrite(10, LOW); //Czerwona

digitalWrite(9, HIGH); //Pomarańczowa

digitalWrite(8, LOW); //Zielona

delay(1000); //Czekamy 1 sekundę

digitalWrite(10, HIGH); //Czerwona

digitalWrite(9, LOW); //Pomarańczowa

digitalWrite(8, LOW); //Zielona

delay(1000); //Czekamy 3 sekundę

digitalWrite(10, HIGH); //Czerwona

digitalWrite(9, HIGH); //Pomarańczowa

digitalWrite(8, LOW); //Zielona

delay(1000); //Czekamy 1 sekundę

}delay(1000);

while(digitalRead(2)==LOW){

digitalWrite(10, LOW); //Czerwona

digitalWrite(9, LOW); //Pomarańczowa

digitalWrite(8, LOW); //Zielona}

}

}

__________

Komentarz dodany przez: Treker

Kody programów należy umieszczać przez narzędzie KOD (znajdziesz je w edytorze pod ikonką "<>"). Dzięki niemu składania programów jest automatycznie kolorowana, a wtedy wszystkim znacznie łatwiej analizować wklejone programy. Proszę to poprawić - z góry dziękuję za zrozumienie i pomoc przy utrzymaniu porządku na forum.

Udostępnij ten post


Link to post
Share on other sites

dexu, witam na forum 🙂 Pamiętaj, aby kody programów obejmować tagami -

ułatwi to wszystkim czytanie programów. Jeśli chciałbyś, aby program reagował natychmiast to należałoby zainteresować się tematami, które są opisane w drugim poziomie kursu Arduino. Problem ten można rozwiązać za pomocą przerwań (Kurs Arduino II – #4 – przerwania, kontaktron, czujnik PIR) lub funkcją millis (Kurs Arduino II – #9 – wielozadaniowość, opóźnienia z millis()).

Udostępnij ten post


Link to post
Share on other sites

Funkcje można pisać samodzielnie, może również korzystać z gotowych, dostarczanych przez producentów lub przez maniaków programowania, którzy zechcieli podzielić się własnym kodem. (można)?

Każda funkcja ma swój typ - (czyli rodzaj wynik) może być liczbą, znakiem lub czymś jeszcze innym. (czyli rodzaj zwracanego wyniku)?

Znajdują się w niej instrukcje, które powinny wykonywać się bez przerwy. (wstawimy delay(x) i instrukcje będą się wykonywać z przerwami; zależy jak to zinterpretujemy)?

Za nim jednak do tego dojdziemy musimy poznać wyprowadzenie złącz oraz odpowiednie funkcje, które służą do operowania na portach I/O (Input/Output), czyli na portach wejścia/wyjścia. (zanim)?

Oznacza, to że właśnie za ich pomocą możemy przykładowo sterować diodami lub odczytywać informacje z prostych czujników/przycisków. (przecinek dopiero przed "że")?

SDA, SCL - wyprowadzenia magistrali I2C, wykorzystywana np.: do komunikacji z bardziej zaawansowanymi czujnikami, (wykorzystywanej lub która jest wykorzystywana)?

Na początek wybierzmy wyjście cyfrowe o nr 8. (bez "o" skoro wykorzystany jest skrót)?

Naszym głównym celem będzie napisanie programu, który po wciśnięciu przycisku wyświetli kolejną, poprawną sekwencje świateł. (sekwencję)?

2. Wchodzimy w pętlę while(), które jest tuż poniżej. (która)?

Mam nadzieje, że zauważyłeś równie, że często warto rozbić program na kilka etapów zamiast od razu pisać "pełną funkcjonalność". (nadzieję, również)?

__________

Komentarz dodany przez: Treker

Zmiany wprowadzone - dziękuję za zgłoszenie 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

vst, dziękuję za zgłoszenie błędów (oraz te z drugiego tematu również). Kurs ma już kilka lat, zabieramy się za jego odświeżanie. Wtedy wszystkie błędy zostaną usunięte na 100%. Oczywiście Twoje poprawki naniosę szybciej 😉

Udostępnij ten post


Link to post
Share on other sites

Cytat z 2 części kursu przy opisywaniu pętli while:

"Prawdopodobnie pomyślałeś tutaj o instrukcji warunkowej if. Jednak jak chciałbyś zrealizować miganie diodą?"

W związku z tym mam pytanie, jaka jest różnica w stosowaniu pętli while i instrukcji if, skoro można to samo zrealizować za pomocą if i while, przynajmniej w przypadku migania diod?

/* Osiem diod miga na zmianę co sekundę: 
*  najpierw: z pinów 2,4,6,8, a następnie 3,5,7,9.
*  po wcisnięciu przycisku zwiększa się prędkość migania do 100 ms
*/
void setup()  {
 pinMode (2, OUTPUT); // ustawienie pinów jako wyjscie
 pinMode (3, OUTPUT);
 pinMode (4, OUTPUT);
 pinMode (5, OUTPUT);
 pinMode (6, OUTPUT);
 pinMode (7, OUTPUT);
 pinMode (8, OUTPUT);
 pinMode (9, OUTPUT);
 pinMode (11, INPUT_PULLUP); // wejscie z podciagnieciem do Vcc
}
void loop() {

 if (digitalRead(11) == LOW)/* jesli przycisk jest wcisniety, diody migają 
 z szybkoscia 100 ms. */
 {
 digitalWrite (2, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (6, HIGH);
 digitalWrite (8, HIGH);
 digitalWrite (3, LOW);
 digitalWrite (5, LOW);
 digitalWrite (7, LOW);
 digitalWrite (9, LOW);
 delay (100);
 digitalWrite (3, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (7, HIGH);
 digitalWrite (9, HIGH); 
 digitalWrite (2, LOW);
 digitalWrite (4, LOW);
 digitalWrite (6, LOW);
 digitalWrite (8, LOW);
 delay (100);
  } else /*jesli przycisk nie jest wcisniety, diody mrugają na zmiane 
 co sekundę */
 {
   digitalWrite (2, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (6, HIGH);
 digitalWrite (8, HIGH);
 digitalWrite (3, LOW);
 digitalWrite (5, LOW);
 digitalWrite (7, LOW);
 digitalWrite (9, LOW);
 delay (1000);
 digitalWrite (3, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (7, HIGH);
 digitalWrite (9, HIGH); 
 digitalWrite (2, LOW);
 digitalWrite (4, LOW);
 digitalWrite (6, LOW);
 digitalWrite (8, LOW);
 delay (1000);
 }
}

i z wykorzystaniem pętli while:

/* Osiem diod miga na zmianę co sekundę: 
*  najpierw: z pinów 2,4,6,8, a następnie 3,5,7,9.
*  po wcisnięciu przycisku zwiększa się prędkość migania do 100 ms
*/
void setup()  {
 pinMode (2, OUTPUT); // ustawienie pinów jako wyjscie
 pinMode (3, OUTPUT);
 pinMode (4, OUTPUT);
 pinMode (5, OUTPUT);
 pinMode (6, OUTPUT);
 pinMode (7, OUTPUT);
 pinMode (8, OUTPUT);
 pinMode (9, OUTPUT);
 pinMode (11, INPUT_PULLUP); // wejscie z podciagnieciem do Vcc
}
void loop() {

 while (digitalRead(11) == LOW)/* jesli przycisk jest wcisniety, diody migają 
 z szybkoscia 100 ms. */
 {
 digitalWrite (2, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (6, HIGH);
 digitalWrite (8, HIGH);
 digitalWrite (3, LOW);
 digitalWrite (5, LOW);
 digitalWrite (7, LOW);
 digitalWrite (9, LOW);
 delay (100);
 digitalWrite (3, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (7, HIGH);
 digitalWrite (9, HIGH); 
 digitalWrite (2, LOW);
 digitalWrite (4, LOW);
 digitalWrite (6, LOW);
 digitalWrite (8, LOW);
 delay (100);
  } 

   digitalWrite (2, HIGH);
 digitalWrite (4, HIGH);
 digitalWrite (6, HIGH);
 digitalWrite (8, HIGH);
 digitalWrite (3, LOW);
 digitalWrite (5, LOW);
 digitalWrite (7, LOW);
 digitalWrite (9, LOW);
 delay (1000);
 digitalWrite (3, HIGH);
 digitalWrite (5, HIGH);
 digitalWrite (7, HIGH);
 digitalWrite (9, HIGH); 
 digitalWrite (2, LOW);
 digitalWrite (4, LOW);
 digitalWrite (6, LOW);
 digitalWrite (8, LOW);
 delay (1000);

} 

Udostępnij ten post


Link to post
Share on other sites

Różnica jest ogromna. Instrukcja if to instrukcja warunkowa, która pozwala nam sprawdzić czy zaszły pewne okoliczności. While to pętla, dzięki której możemy wykonywać kilka operacji (nie)skończoną liczbę razy.

Zastanów się jak działają Twoje programy. Gdy używasz pętli while, to w momencie wciśnięcia przycisku, Arduino zaczyna wykonywać w koło tylko ten kod, który znajduje się wewnątrz tej pętli (miga diodami). W momencie puszczenie przycisku program wychodzi z tej pętli i robi pozostałe instrukcje. Druga wersja programu (z if'em) działa w taki sposób, że w każdym obiegu pętli loop() sprawdzany jest warunek i wykonywana jest odpowiednia część kodu, a oprócz tego wykonywany jest pozostały kod z pętli loop().

Programy nie robią nic więcej, więc w tym wypadku działają identycznie. Jednak jeśli w pętli loop() (poza while/if) byłoby cokolwiek innego to działały by już inaczej. Przy while fragment kodu poza tą pętlą nie byłby wykonywany jeśli przycisk byłby wciśnięty. W przypadku if'a wciskanie przycisku nie robiłoby żadnej różnicy - kod poza warunkiem i tak zawsze by się wykonywał (bo jest wewnątrz loop).

Udostępnij ten post


Link to post
Share on other sites

Witam, mam pytanie odnośnie stanu HIGH/LOW przycisku.

Przestudiowałem dosyć uważnie rozdział II kursu Arduino oraz odpowiedzi, które zostały udzielone na forum na różne pytania ale nie znalazłem odpowiedzi na moje pytanie.

Pytanie brzmi:

Dlaczego w kursie w przykładowych programach jest raz przypisany stan wysoki (HIGH), a raz stan niski (LOW) dla wciśniętego przycisku?

Odpowiedź na forum, która jest najbardziej właściwa i zgodna z prawdą to:

igor,
while(digitalRead(7)==HIGH)

oznacza tyle, że jeśli przycisk nie jest wciśnięty, to program sobie biega w tej pętli tak długo dopóki, dopóty nie wciśniesz go z powrotem, jak już go naciśniesz, to pętlę omija, bo jej warunek nie jest spełniony, innymi słowami trzymając przycisk wciśnięty cały czas, pętle while w tym kodzie są po prostu omijane. Chyba, że się mylę, to niech mnie ktoś poprawi.

Nie mniej jednak w dwóch miejscach przykładowych programów mam sprzeczne informacje.

Oto wersja pierwsza (z którą się zgadzam):

void setup() {
 pinMode(8, OUTPUT); //Dioda jako wyjście
 pinMode(7, INPUT_PULLUP); //Przycisk jako wejście
 :arrow:  digitalWrite(8, LOW); //Wyłączenie diody
}

void loop()
{
 if (digitalRead(7) == LOW) { //Jeśli przycisk wciśnięty
   digitalWrite(8, HIGH); //Włącz diodę
   delay(10000); //Czekamy 10 sekund
   digitalWrite(8, LOW); //Wyłączamy diodę
 }
}

A to wersja druga, która tak bardzo miesza mi w głowie:

void setup() {
 pinMode(10, OUTPUT); //Dioda czerwona
 pinMode(9, OUTPUT); //Dioda żółta
 pinMode(8, OUTPUT); //Dioda zielona

 pinMode(7, INPUT_PULLUP); //Przycisk

 digitalWrite(10, LOW); //Wyłączenie diod
 digitalWrite(9, LOW);
 digitalWrite(8, LOW);
}

void loop()
{
 digitalWrite(10, LOW); //Czerwona
 digitalWrite(9, LOW); //Pomarańczowa
 digitalWrite(8, HIGH); //Zielona

 delay(1000); //Zatrzymujemy program przed wejsciem do pętli na 1 sekunde
 while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty 

 digitalWrite(10, LOW); //Czerwona
 digitalWrite(9, HIGH); //Pomarańczowa
 digitalWrite(8, LOW); //Zielona

 delay(1000); //Zatrzymujemy program przed wejsciem do pętli na 1 sekunde
 while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty 

 digitalWrite(10, HIGH); //Czerwona
 digitalWrite(9, LOW); //Pomarańczowa
 digitalWrite(8, LOW); //Zielona

 delay(1000); //Zatrzymujemy program przed wejsciem do pętli na 1 sekunde
 while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty 

 digitalWrite(10, HIGH); //Czerwona
 digitalWrite(9, HIGH); //Pomarańczowa
 digitalWrite(8, LOW); //Zielona

 delay(1000); //Zatrzymujemy program przed wejsciem do pętli na 1 sekunde
 while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty 
}

I teraz jak to rozumieć?

if (digitalRead(7) == LOW) { //Jeśli przycisk wciśnięty

czy

while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty

W przykładzie drugim programu, który wkleiłem jest pętla while (digitalRead(7) == HIGH) {}, która nie pozwala na kontynuowanie kodu ponieważ przycisk nie jest wciśnięty. Wciśnięcie przycisku pozwala na zmianę świateł.

Gdy zmienię while (digitalRead(7) == LOW) {} to wtedy program nie zatrzymuje się do momentu wciśnięcia przycisku.

Generalnie musiałem się cofnąć z rozdziału 5 do początku bo mi się już wszystko z tego programowania pomieszało 😋

Bardzo fajny kurs!

Udostępnij ten post


Link to post
Share on other sites

leidan88, wszystko się zgadza, może po prostu ten komentarz jest dla Ciebie mylący:

while (digitalRead(7) == HIGH) {} //Jeśli przycisk jest wciśnięty 

Lepiej byłoby gdyby brzmiał "Jeśli przycisk wciśnięty to idź dalej". Jeśli podłączamy przycisk do masy, czyli w 99% przypadków to jego wciśnięcie zawsze oznacza stan niski na wejściu Arduino. W przypadku cytowanej pętli while program się zatrzymuje (kręci się w pustej pętli while) tak długo, jak długo na wejściu jest stan wysoki. Czyli po wciśnięciu przycisku (stan niski, LOW) program wyjdzie z pętli i pójdzie dalej.

Linijkę tę można również zapisać tak:

while (digitalRead(7) != LOW) {}

Może taka wersja będzie mniej myląca 🙂?

Udostępnij ten post


Link to post
Share on other sites

Dzięki za odpowiedź "Treker" ale jednak ciężko jest mi to jeszcze wszystko objąć "moim" kompilatorem.

Rękawic jeszcze nie składam i uczę się dalej! 🙂

Udostępnij ten post


Link to post
Share on other sites

ma 10 lat i zaczynam programować ... wow

jedyny kurs z którego da się czegos dowiedzieć

Udostępnij ten post


Link to post
Share on other sites

kirysiomik2, miło słyszeć - powodzenia w nauce programowania 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam wszystkich użytkowników forum.

Mam pytanie - nie bardzo rozumiem dlaczego wciśnięty przycisk generuje sygnał typu LOW,
przecież właśnie zwarcie (wg mnie) powinno powodować przesłanie sygnału HIGH do Arduino i trochę to zaburzyło moje dotychczasowe rozumowanie, tj : jakikolwiek sygnał = HIGH, jego brak = LOW.

Udostępnij ten post


Link to post
Share on other sites

Grzesiek,

odnośnie Twojego pytania: Pin D7 na Arduino jest ustawiony jako wejście, czyli pobiera dane z otoczenia. Gdyby nie dochodziłby żaden sygnał, to ten pin D7 zbierałby szumy z otoczenia i odczyt (HIGH czy LOW) byłby przypadkowy. Aby temu zapobiec, w programie ustawiono ten pin jako INPUT_PULLUP, czyli wejście, które jest podciągnięte do góry, czyli do 5V (HIGH). Dlatego, kiedy przycisk nie jest wciśnięty, dochodzi do niego sygnał HIGH. Natomiast po wciśnięciu przycisku pin D7 zostaje zwarty do GND (0V), i dlatego odczytuje sygnał niski. W zrozumieniu zasady działania przycisków podciągniętych do góry pomoże Ci ta ilustracja z tego tematu: link

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
Mam pytanie - nie bardzo rozumiem dlaczego wciśnięty przycisk generuje sygnał typu LOW, przecież właśnie zwarcie (wg mnie) powinno powodować przesłanie sygnału HIGH do Arduino i trochę to zaburzyło moje dotychczasowe rozumowanie, tj : jakikolwiek sygnał = HIGH, jego brak = LOW.

Jeśli wciśnięcie przycisku miałoby wywoływać stan wysoki (HIGH), to musiałby zwierać wejście Arduino z VCC, a nie z masą. W tej chwili przycisk zwiera wejście z masą, czyli właśnie po wciśnięciu na wejściu mamy wtedy "brak napięcia" (LOW).

Udostępnij ten post


Link to post
Share on other sites

Witam Wszystkich 🙂

Jestem już po pierwszym kursie podstaw elektroniki (dzięki).

Teraz na podstawach Arduino coś się zablokowałem... Poproszę o pomoc 🙂

Wydaje mi się, że wszystko wpisałem poprawnie, ale pokazuje mi błąd.

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...