Skocz do zawartości

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


Pomocna odpowiedź

bonneripper, witam na forum 🙂 Zacznijmy od tego czy na pewno masz wszystko dobrze podłączone. Sprawdzałeś prostym programem, czy możesz zamigać diodą?

Link do komentarza
Share on other sites

Witam, Arduino programuję od niedawna. Przebrnąłem przez kolejne lekcje kursu bez żadnych problemów aż to lekcji #3. Przy próbie komunikacji przez UART i odczycie imienia nie pojawił się jeszcze problem. Stworzył się podczas próby kontroli przez ww. zapalania diod, zielonej i czerwonej. Próbowałem z każdej strony do tego podejść ale bez wyniku. Na początku sprawdziłem poprawność połączeń poprzez prosty program zapalający diody i wszystko było ok. Następnie wróciłem do programu z imieniem i UART działał jak powinien. Wszystko jest ok dopóki nie używam więcej jak jednej instrukcji "if". Wygląda to tak jak by Arduino nie widziało kolejnych instrukcji "if" w instrukcji głównej. Czy możliwe jest, że mam problem z kompilatorem, mikrokontrolerem albo IDE ? Dodam tylko, że po kolejnych próbach z kompilacją postanowiłem skopiować program prosto ze strony więc nie ma mowy o błędach w kodzie. Dziękuję za pomoc.

Link do komentarza
Share on other sites

Kamil88, witam na forum 🙂 Błędy kompilatora można wykluczyć. Pokaż proszę dla pewności dokładny program, który kompilujesz i do tego zrzut z okna, przez które komunikujesz się później z płytką (tak, aby było widać ustawienia).

Link do komentarza
Share on other sites

Witam,
Do sprawdzenia działania Monitora Portu pod względem instrukcji zagnieżdżonych "if" skompilowałem taki program:

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

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
}

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"
    Serial.println("zielona"); //To odbierzemy "zielona"
    delay(1000); 
   }

   if (odebraneDane == "czerwona") { //Jeśli odebrano słowo "czerwona"
     Serial.println("czerwona"); //To odbierzemy czerwona
     delay(1000);
   }
 }
}

Na zdjęciu skompilowany program wraz z otwartym monitorem portu z widocznymi ustawieniami jak prosiłeś.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Kamil88, wygląda na to, że Twój problem leży w źle ustawionym monitorze portu szeregowego. Pokombinuj z menu, gdzie w tej chwili masz ustawione "Zarówno NL, jak i CR" (sprawdź jak program działa przy różnych ustawieniach) i daj znać jakie wnioski 😉

Link do komentarza
Share on other sites

Treker, Dzięki za pomoc. Oczywiście wszystko teraz działa jak powinno. Przy pierwszych dwóch ustawieniach program działa a następnych już nie. To też wydaje się dziwne bo nie zmianiałem ustawień przy poprzednim programie z komunikacją przez UART. Tak czy inaczej już wszystko ok. Dzieki jeszcze raz.

Link do komentarza
Share on other sites

Hej, niestety: odebraneDane = Serial.readStringUntil('\n'); nie działa poprawnie, tzn. nie zapisuje do znaku końca linii. Czy coś się pozmieniało w Arduinach? Funkcja ta działa poprawnie dopiero jak dodamy jakieś opóźnienie w kodzie w innym przypadku wyświetla to co uda jej się "złapać", a przecież powinna omijać odbiór jeśli nie wykryła końca linii. Z opóźnieniem jest ten problem że musi być mniejsze od opóźnienia w Arduinie nadającym dane.

Wiem że można poczekać aż w buforze znajdzie się więcej danych przez zwiększenie zera w ifie: Serial.available() > 0, ale przy zmiennej długości przesyłanego komunikatu robi się choinka.

Dla przykładu Serial.parseInt działa poprawnie nawet jak w kodzie nie ma ani jednego delay czy millis(). Ewidentnie Serial.setTimeout przyjmujący domyślną wartość 1000ms robi robotę bo jak zmniejszę na zero to tylko szczątkowe dane zbiera co jakiś czas.

Jak już jesteśmy przy Serial.setTimeout() to jestem załamany tym jak Arduino wolno te dane mieli - widać gołym okiem że odbieranie danych przez UART spowalnia cały kod, a jak setTimeout damy na zero to znowu choinka.

Świetną wydała mi się funkcja void serialEvent(), ale to już w ogóle zamula wszystko.

Po co jest ten bufor w Arduino skoro bez opóźnienia nie chce działać? Ja to tak rozumiem że dane do bufora powinny być zapisane jednocześnie w trakcie wykonywania się pętli głównej, a w dowolnej chwili zaglądam do bufora i jak są dane to zapisuje do zmiennej/ robię z nimi co chce.

Czy jest jakiś sposób przesyłania danych o zmiennej długości bez użycia jakichkolwiek opóźnień w kodzie odbiornika? Po odebraniu chciał bym te dane jeszcze jakoś podzielić na dwie zmienne int więc muszę mieć zawsze komplet w nowej linii 🙂 Musi być jakiś sposób skoro ludzie na tych prockach autopiloty do modeli RC robią, które są w stanie odbierać na bieżąco całą sieczkę z GPS i przeliczać to robiąc jeszcze setki innych obliczeń w ułamku sekundy. Pomóżcie coś bo już czacha mi dymi, od rana nad tym siedzę...

EDYTA:

Mam wrażenie że w dokumentacji https://www.arduino.cc/en/Serial/SetTimeout jest bzdura, na Serial.parseInt() owszem działa tak jak tam opisali. Jeśli

Serial.setTimeout()

jest mniejsza niż częstotliwość wysyłania danych do seriala to zaczyna pluć zerami między pomiarami, ale już Serial.parseFloat() nic sobie nie robi z Serial.setTimeout() czy jest 500 czy 2500ms odczytuje prawidłowo dane gdy tylko się pojawią, mało tego nie blokując pętli 🙄

PS. Wybaczcie że wcześniej tak ciurkiem napisałem, ale myślałem że piszę komentarz, a nie post na forum...

Link do komentarza
Share on other sites

KapitanBomba, witam na forum!

Hej, niestety: odebraneDane = Serial.readStringUntil('\n'); nie działa poprawnie, tzn. nie zapisuje do znaku końca linii. Czy coś się pozmieniało w Arduinach? Funkcja ta działa poprawnie dopiero jak dodamy jakieś opóźnienie w kodzie w innym przypadku wyświetla to co uda jej się "złapać", a przecież powinna omijać odbiór jeśli nie wykryła końca linii. Z opóźnieniem jest ten problem że musi być mniejsze od opóźnienia w Arduinie nadającym dane.

Zacznijmy od tego na jakim kodzie testujesz to rozwiązanie? Nie słyszałem, aby Arduino coś zmieniało i w moich projektach wszystko działa "po staremu". Pokaż kod to łatwiej będzie rozmawiać.

PS. Wybaczcie że wcześniej tak ciurkiem napisałem, ale myślałem że piszę komentarz, a nie post na forum...

Nic się nie stało - u nas komentarze są połączone z forum, dzięki temu łatwiej prowadzić bardziej rozbudowane dyskusje 🙂

Link do komentarza
Share on other sites

Co w przypadku, gdy konieczna będzie zmiana fizycznych podłączenie np.: diody lub przycisku? (fizycznego podłączenia)?

Sięgamy do miejsca w pamięci, który zadeklarowaliśmy jako zmienną licznik, a następnie wysyłamy znalezioną tam wartość przez UART. (które)?

Czy Arduino odebrano dane (odebrało)?

