Problema comunicazioni tra un master e piu' slave

Mar 06, 2025 Last reply: 1 anno fa 29 Replies

Il 07/03/2025 16:55, pozz ha scritto:

Si ci avevo pensato a mandare via solamente dati in ascii, ma si andrebbe ad allungare la trasmissione e questo non e' un bene, oltre che essere una soluzione poco elegante E noi siamo qua per le soluzioni eleganti, 'alla grezza via' son capaci tutti di farle

Il 08/03/2025 00:17, RobertoA ha scritto:

Non sono d'accordo nell'etichettare la soluzione ASCII come poco elegante. E' vero che raddoppi la lunghezza dei frame, ma chi se ne accorge? Che througput hai su questo bus?

Nella maggior parte dei casi, il bus è in idle in attesa che il master inizi la successiva richiesta o che lo slave risponda. Il tempo in cui il bus è occupato da una trasmissione (richietsa o risposta) è normalmente una percentuale abbastanza piccola. Quindi, anche raddoppiando questo tempo, non hai problemi.

Con un protocollo ASCII guadagni in leggibilità (come dicevo, ti basta uno sniffer ed un putty) e risolvi nativamente tutti i problemi legati al framing.

Il 06/03/2025 05:00, RobertoA ha scritto:

Mancando l'indirizzo del mittente, che sarebbe poi il master, è un protocollo inaffidabile. Il master deve farsi riconoscere in qualche modo, altrimenti può succedere quello che temi. Se usi due byte per gli indirizzi, hai 256 combinazioni disponibili di cui una per il master e 255 per gli slave.

Il 08/03/2025 17:18, MobiusLoop ha scritto:

Mettere nelle richieste l'indirizzo del mittente e' sicuramente fattibile, inutile (perche' e' unico) ma fattibile Ma questo non sposta di una virgola il problema, che e' la possibilita' per i client di confondere dei byte dati con l'inizio di un messaggio a loro destinato, se ci pensi all'interno dei dati potrebbe benissimo esserci una quadrupleta composta da prembolo + comando + mittente + destinatario

Capisco che tu non sia d'accordo Ma la realta' e' che dimezzi la velocita' di lettura del sensori Metti di averne una decina, e metti di andare pian pianino sulla seriale onde minimizzare problemi che possono arrivare dal campo, invece di una ventina di letture al secondo passi a una decina di letture al secondo In sostanza un sensore viene letto una volta al secondo Pochetto per visualizzare delle immagini in movimento, gia' due volte al secondo e' poco Chiaramente il 'poco' o 'tanto' e' parere soggettivo, ma siccome il soggetto sono io, direi che una lettura sensore/sec e' poco

Il 08/03/2025 10:06, alfio ha scritto:

Questa non l'ho capita Se partiamo dal presupposto che ogni byte dati possa contenere un valore qualsiasi, ed il pacchetto dati sia piu' lungo dell'inizio trasmissione, allora qualsiasi inizio trasmissione venga adottato puo' essere 'confuso', indipendentemente da quale esso sia

Il 10/03/2025 08:08, RobertoA ha scritto:

Non è proprio così.

Supponiamo che ogni domanda e risposta sia composta da 10 byte e diciamo che tu vada a 9600bps, cioè molto lentamente. Hai quindi 20 byte per ogni lettura da sensore, circa 21ms. Con 10 sensori avresti 210ms per finire il ciclo, quindi circa 5 letture al secondo per ogni sensore. Se vai a 38400bps, hai ancora un fattore 4.

Questo supponendo che il bus sia occupato al 100% (se non sbaglio si parla di throughput) da una trasmissione del master o dello slave. In questa condizione, se dimezzi la lunghezza dei pacchetti, raddoppi il numero delle letture. Sarebbe il tuo ragionamento.

Però, nella mia piccola esperienza, la percentuale di occupazione del bus non è per niente il 100%, piuttosto si aggira sul 50% se non meno. Questo perché devi considerare la latenza che lo slave impiega per leggere il pacchetto ricevuto, capire che è per lui, calcolare la checksum, organizzare la risposta ed iniziare a trasmettere. Allo stesso modo, c'è una latenza nel master che deve leggere la risposta dello slave, processarla, decidere quale altro slave interrogare, organizzare la richiesta ed iniziare a trasmettere.

