Mega 2560 e due comunicazioni seriali

Ciao a tutti,
sto costruendo uno sketch più complesso di quelli che solitamente costruivo, e mi ritrovo in questa situazione:
1 arduino Mega dialoga via uart con 1 ESP32 (ho anche provato sostituendolo con un Nano, il problema sussiste) attraverso Serial2.

Lo stesso arduino Mega dialoga con un modulo GSM sim800L usando la Serial3 e gli manda comandi e riceve risposte sempre via seriale, baudrate 57600 .

Arduino Mega riceve da ESP32 un array di byte, lungo 82 bytes, baudrate 57600 .

Il problema è che Mega mentre sta ricevendo dal sim800L ovviamente "perde" l' array che esp32 gli invia. in ordine di importanza, ESP32 (quindi l array di 82 bytes) è più importante della comunicazione col sim800L quindi a dover scegliere preferirei che mentre dialoga col sim800L se riceve qualcosa sulla Serial2 (quindi da parte di ESP32) interrompesse il dialogo col sim800L .
Come si fa in questi casi? pensavo:
-> esiste una specie di serial interrupt, da configurare nel mio caso sulla Serial2, per dare priorità ?
-> altrimenti immaginavo di dedicare 1 pin del MEGA come "busy" cosi esp32 prima di iniziare la trasmissione legge (in input quindi) il piedino del Mega e se lo vede "alto" aspetta che torni a "basso" per trasmettere in felicità e col suo tempo tutto l array

Ho anche impostato Serial.setTimeout(6000); per dare "tempo" alla trasmissione ma non cambia nulla, come temevo. Ho cambiato la baud rate, ma niente ugualmente.
Consigli? Grazie del supporto e della PAZIENZA

Serve vedere il codice
Le seriali della MEGA sono HW, non dovresti perdere nulla...

il codice è grandetto, saranno più di 500 righe suddivise in più schede.. inizio a pensare, leggendo in giro, che io debba forse aumentare il "buffer" della seriale?
Prima di rendere il progetto più massiccio, ho provato a far dialogare 2 arduino (1 mega 1 nano, poi 1 mega e 1 uno) ed effettivamente notavo che in caso di delay(5000) di uno mentre l altro inviava un grosso array (maggiore di 32bit) andava perso. Mi è tornato in mente adesso che ho riscontrato lo stesso problema usando 1 mega, 1 sim800L e 1 esp32 . Forse ci sono delle configurazioni da settare? sempre su questo forum ho letto di programmatori che volevano alzare il buffer, cos è di preciso? io uso Arduino 1.8.19 , se può aiutare, come lo alzo?

Probabilmente è possibile strutturare in modo diverso il programma, in modo che gestisca entrambe le comunicazioni in parallelo, senza attendere che una finisca per dedicarsi all'altra.

La seriale già lavora ad interrupt, ma il buffer circolare della seriale è di 64 bytes (ed è fissato nel "core" Arduino, NON lo puoi modificare senza poi doverlo rifare e rifare e rifare ... ad ogni aggiornamento) ... o li leggi nel tempo che arrivano o ti perdi dei pezzi. A 57600 bps ricevi circa 5700 caratteri al secondo, quindi il buffer si riempie in circa 10 msec. ... se tu sei impegnato a fare altro per più di quel tempo, i rimanenti byte dei tuoi 82 sovrascrivono i vecchi e te li perdi.

Devi riorganizzare il programma ...

Guglielmo

Infatti quella è la strada da seguire, comunque controllare sempre se c'è qualche cosa di disponibile su TUTTE le seriali e prelevare subito mettendo in propri buffer :wink:

Oppure, se lo può fare, come dice può usare un pin come indicatore di "busy" e risolve ancora più semplicemente.

Guglielmo