Dzieje się to za pomocą funkcji Serial.readStringUntil(terminator), która kopiuje dane z bufora do momentu napotkania znaku terminator (w tym przypadku "\n" - czyli znak nowej linii). (terminatora)?

Na początku definiowane są nr pinów z diodami oraz deklarowane jest zmienna, do której kopiowane są odebrane dane. (deklarowana)?

  • Lubię! 1
Link do komentarza
Share on other sites

Witam serdecznie,
jestem tutaj nowy. Pozwolę sobie "pochwalić" się swoim rozwiązaniem zadania z gwiazdką w tym artykule:

#define green 9
#define red 8

String odebraneDane = "";
boolean greenState = false;
boolean redState = false;

void setup() {
 Serial.begin(9600);
 pinMode(green, OUTPUT);
 pinMode(red, OUTPUT);

 digitalWrite(green, LOW);
 digitalWrite(red, LOW);

}

void loop() {

 if(Serial.available() > 0){
   odebraneDane = Serial.readStringUntil('\n');

   if (odebraneDane == "zielona"){
     if (greenState){
       digitalWrite(green, LOW);

     } else{
       digitalWrite(green, HIGH);

     }
     greenState = !greenState;    
   } else if (odebraneDane == "czerwona"){
     if (redState){
       digitalWrite(red, LOW);
     } else{
       digitalWrite(red, HIGH);
     }
     redState = !redState;  
   } else {
     Serial.println("Wpisz zielona lub czerwona");
   }
 }

}

Pozdrawiam, i dziękuję za tę serię - jest świetna. Nie mogę się doczekać aż przerobię tę i kolejne 😉

Link do komentarza
Share on other sites

mszzukowski, witam na forum!

Dzięki za miłe słowa, cieszę się, że kurs jest pomocny 🙂 Pamiętaj, aby na przyszłość w swoich program umieszczać komentarze, które ułatwiają analizę kodu - wtedy będzie jeszcze lepiej. Powodzenia w dalszej nauce!

Link do komentarza
Share on other sites

Nie wiem czy ktoś spotkał się z takim problemem ale pisząc własny, mały program w oparciu o akapit "Interakcja z układem - sterowanie diodami przez UART" napisałem prosty program, który ma wypisywać jedną rzecz do terminala i sterować jednym wyprowadzeniem. W każdym razie sugerując się tamtym programem pisałem:

if(odebrane == "shutdown") {
     Serial.println("wylaczanie");
     digitalWrite(5, LOW);
   } 

Kompilator nie pokazywał tu błędu ale ten fragment nie działał (if się nie wykonywał). Znalazłem jednak mój wcześniejszy, działający program i tam zamiast (" ") było (' '). Zmieniłem i zadziałało od razu. Nie wiem czy to w kursie jest błąd czy w innej wersji Arduino IDE jest inaczej (moja to 1.8.3). W każdym razie to taka pierdółka ale spędziłem nad tym kilka godzin.

Zapraszam do dyskusji.

Link do komentarza
Share on other sites

Mechano, sprawdziłem przed chwilą podobny kod na najnowszej wersji Arduino IDE, jednak nie jestem w stanie odtworzyć Twojego błędu. Przykładowy kod:

String odebraneDane = "";

void setup() {
 Serial.begin(115200);
}

void loop() {
 if(Serial.available() > 0) {
   odebraneDane = Serial.readStringUntil('\n');

   if (odebraneDane == "shutdown") {
     Serial.println("Wylaczanie");
   }

 }
}

Efekt działania:

Cytowane wyżej porównanie działa u mnie poprawnie. Obawiam się, że Twój błąd mógł wynikać jednak z czegoś innego 😉

Link do komentarza
Share on other sites

Dlaczeg po wpisaniu komendy delay 25 i puszczeniu przycisku komunikat nie pojawia się co określony odstęp czasu? (interakcja z programem)

Dlaczego po void setup są znaki () ?

Ps. kurs bardzo pomocny

Link do komentarza
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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.