Comunicazione seriale tra arduino uno e arduino mega

Buongiorno a tutti, sto eseguendo dei tentativi di comunicazione tra arduino Uno e arduino Mega, per via seriale.
In particolare voglio inviare da Arduino Uno verso Arduino Mega, delle variabili ricavate da alcuni sensori.
L'idea di base, anche ricercando all'interno del forum, è la creazione di un array da parte di arduino Uno che poi invierà al Mega.( ovviamente il messaggio conterrà sia un carattere per l'inizio del messaggio che per la sua fine).
Come prima cosa ho letto che l'invio di dati tramite seriale viene eseguito un byte alla volta, dunque come posso impostare la ricezione del messaggio in arduino mega. Suppongo che anch'esso legga i dati in arrivo dalla seriale un Byte alla volta, perciò basta semplicemente implementare un ciclo if che ogni volta che riceve dati sulla seriale dedicata ad arduino uno, li trascriva in un Array di dimensione predefinita in base ai dati che devo inviare, o la cosa è un po più complicata?
esistono eventualmente altre soluzioni?
Purtroppo è da poco che mi sono interessato a questo tipo di comunicazione e sono alle primissime armi, perciò scusate se ho scritto qualche castroneria.
Vi ringrazio in anticipo.

Concettualmente è tutto giusto e sufficiente. Poi si possono implementare sistemi più o meno sofisticati per la sincronizzazione (diverse strategie di start/stop con le problematiche di evitare falsi positivi confondendo i dati con i delimitatori) e/o per la rilevazione errori (dal banale checksum/xor al più sofisticato CRC con possibili vie di mezzo).

no, non esistono altre soluzioni, sono tutte varianti della stessa minestra

e no, non dici castronerie

io ti direi per prima cosa di definire cosa vuoi trasmettere e in che condizioni

cioè: si tratta di letture di sensori,
ma sono tante? poche?
vuoi trasmetterle sempre tutte o solo quelle che cambiano?
vuoi avere una certa "robustezza" a riguardo eventuali errori di trasmissione?

e altri dettagli simili

io ho fatto una rapida ricerca e ti posso consigliare di partire a leggere da qui
https://forum.arduino.cc/t/trasferimento-di-valori-via-seriale-tra-arduino-uno-e-arduino-mega/320399
si tratta di una vecchissima discussione, ma mi sembra bene impostata
mi ricordo che anch'io ero partito da qui

P.S.
fatti un "bel" giro su "aiutateci ad aiutarvi", e segui ben bene i suoi link
scommettiamo che ti sarà utile?

Grazie per la risposta Claudio_FF. Ti volevo chiedere visto che ne hai parlato se hai qualche link utile riguardo alla sincronizzazione della comunicazione o se te hai qualche consiglio per iniziare.
La mia idea di base era la seguente:

Arduino uno invia Tutti Byte sulla seriale, quindi avrò il primo carattere di inizio comunicazione salvato sul primo Byte, successivamente seguiranno N Bytes contenenti l'informazione, per chiudere con il carattere di fine trasmissione.( se non sbaglio successivamente qui si può aggiungere il CRC).

Mentre su arduino Mega "rimango in ascolto" finche arduino uno non cessa di inviare dati sulla seriale e salvo le informazioni su un array, che in un secondo momento, finita la trasmissione, andrò a elaborare,

il CRC lo lascio alla fine ahahahahah

Grazie per la risposta standardoil, avevo già dato uno sguardo a quella discussione e concordo con te che e molto utile, solo che non ho trovato lo sketch per la ricezione del messaggio ahahaah.

Anche in questa discussione si affrontano problematiche simili. E ci sono degli esempi.

È una possibilità. La sincronizzazione (riconoscimento certo dell'inizio) la ottieni o con pause, o con handshake fisico (fili) o logico (scambio byte di comando), o aggiungendo informazione ai dati.

la pausa è la più semplice, quando l'Arduino ricevente riscontra mancanza di dati in arrivo per tot millisecondi si predispone in stato "inizio ricezione". Bisogna vedere di caso in caso se è una strategia valida.

L' handshake logico potrebbe anche essere un'idea semplice, l'Arduino ricevente invia un byte per dire all'altro "mandami i dati", e l'altro non invia nulla finché non riceve la richiesta. La sincronizzazione ne deriva in modo automatico e non serve alcun preambolo/terminatore.

L'aggiunta di informazione apre invece un ventaglio di possibilità, dalla manipolazione dei bit, alla manipolazione dei valori dei byte (ad esempio per ottenere le rispettive rappresentazioni ASCII esadecimali o in codifica base64), all'aggiunta di preamboli e terminatori in qualche modo distinguibili dal resto dei dati veri e propri.

Quest'ultimo punto è più o meno complicato a seconda che i dati possano o meno formare casualmente le stesse combinazioni di valori dei preamboli/terminatori, e un campo di check finale naturalmente permette di capire se si è ricevuto qualcosa di corretto o se per sbaglio ci si è agganciati a dei dati scambiandoli per preamboli.

Certo se i byte dei dati non usano l'intero range 0..255 ma un sottoinsieme, il problema non si pone perché preamboli/terminatori si realizzano con gli altri valori non usati dai dati.

Un modo che mi sembra assolutamente semplice per trasmettere byte con qualsiasi valore è quello di usare sequenze di escape per identificare preambolo e terminatore. In sostanza sia preambolo che terminatore può essere un byte qualsiasi, ma preceduto da un escape (in ASCII ci sarebbe il codice 27 pensato per questo), e all'interno dei dati, qualora si dovesse trasmettere proprio il codice dell'escape lo si trasmette due volte. In ricezione semplicemente si scarta il primo escape ricevuto (e ci si pone in stato "attenzione ricevuto escape") e si controlla cosa arriva subito dopo, e dopo può esserci solo il preambolo (allora siamo all'inizio), il terminatore, o un nuovo escape che quindi è da considerare un dato e si ritorna in stato "ricevo normale".

Grazie mille ho dato uno sguardo veloce è ho notato che mi può essere utile. Domani approfondisco.

Credo di avere capito, complimenti anche per la spiegazione ahah, è molta carne al fuoco, occorre studiarmelo un po e fare dei tentativi, come mi avete suggerito .

Io ho usato spesso questa libreria

Buonasera, torno da voi dopo un po' di prove svolte in questi giorni. Alla fine ho deciso di raccogliere tutti i dati in un buffer per poi elaborarli successivamente.
Ho steso qualche riga di codice che a mio parere doveva funzionare ma non funziona nulla.
Questo e il codice per arduino mega che in questo caso riceve solo

byte buff[12];
int i=0;
void setup()  
{ 
  
  Serial.begin(9600);
  Serial1.begin(9600);

}

void loop()
{
  if (Serial1.read()=='H'){
  while(!Serial1.available()){
   buff[i]=Serial1.read(); 
   Serial.println(buff[i]);
   i++;
  }
  i=0;
  }
  }

Qui invece ho il codice per arduino uno che trasmette


char text[11]={"H,123,345,S"};

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

void loop()
{
  for (int i=0; i<sizeof(text);i++){
    //Serial.println((text[i]));
    //Serial.print((byte)(text[i]));
    Serial.write(text[i]);
    //delay(1000);
  }
delay(5000);

}

Nella mia testa arduino uno invia continuamente il messaggio text un carattere alla volta, e a quanto ho letto serial.write invia i dati un byte alla volta, mentre arduino mega che resta in ascolto e inserisce cio che trova in un buffer di lunghezza abbastanza lunga( l'ho sovradimensionato per comodità in questa fase iniziale).
Tuttavia quando vado a mostrare i valori del buff nel monitor seriale per tutti i valori mi appare 255.
Ora nel listato di arduino uno ho provato anche con serial.print per fare delle prove, ma niente stesso risultato.
Un altra cosa che mi sfugge e questa:
Ho letto sempre sul forum che Serial.print(10,BIN) equivale a scrivere Serial.write(10).
Ora pero nel primo caso sul monitor seriale mi appare 00000010, mentre nel secondo mi appare 32 che nella tabella ASCII corrisponde giustamente a 2. dunque per far si che Serial.write mi restituisca 00000010 devo inserire un valore non un carattere char giusto?

Hai scritto di riempire il buffer quando la seriale non è available (quindi si riempie di -1 che corrispondono a 255). Ma comunque usando un while per acquisire tutti i byte bisogna prima aspettare che arrivino (il while è molto più veloce dei dati in arrivo), quindi dopo aver riscontrato il byte 'H' si dovrebbe aspettare almeno 11 millisecondi.

Per quanto riguarda print e write, con print generi delle stringhe di caratteri (cioè i byte che rappresentano i caratteri ASCII), mentre con write scrivi direttamente un solo byte (di valore 0..255).

Il monitor seriale mostra i byte in arrivo come caratteri corrispondenti, quindi quelli stampabili da 32 a 126 si vedranno, gli altri no.

Una strategia migliore potrebbe essere la procedura seguente, nel buffer finisce la stringa completa esclusi i caratteri di inizio e fine 'H' 'S', e viene completata con il terminatore 0. Si usa una variabile flag 'inrx' per indicare la fase di funzionamento (attesa o ricezione).

Buongiorno scusate il ritardo nella risposta.
Claudio_FF hai pienamente ragione sul serial.available() non so perchè ho scritto cosi hahaha appena ho letto la tua risposta mi sono dato del tonto.
Comunque ti ringrazio anche per il suggerimento, ho provato a implementarlo e funziona tutto, perfettamente. Per prova ho provato anche qualche accensione di led, lettura di dati e movimentazione stepper, e tutto funziona.
Il prossimo passo sarà l'utilizzo del CRC.

E un altro passo evitare che stringhe malformate troppo lunghe vadano a sbordare oltre l'array di ricezione :wink: