Arduino Polska Forum

Pełna wersja: UART, komunikacja pomiędzy dwoma Arduino.
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witam. Chcę zrobić, aby dwie sztuki arduino nano po każdorazowym rozpoczęciu nowej pętli wymieniały między sobą wartości zmiennych. Chcę do tego wykorzystać UART programowy lub sprzętowy, ale wolałbym programowy, gdyż na sprzętowym z tego co wiem nie mógłbym używać serial monitora. Dodam, że oba piny z przerwaniami są zarezerwowane do mojego programu. Próbowałem działać z przykładem software UART na stronie Arduino, lecz serial monitora zamiast wartości pokazywał mi znaki zapytania (https://www.arduino.cc/en/Tutorial/Softw...ialExample)
Pętla loop powinna się wykonywać miliony czy chociaż tysiące razy na sekundę. Najlepiej użyć Arduino z przynajmniej jednym wolnym UART sprzętowym, np. PRO MICRO (3$ na Aliexpress). Poza tym po prostu pokaż swoje próby, kod z obu Arduino. Jeśli głównie co robisz to przekazywanie tych parametrów w softserial to po prostu dławisz te uC.
Sprawdzałem dzisiaj i hardware uart działa razem z USB, więc nie ma problemu.

Znalazłem również sposób na wysłanie wartości zmiennej konwertując ją na kod ascii, jednak jest jakiś problem, ponieważ w trakcie testów funkcja za każdym razem staje na "delay(100)". Nie dzieje się tak, gdy usunie się linijkę z funkcją itoa. O co może chodzić?

Nadajnik:

char *zmienna;
int i = 2051;

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

void loop() {
itoa(i, zmienna, 10);
Serial.write(zmienna, 10);
i++;
delay(1000);
}

Odbiornik:

char mystr[10]; //Initialized variable to store recieved data

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

void loop() {
if (Serial.available() > 0) {
Serial.readBytes(mystr, 10);
Serial.println(mystr);
}
}
Witam
Proponuję zainteresować się strukturami.
Deklarujesz takie same struktury w "nadajniku" i "odbiorniku". Następnie strukturę do wysłania w nadajniku zamieniasz  na string i wysyłasz przez UART. W odbiorniku nasłuchujesz i jak coś przyjdzie po UART to zapisujesz i zamieniasz na strukturę.
Deklarujesz struktury: to są moje dla przykładu w nadajniku w odbiorniku mają tylko zamienione DaneOdebrane z DaneDoWyslania


  struct RamkaMala{
    float WilgWew ;
    float TempWew ;
    byte SterRek = 1 ;
    } DaneOdebrane;
   
  struct RamkaDuza{
    float CisAtm ;
    float TempRek ;
    float WilgNaw ;
    float TempNaw ;
    float PmZew ;
    float PmWew ;
    float WilgZew ;
    float TempZew ;
    } DaneDoWyslania;


deklarujesz stringi

  char StringDoNadania[sizeof(DaneDoWyslania)];
  char StringOdebrany[sizeof(DaneOdebrane)];

Teraz podprogramy do wysyłania i odbierania po UART programowym o nazwie np S1 i w odbiorniki i nadajniku


void writeserial_S1 ()
{
  if (aktualnyczas - zapamietany_czas_wysylu_danych >= 2010UL) //tu wysyłam co 2 sekundy ale można inaczej
  {
    zapamietany_czas_wysylu_danych = aktualnyczas ;
    memcpy(StringDoNadania,&DaneDoWyslania,sizeof(DaneDoWyslania));
    S1.write(StringDoNadania,sizeof(DaneDoWyslania));
  }
}
void readserial_S1 ()
{
  if(S1.available()>0)
  {
  delay (100);
  if(S1.available()==sizeof(DaneOdebrane))
  {
  S1.readBytes(StringOdebrany,sizeof(DaneOdebrane));
  memcpy(&DaneOdebrane,StringOdebrany,sizeof(DaneOdebrane));
  }
  else
  {
    while (S1.available()> 0)
    {
 
   
    int czyszczenie = S1.read();
    }
  }
 

 
  }
}

Można zrobić tak, że nadajnik nadaje rytm wymiany danych a odbiornik jak coś otrzyma to odsyła swoje.
Może trochę chaotycznie, ale może Ci się przyda
Jestem początkującym w tych tematach a seniorem w latach Smile
Jeśli tylko wysyłasz między dwoma Arduino przez UART to ten jeden wystarcza. Normalnie tak nie wolno robić, ale mostek UART USB jest podłączony do Atmegi przez rezystory 1k, co osłabia sygnał z USB na tyle, że jeden nie uszkodzi drugiego, wygra ten z drugiego UNO. Nie mniej jednak używanie tych dwóch równocześnie może powodować napływ śmieci na wejścia, tak że byś potem nie szukał co się dzieje - to zapewne walczą ze sobą dwa nadajniki.
Wywal delay, naucz się obsługiwać czas z millis(), jest sporo przykładów tu na forum, kurs na FORBOT.
Co do zatrzymania programu to zamień char *zmienna na char zmienna[10]. Przy okazji polecam lekturę całości na wikibooks: https://pl.wikibooks.org/wiki/C/itoa.
@Agregacik, obejrzyj przykład z Serialevent z przykładów Arduino, daj na początek transmisji int'a o rzadko spotykanej wartości, np. 0x0F0F i jeśli odbierzesz takiego ściągaj kolejne x bajtów do bufora i przekaż cały do osobnej funkcji, która coś z tym potem zrobi w loop. Można też dodać CRC w ostatnim polu struktury i weryfikować, czy ramka ma sens w ten sposób. Czekanie 100ms jest na początek OK, ale to wieczność w świecie uC. Można też sprzętowo dać znać, że coś wysłałeś już w całości, jeden pin jako wejście i piknięcie sygnałem 100ms (bez delay), że coś poszło. UART w Arduino jest buforowany, jeśli zaglądasz tam co najmniej raz na 100ms i wysyłasz nie częściej niż 1s to spokojnie można chyba też poczekać na pełną ramkę. Używanie float w Arduino lepiej ograniczyć do wcale. Temperaturę lepiej trzymać, przeliczać i porównywać w formie int, np. 20.66oC jako 2066, ciśnienie po prostu trzymać w Pa. Każde użycie int jest 10x szybsze niż floata, szczególnie widać to w ESP8266 i STM32, gdzie int jest również 32bity jak float, a jednak 10 razy wolniejszy. W ESP32 czy z STM gdzie jest jakiś ficzer do wspomagania obliczeń jest już to samo, ale i tak trzeba się pilnować, bo wszędzie jest promocja do int'a i można się na tym przejechać, tak jak przy porównywaniu wartości i przy chęci skorzystania z liczb porządkowych.
@kaczakat
Z Serialevent praktykowałem na UNO,  ale po przejściu na LEONARDO (ma dodatkowy UART) okazało się, że nie działa. Po wielu bojach doczytałem, że na LEONARDO nie działa. Dowiedziałem się o tym tu https://plociennik.info/index.php/arduino-wstep
Po tym "incydencie" o Serialevent zapomniałem.
Dzięki za rady. Wiem, że delay to zło i że trzeba używać roztropnie, jak już musimy.  Niektóre biblioteki tez dają popalić jak autor stosował delay. Nie wiedziałem o tak znacznej różnicy pomiędzy INT a FLOAT. Wiedziałem tylko, że zajmują więcej pamięci. Projekty, które dotychczas zrobiłem, mają prędkości furmanki, więc procesorki, można powiedzieć, że się nudzą biegając w kółko.
Autorowi wątku polecam poczytanie w podanym wyżej linku o transmisji szeregowej.
(19-08-2019, 22:36)kaczakat napisał(a): [ -> ]1. Wywal delay, naucz się obsługiwać czas z millis()"
2. Można też sprzętowo dać znać, że coś wysłałeś już w całości, jeden pin jako wejście i piknięcie sygnałem 100ms (bez delay), że coś poszło.
3. Używanie float w Arduino lepiej ograniczyć do wcale. Każde użycie int jest 10x szybsze niż floata"

1. Delay tutaj użyłem tylko w ramach testu.  W gotowym projekcie i tak mi będzie potrzebny, aby czekać 1ms na przełączenie się adresów multipleksera.

2. Chcę poświęcić jeden pin na sygnalizację rozpoczęcia się nowej pętli w odbiorniku, aby nadajnik zaczął nadawać. Zależy mi, aby co każdą pętlę była wymiana danych.

3. Jednak posługiwanie się wszędzie int jest mniej wygodne. Nie wiedziałem, że to ma taki duży wpływ na szybkość programu, ale jeżeli program będzie działał za wolno to raczej nie ma problemu, żeby to zamienić na inta.
zamieniłem *zmienna na zmienna[10] i wszystko działa, jednak nie za każdym razem poprawnie przesyłane są dane tzn, odbierane są losowe liczby, dopóki się nie zresetuje nadajnika. Da się ten problem jakoś ominąć w sofcie?

Nadajnik:

char zmienna[10];
int i = 2051;

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

void loop() {
itoa(i, zmienna, 10);
Serial.write(zmienna, 10);
i++;
delay(1000);
}

Odbiornik:

char mystr[10]; //Initialized variable to store recieved data

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

void loop() {
if (Serial.available() > 0) {
Serial.readBytes(mystr, 10);
Serial.println(mystr);
}
}
Pewnie czytasz trochę jednej trochę drugiej danej. Brak synchronizacji. Spróbuj czyścić bufor jak zawartość bufora jest inna niż spodziewana. Masz to w moim przykładzie.
Kod jest w porządku. Może to wina połączeń.
Ale faktem jest, że powinieneś zainteresować się przerwaniem od UART, jak wyżej zasugerowano.
Stron: 1 2