Molto dipende dal tipo di processore che hai, dalla sua frequenza, da come legge e reagisce ai byte ricevuti; in un software "classico" dove ricevi ad interrupt, ma elabori in background e dove non hai supercomputer, ma semplici microcontrollori (tipo un Arduino che va a

16MHz) che magari devono fare altro e magari questo altro è pure bloccante, ti ritroverai con un bus largamente inutilizzato e ti renderai conto che ottimizzare la lunghezza dei pacchetti è l'ultima cosa che potresti fare per aumentare il numero delle letture per sensore.

"RobertoA" ha scritto nel messaggio news:vqm47i$17tis$ snipped-for-privacy@dont-email.me...

facciamo un esempio pratico che ricalca il tuo esempio del primo post:

il master trasmette

0x00 inizio trasmissione 0xad ad=indirizzo dello slave da 01 a FF (importante != 0) 0xcm cm=comando da 00 a FF 0x00 lunghezza dei dati a seguire (=0 perche' il master no ha dati) 0xcs cs=checksum

lo slave trasmette

0x00 inizio trasmissione 0xad ad=indirizzo dello slave stesso 0xcm cm=il comando ricevuto 0xlu lu=lunghezza dei dati a seguire [0xlu] array di "lu" byte di dati da 00 a FF 0xcs cs=checksum

se anche nel messaggio trasmesso dal master inserisci la lunghezza dei dati (che varra' sempre 0) la routine di ricezione qui sotto sara' la stessa sia per il master sia per lo slave. non devi usare l'indirizzo 0 per gli slave.

l'algoritmo per trasmettere sara' qualcosa di simile:

void tx ( int len,byte* buf ) { byte checksum=0; serial.tx( 0x00 ); // start byte for( int n=0 ; n<len ; n++ ) { checksum += buf[n]; serial.tx( buf[n] ); if( buf[n]==0x00 ) serial.tx( 0x00 ); } serial.tx( checksum ); if( checksum==0x00 ) serial.tx( 0x00 ); }

l'algoritmo per ricevere sara' qualcosa di simile:

int rx ( int len,byte* buf ) { bool startbyte=false; byte rx;

for( ;; ) { rx=serial.rx(); if( rx!=0x00 ) // attesa start byte continue; rx=serial.rx(); if( rx==0x00 ) // se doppio 0x00 non e' lo start byte continue; // ricevuto start byte byte checksum=rx; int n=0; for( buf[n++]=rx ; n<len ; buf[n++]=rx ) { rx=serial.rx(); if( rx==0x00 ) { rx=serial.rx(); if( rx!=0x00 ) return -1; // errore 0x00 singolo nei dati } checksum+=rx; if( n==2 ) if( n+rx+1<=len ) len = n+rx+1; else return -2; // errore lunghezza dati eccede buffer } if( checksum!=serial.rx() ) return -3; // errore checksum if( checksum==0x00 ) { rx=serial.rx(); if( rx!=0x00 ) return -4; // errore 0x00 singolo nel checksum } return len; } }

la funzione di ricezione ritorna il numero di byte inseriti nel buffer, oppure un numero negativo per indicare l'errore riscontrato. il buffer deve essere allocato da chi chiama la funzione rx, e va passata la sua lunghezza.

non l'ho provato, e manca la gestione del timeout.

Il 10/03/2025 19:24, alfio ha scritto:

Capisco, ma ipotizzi sempre che gli slave 'vedano' correttamente tutte la trasmissioni, e quindi ti metti dalla parte "come dovrebbe essere" Nella realta' se ci fossero problemi nella comunicazione, e' facile che uno slave non sempre veda correttamente tutte le trasmissioni Voglio dire, se uno slave si perde la lettura di alcuni byte per strada, potrebbe interpretare dei byte che vede passare:

0x00 inizio trasmissione 0xad ad=indirizzo dello slave da 01 a FF (importante != 0) 0xcm cm=comando da 00 a FF 0x00 lunghezza dei dati a seguire (=0 perche' il master no ha dati) 0xcs cs=checksum

come una richiesta a lui destinata, anche se in realta' sono i byte dei dati di un suo collega che sta rispondendo al master

Se non introducesse una complicazione atroce ho anche pensato di sincronizzare tutti i devices in modo da avere un ulteriore strato di verifica imponendo che trasmissione e ricezione per ciascuno avvengano in intervalli stabiliti. La IMprecisione degli arduini e necessità di un RTC esterno mi ha dissuaso. Del resto l'intuito mi dice che è una di quelle complicazioni che è meglio non introdurre.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required