Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Przesyłanie danych float po uart

08 Paź 2019 19:42 291 15
  • Poziom 11  
    Witam Państwa,
    Potrzebuję wysłać wartość np. 22,5 czyli float między dwoma arduino po UART. No i o ile za pomocą ponizszych kodów daje radę przesyłać dane typu int to nie wiem jak to zrobic wlaśnie float.
    W arduino wysyłajacym stosuje te instrukcje:
    Code:

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

    void loop()
     {
      Serial.write(45);
    }

    Natomiast w arduino odbierającym :
    Code:

    int incomingByte = 0;

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

    void loop() {
     
      if (Serial.available() > 0) {
     
        incomingByte = Serial.read();
        Serial.println(incomingByte, DEC);
      }
    }
  • PCBway
  • Poziom 28  
    Nie wiem, czy w Arduino będą do tego jakieś zmyślne funkcje, ale generalnie taki float to zmienna 32bit, więc możesz ją rozczłonować i wysłać po kawałku, a po drugiej stronie skleić ponownie.
    Da się to łatwo zrobić definiując unię, czyli taki twór, który wskazuje na ten sam zakres danych, ale jest interpretowany zależnie od tego jak go wywołasz. Piszę z pamięci, ale chyba leciało to tak

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i potem u.value zachowuje się jak float, a u.bytes[] jak tablica. I całe piękno unii polega na tym, że wpisujesz coś do float, a potem masz dostęp do tego bajt po bajcie w tablicy, np.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i z drugiej strony sklejasz to analogicznie, czyli odbierane bajty wpychasz kolejno do u.bytes[i], a potem używasz sobie u.value jako float...

    Oczywiście będzie problem jak komunikacja Ci się rozjedzie i bajty się poprzesuwają, bo wtedy sklejona wartość to będzie bzdura ;)

    Ps. Nie wiem, czy w Arduino to pójdzie, ale chyba w C++ zadziała to, co jest pisane w C ;)
  • Poziom 34  
    W sumie to można wysyłać bez unii i dodatkowej pętli, i dodatkowo w C++ ;)
    Kod: c
    Zaloguj się, aby zobaczyć kod

    gdzie value to zmienna typu float. Analogicznie można odbierać funkcją Serial.readBytes():
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Albo wykorzystać do odbioru funkcję Serial.parseFloat() - to jest trudniejsze.

    https://www.arduino.cc/reference/en/language/functions/communication/serial/write/
    https://www.arduino.cc/reference/en/language/functions/communication/serial/readbytes/
    https://www.arduino.cc/reference/en/language/functions/communication/serial/parsefloat/
  • PCBway
  • Poziom 28  
    O widzisz, jeszcze lepsze rozwiązanie :) Myślałem, że ten write() łyka tylko po bajcie, stąd pomysł z dodatkową pętlą itp. :lol:
  • Poziom 11  
    Witam,

    użyłem Twoich instrukcji khoam:
    nadawanie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Odbieranie:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Niestety w serialu mam 0.00, oczywiście w setup w jednym i w drugim urządzniu mam ustawione float value =0;
  • Poziom 34  
    omnixcrs napisał:
    oczywiście w setup w jednym i w drugim urządzniu mam ustawione float value =0;

    W setup()? Tę deklarację zmiennej powinieneś ustawić w bloku głównym, przed setup(). Pokaż kod proszę.

    Dodano po 5 [minuty]:

    Ewentualnie w samej pętli loop().

    Dodano po 23 [minuty]:

    Czy używasz jednocześnie Serial do komunikacji pomiędzy Arduino oraz do monitora portu szeregowego ?

    omnixcrs napisał:
    if (Serial.available() > 0) {
    Serial.readBytes((byte *)&value, sizeof(value));
    Serial.print(value);
    delay(2000);
    }
  • Poziom 11  
    Witam khoam,
    sory za wprowadzenie w błąd arduino przesyła jednak poprawnie wartość float, ale nie wiem dlaczego działa to tylko przez jakiś czas około 3-5min. Napisałem testowy programik wyświetlający wartość przesłanej temp na lcd2x16. Po uruchomieniu na wyświetlaczu wyświetla się tamp 22,5 i 27,5 ale przez dosłownie 3-5 min potem jest już 00,0. Dlaczego tak się dzieje. Wklejam kody:
    Nadawanie:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Odbieranie
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 34  
    Spróbuj nieco zmodyfikowanej wersji nadawania:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Oraz nieco zmodyfikowanej wersji odbierania:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 11  
    Ok spróbuje i dam znać, a powiedz mi czy identycznych poleceń mogę użyć dla int ?
  • Poziom 34  
    omnixcrs napisał:
    czy identycznych poleceń mogę użyć dla int ?

    Tak, z poprawką na Serial.available() - wtedy musisz oczekiwać na 2 bajty, a nie 4.
    Można też przerobić pętle odbierania na taką, bardziej "uniwersalną":
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Wtedy temp_pompy może być float czy int.
  • Poziom 11  
    Witam, no więc niestety nie zadziałało. Powodem problemu jest raczej mój kod odbierający ponieważ gdy zresetuje arduino z wyświetlaczem(odbierające) to na jakiś czas temp_pompy ma wartość i potem znowu 0.00. Tak naprawdę mój kod jest troszkę bardziej rozbudowany ale nie chciałem wrzucać całego aby nie zaśmiecać. Tym razem wrzucam cały odbierający może coś mam źle:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 34  
    omnixcrs napisał:
    gdy zresetuje arduino z wyświetlaczem(odbierające) to na jakiś czas temp_pompy ma wartość i potem znowu 0.00

    Zanim dochodzi w pętli loop() do odczytu Serial, masz wstawione opóźnienia na 10 s! Może być tak, że bufor Serial się przepełni (nie nadążasz odbierać dane) i stąd takie dziwne zachowanie.
    Rozumiem, że ten odbiornik to ESP8266? ;) W ESP8266 rozmiar bufora odbiorczego UART to 128 bajtów.
    Nie wiem, dlaczego wstawiłeś takie duże delay() w loop(), ale jeżeli są potrzebne, to odbiór danych z Serial powinieneś wtedy zrealizować na przerwaniu.
  • Poziom 28  
    Spróbuj w module nadawczym zmniejszyć częstotliwość nadawania danych pomiarowych skoro wyświetlasz je co 30s, albo odbieraj dane i aktualizuj zmienną w przerwaniu, albo przy odbiorze czytaj z bufora wszystko co masz dostępne, żeby zwolnić miejsce. Bo jak nadanesz co 2 czy 4 sekundy, a odczytujesz co 30, to nic dziwnego, że po czasie się zatyka.. Swoją drogą w takim układzie wyświetlasz stare dane, bo wysłałeś jeden pomiar, wyświetliłeś, po dwóch sekundach drugi.. ale on zaczeka jeszcze 28s na odczytanie z bufora i wyświetlenie. Po kolejnych 2 sekundach wysyłasz kolejny, ale on wyświetli się po 26+30=56s, czwarty wysłany po kolejnych 2 sekundach wyświetli się dopiero po 24+30+30=84s itp. A kolejka się zapycha..

    W sumie dobrze wysyłać częściej, żebyś miał zawsze aktualne info jak nie trafisz z karuzelą ekranów, ale musisz to na czas ściągać z bufora i wyświetlać najnowszy..


    Ps. Czy Ty specjalnie opóźniasz start sterownika, żeby wyświetlić sobie napis uruchamianie? Czy tam faktycznie w tle coś startuje? ;-)
    I po co tyle razy piszesz Uruchamianie z dodatkowymi kropkami, jak wystarczy napisać raz, a potem tylko odpowiednio ustawić kursor i dopisać kropkę? ;-)
  • Poziom 34  
    @omnixcrs Mam taką luźną propozycję. Podziel kod odbiornika na zadania: sprawdzenie WiFi, odczyty z poszczególnych czujników etc. Dla każdego z nich zdefiniuj wymagany, maksymalny interwał czasowy (lepiej krótszy niż dłuższy - ESP8266 ma szybki MCU). Użyj biblioteki TaskScheduler do zarządzania zadaniami - chodzi na ESP8266. W mojej stopce znajdziesz link do artykułu na ten temat. Kod będzie bardziej czytelny i ławiej będzie go rozbudowywać, a jako bonus pozbędziesz się delay() ;)
  • Poziom 11  
    Opóźnienia uruchomiania jest celowe bo w tym czasie startują dodatkowe urządzenia peryferyjne.
    Co do Seriala to nie jestem w tym niestety mocny. Czy zastosowanie millis zamiast dealy pomoże. Pytam bo nie wiem czy dam radę z przerwaniami.
  • Poziom 34  
    omnixcrs napisał:
    Czy zastosowanie millis zamiast dealy pomoże.

    Jeszcze bardziej sobie skomplikujesz sobie kod przez ręczne naliczanie poszczególnych interwałów. Patrz post #14.

    omnixcrs napisał:
    Opóźnienia uruchomiania jest celowe bo w tym czasie startują dodatkowe urządzenia peryferyjne.

    Funkcja setup() to nie problem, problemem jest to, co jest w loop().