Se quindi usassi un array di 60 bytes, non avrei quindi perdite? esempio:
-> Arduino Mega è impegnato in un delay di 4 secondi (è un esempio, per ovviare a questo problema invece dei delay uso millis(), scrivo così per rendere l idea)
-> esp32 (o l altro arduino) invia l array di 60bytes mentre Arduino Mega è al primo secondo di delay quindi ne ha ancora 3 davanti a se

Finiti i 4 secondi, Mega si ritroverebbe con Serial2.available()>0 e riceverebbe l intero array? Ho capito bene?

Si, ma perché?

Tratta la ricezione un carattere per volta mano a mano che arriva mettendo subito i singoli caratteri dove vanno e usando programmi snelli e non bloccanti e non avrai alcun limite di dimensione
Come ti ha già indicato Guglielmo peraltro

Vai a fare un giro su "la pappa è fatta"
E in particolare "grep non vuol dire greppia"

A volte non è possibile inviare un byte alla volta, o comunque risulta tutto più macchinoso.
Ho 16 sensori e mega deve comunicare ad esp quale di quelli è Low e quale High, ed essendo analogici anche la lettura da 0 a 254. Esp scrive a mega quale di quelli misurare, e altri comandi 0-1. Inviando un byte alla volta non saprei se una trasmissione è stata persa, e di conseguenza la lettura slitterebbe di 1 sensore, associando al sensore X il valore di X+1 e quindi sbagliando. Con l array invece dedico gli ultimi bytes a controllo (facendo somme, xor, insomma un po' come fa la seriale 485 nel protocollo Pelco per la videosorveglianza). in pratica mi serve l array

Vedo che non ti è chiaro il mio pensiero

Pazienza

Si, hai capito bene ... sino al limite del buffer circolare, i caratteri vengono accumulati e restituiti quando tu li vai a leggere.

Guglielmo

Nessuno dice che non debba essere trasmesso/ricevuto un array con i sacrosanti cheksum, quello che si dice è che non è necessario trasmetterlo/riceverlo tutto insieme all'interno dello stesso ciclo di programma.

I byte possono essere trasmessi/ricevuti in più cicli, e quando ci sono tutti si alza un flag per dire "pronti!". L'unico vincolo è che chi riceve sia in grado mediamente di smaltire i byte almeno velocemente quanto chi li trasmette, con il buffer di ricezione che fa da piccolo polmoncino durante la ricezione, non da deposito per l'intero blocco di dati.

Certo applicando una strategia di handshake (controllo flusso tramite pin di busy o caratteri Xon Xoff), tutto si può fare.

1 Like

Risolto con un PIN sul Mega dedicato, in pratica nel loop() richiamo, tra le altre, una funzione "controlla_serial2(); " (che è quella di cui non voglio perdere nessuna trasmissione), quando entro nella funzione ALZO a 1 logico 1 pin del MEGA e subito dopo ho messo un if(Serial2.available()) dentro un while di 300ms, in attesa che ESP si renda conto dell 1 logico e in caso volesse inizierebbe a trasmettere.
a fine funzione ABBASSO a 0 logico il pin del MEGA.

Dall altra parte, ho programmato ESP ad attendere l' 1 logico del MEGA in un while() prima di iniziare la trasmissione dell' array.

In pratica ho usato il pin del mega NON come "busy" ma al contrario come "sono disponibile a ricevere l array".
In futuro proverò a giocarci un po' provando ad alzare il buffer della seriale del mega, ho letto su altri post di questo forum che era possibile modificando hardwareserial.h sulle versioni precedenti, io sto usando l ultima, vedrò se è ancora possibile.
Grazie a tutti come sempre per la pazienza!

... come ti ho spiegato certo che è possibile, peccato che, essendo un modulo del "core" Arduino, ogni nuovo rilascio il file viene sovrascritto e quindi ti devi sempre ricordare di modificarlo o ... il programma che compili poi non funziona più correttamente.

Credo sia meglio la soluzione che hai adottato che NON va a modificare nulla che fa parte della base e che può cambiare nel tempo.

Guglielmo

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.