Skocz do zawartości
Komentator

Kurs Arduino - #3 - UART (komunikacja z PC), zmienne

Pomocna odpowiedź

Zrobiłem tak na początku ale jest to błędne, zauważ, że jeśli wpiszesz słowo "zielona" to warunek z czerwoną diodą nie zostanie spełniony więc zadziała funkcja else i wyświetli komunikat o złym kolorze mimo, że był dobry.

To pomyśl jak to inaczej rozwiązać 🙂 Np.: informacja o złym kolorze powinna być uzależniona od 3 warunku (i zmiennej pomocniczej) lub można połączyć warunki w taki sposób:

    if (odebraneDane == "zielona") { //Jeśli odebrano słowo "zielona" 
     digitalWrite(zielona, HIGH); //To włączamy diodę zieloną 
     delay(1000); 
     digitalWrite(zielona, LOW); 
   } else if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona" 

Udostępnij ten post


Link to post
Share on other sites
Zrobiłem tak na początku ale jest to błędne, zauważ, że jeśli wpiszesz słowo "zielona" to warunek z czerwoną diodą nie zostanie spełniony więc zadziała funkcja else i wyświetli komunikat o złym kolorze mimo, że był dobry.

To pomyśl jak to inaczej rozwiązać 🙂 Np.: informacja o złym kolorze powinna być uzależniona od 3 warunku (i zmiennej pomocniczej) lub można połączyć warunki w taki sposób:

    if (odebraneDane == "zielona") { //Jeśli odebrano słowo "zielona" 
     digitalWrite(zielona, HIGH); //To włączamy diodę zieloną 
     delay(1000); 
     digitalWrite(zielona, LOW); 
   } else if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona" 

Poradziłem sobie z tym zadaniem dokładnie w taki sposób (nie ukrywam że podejrzałem jakiś z wcześniejszych komentarzy myśląc, że mój sposób również zadziała, więc później miałem już gotowy pomysł) nie zdążyłem tego oznajmić bo tak wciągnęło mnie zadanie 2.5 które mi prawie działa:

jeśli włączę czerwoną diodę i następnie zieloną to wszystko jest OK, a jak włączę diodę zieloną to później mogę tylko ją włączać lub wyłączać.

Oto mój kod:

#define zielona 8
#define czerwona 9

String odebraneDane = ""; //Pusty ciąg odebranych danych
boolean ziel = "";
boolean czer = "";

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
  ziel = false;
  czer = false;
}

void loop() {
 if(Serial.available() > 0) { //Czy Arduino odebrano dane
   //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej odebraneDane
   odebraneDane = Serial.readStringUntil('\n'); 

   if (odebraneDane == "zielona") { //Jeśli odebrano słowo "zielona"
     if (ziel == false) { // jeśli zielona dioda jest wyłączona
       digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
     ziel = true; // pokazujemy, że dioda jest włączona
     } else { // jeśli dioda jest włączona
       digitalWrite(zielona, LOW); //To wyłączamy diodę zieloną
     ziel = false; //  pokazujemy, że dioda zielona jest wyłączona
     }
     }

 if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona"
     if (czer == false) { // jeśli czerwona dioda jest wyłączona
       digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
     czer = true; // pokazujemy, że dioda jest włączona
     } else { // jeśli dioda jest włączona
       digitalWrite(czerwona, LOW); //To wyłączamy diodę czerwoną
     ziel = false; //  pokazujemy, że dioda czerwona jest wyłączona
     }
     }

     }
     }

Udostępnij ten post


Link to post
Share on other sites

Razor1996, po pierwsze zadbaj o poprawne wcięcia w kodzie. Teraz ciężko zrozumieć dokąd sięga który warunek. Nie ignoruj wcięć 😉

Udostępnij ten post


Link to post
Share on other sites
Razor1996, po pierwsze zadbaj o poprawne wcięcia w kodzie. Teraz ciężko zrozumieć dokąd sięga który warunek. Nie ignoruj wcięć 😉

Szczerze mówiąc nie znam reguł dawania wcięć, więc zrobiłem to na wyczucie 😐

Oto kod:

#define zielona 8
#define czerwona 9

String odebraneDane = ""; //Pusty ciąg odebranych danych
boolean ziel = "";
boolean czer = "";

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
  ziel = false;
  czer = false;
}

void loop() {
 if(Serial.available() > 0) { //Czy Arduino odebrano dane
   //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej odebraneDane
   odebraneDane = Serial.readStringUntil('\n'); 

   if (odebraneDane == "zielona") { //Jeśli odebrano słowo "zielona"

         if (ziel == false) { // jeśli zielona dioda jest wyłączona
         digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
         ziel = true; // pokazujemy, że dioda jest włączona
         }   
         else { // jeśli dioda jest włączona
         digitalWrite(zielona, LOW); //To wyłączamy diodę zieloną
         ziel = false; //  pokazujemy, że dioda zielona jest wyłączona
       }
     }

   if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona"

        if (czer == false) { // jeśli czerwona dioda jest wyłączona
        digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
        czer = true; // pokazujemy, że dioda jest włączona
        } 
        else { // jeśli dioda jest włączona
        digitalWrite(czerwona, LOW); //To wyłączamy diodę czerwoną
        ziel = false; //  pokazujemy, że dioda czerwona jest wyłączona
       }
     }
   }
 }

Udostępnij ten post


Link to post
Share on other sites

Już blisko, ale jeszcze zamiast:

        } 
        else {

Powinieneś robić tak:

         } else {

Dodatkowo, to co jest między nawiasami klamrowymi powinno być wcięte o 1 poziom bardziej od nawiasów, czyli zamiast:

{
coś
}

Powinno być:

{
   coś
}

Udostępnij ten post


Link to post
Share on other sites

Ok, dziękuje zaraz zastosuje się do w/w wskazówek.

Dodam, że błąd już znalazłem nie chciało mi się pisać dla diody czerwonej osobno linijek więc przekopiowałem dla zielonej i pozmieniałem nazwy, jednej nie zmieniłem i temu nie działało.

Gotowy działający program:

#define zielona 8
#define czerwona 9

String odebraneDane = ""; //Pusty ciąg odebranych danych
boolean ziel = "";
boolean czer = "";

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
  ziel = false;
  czer = false;
}

void loop() {


   odebraneDane = Serial.readStringUntil('\n'); 

   if (odebraneDane == "zielona") { //Jeśli odebrano słowo "zielona"

         if (ziel == false) { // jeśli zielona dioda jest wyłączona
           digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
           ziel = true; // pokazujemy, że dioda jest włączona
         } else { // jeśli dioda jest włączona
             digitalWrite(zielona, LOW); //To wyłączamy diodę zieloną
             ziel = false; //  pokazujemy, że dioda zielona jest wyłączona
       }
     }

   if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona"

        if (czer == false) { // jeśli czerwona dioda jest wyłączona
         digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
         czer = true; // pokazujemy, że dioda jest włączona
        } else { // jeśli dioda jest włączona
           digitalWrite(czerwona, LOW); //To wyłączamy diodę czerwoną
           czer = false; //  pokazujemy, że dioda czerwona jest wyłączona
       }
     }
   }

Edit: Czy teraz estetycznie jest OK oraz czy w dobry sposób rozwiązałem zadanie? 😉

Udostępnij ten post


Link to post
Share on other sites

Nie warto kopiować kodu, to są najczęstsze miejsca późniejszych błędów... Ogólnie idziemy w dobrą stronę, ale nawiasy nie są jeszcze równe, zerknij jak to wygląda na spokojnie i porównaj czy nawiasy otwierające i zamykające są w tych samych kolumnach.

Udostępnij ten post


Link to post
Share on other sites
Nie warto kopiować kodu, to są najczęstsze miejsca późniejszych błędów... Ogólnie idziemy w dobrą stronę, ale nawiasy nie są jeszcze równe, zerknij jak to wygląda na spokojnie i porównaj czy nawiasy otwierające i zamykające są w tych samych kolumnach.

Teraz już wszystko powinno być ok, ale mam pytanie co do funkcji if, bo w Twoich kodach nie dajesz "{" w nowej lini tylko po nawiesie if () { i wtedy jest problem z tym aby druga klamra była w tej samej kolumnie.

Inaczej mówiąc jak lepiej robić:

if (ziel == false) 
   { // jeśli zielona dioda jest wyłączona
     digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
     ziel = true; // pokazujemy, że dioda jest włączona
   } else { // jeśli dioda jest włączona

czy

if (ziel == false) { // jeśli zielona dioda jest wyłączona
     digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
     ziel = true; // pokazujemy, że dioda jest włączona
   } else { // jeśli dioda jest włączona

(tylko wtedy nawiasy klamrowe nie są w jednej kolumnie)

Oto kod:

#define zielona 8
#define czerwona 9

String odebraneDane = ""; //Pusty ciąg odebranych danych
boolean ziel = "";
boolean czer = "";

void setup() 
{
 Serial.begin(9600); //Uruchomienie komunikacji
 pinMode(zielona, OUTPUT); //Konfiguracja wyjść
 pinMode(czerwona, OUTPUT);

 digitalWrite(zielona, LOW); //Wyłączamy diody
 digitalWrite(czerwona, LOW);
 ziel = false;
 czer = false;
}

void loop()
{
 odebraneDane = Serial.readStringUntil('\n'); 

 if (odebraneDane == "zielona") 
 { //Jeśli odebrano słowo "zielona"

   if (ziel == false) 
   { // jeśli zielona dioda jest wyłączona
     digitalWrite(zielona, HIGH); //To włączamy diodę zieloną
     ziel = true; // pokazujemy, że dioda jest włączona
   } else { // jeśli dioda jest włączona
       digitalWrite(zielona, LOW); //To wyłączamy diodę zieloną
       ziel = false; //  pokazujemy, że dioda zielona jest wyłączona
          }
  }

   if (odebraneDane == "czerwona") 
   { //Jeśli odebrano słowo "czerwona"

     if (czer == false) 
     { // jeśli czerwona dioda jest wyłączona
       digitalWrite(czerwona, HIGH); //To włączamy diodę czerwoną
       czer = true; // pokazujemy, że dioda jest włączona
     } else { // jeśli dioda jest włączona
       digitalWrite(czerwona, LOW); //To wyłączamy diodę czerwoną
       czer = false; //  pokazujemy, że dioda czerwona jest wyłączona
            }
   }
}

Udostępnij ten post


Link to post
Share on other sites

Razor1996, w zasadzie to nie ma różnicy. Kwestia przyzwyczajenia. Dla mnie osobiście przenoszenie klamry przy if'ach do kolejnej lini jest czystym marnotrawieniem miejsca i zaciemnianiem kodu. Ale każdy pisze jak mu wygodnie.

Udostępnij ten post


Link to post
Share on other sites

Razor1996, może źle się wyraziłem. Nie nawias otwierający i zamykający powinien być tej samej kolumnie, ale nawias zamykający powinien być równo z początkiem wyrażenia, po którym jest nawias otwierający. Brzmi zawile, dlatego przykład:

cośTam {
|
|	cośTamDWa {
|	|
|	}	
|
}

Chodzi o zwykłą estetykę 🙂 Widzę, że przydałby się osobny artykuł na temat formatowania kodu. na ten moment mogę Ci polecić się poniższe teksty:

- Sekrety profesjonalnego programowania

- Jak unikać pułapek języka C?

Udostępnij ten post


Link to post
Share on other sites

igor,

Igor, co oznacza

digitalWrite(zielona, stanZielonej);

digitalWrite(czerwona, stanCzerwonej);

stanZielonej i stanCzerwonej to chyba nie jest LOW , ani HIGH , tylko true lub false

Udostępnij ten post


Link to post
Share on other sites

LOW = false = (uint8_t)0

HIGH = true = (uint8_t)1

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Jak chodzi o boolean to obaj macie rację.

Program z wykorzystaniem false i true, jako LOW i HIGH będzie działał, a jednocześnie będzie niepoprawny.

Będzie działał, ponieważ (przypadkiem) wartość false jest zdefiniowana jako 0, a LOW też jest zerem (podobnie true i HIGH to 1).

Jednocześnie program jest niepoprawny - boolean i int to zupełnie różne typy. Wykorzystanie ich zamiennie to błąd logiczny.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Nie chodziło mi o konwersję bool na uin8_t. To raczej chodzi o rozumienie abstrakcji jaką jest typ danych.

Boolean to wartość logiczna - liczba całkowita, to liczba całkowita. W przypadku LOW, HIGH, to typ wyliczeniowy. Oczywiście można rzutować typ wyliczeniowy na np. boolean, ale trzeba na takie konwersje uważać. Widziałem kod, który rzutuje float na uint32_t, żeby szybciej wykonywać pewne operacje - to są sztuczki które jak najbardziej można stosować, ale dla kogoś kto dopiero się uczy lepiej nie wnikać w takie "hakerstwa".

Pomyśl jak bardzo nieprzenośny kod tworzysz - jeśli przykładowo w następnej wersji Arduino ktoś zmieni wartości stałych LOW i HIGH, np. na 1 i 2 - kod przestanie działać.

Nieco nowocześniejsze języki jak. np. C#, czy Java, ale nawet stary dobry Pascal nie traktują boolean-ów i wyliczeń jako integer-ów.

Więc kod z if-ami jest dłuższy, ale za to poprawny logicznie. Używanie true/false jako LOW/HIGH, chociaż działa, może świadczyć albo o bardzo dobrym rozumieniu mechanizmów i potrzebie optymalizacji kodu, albo wręcz przeciwnie.

A jak już jesteśmy przy kodowaniu w C, to taki kod byłby dużo wydajniejszy, ale pokazuję go tylko żeby tak nie robić:

    if (odebraneDane == "czerwona") 
       digitalWrite(czerwona, czer ^= 1); 

Udostępnij ten post


Link to post
Share on other sites

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ę »

×