RobertoA snipped-for-privacy@tiscalinet.it ha scritto:
Ok, allora la via più semplice è quella del raddoppio dello start byte, pensaci e vedrai che non è nemmeno tanto difficile da implementare.
RobertoA snipped-for-privacy@tiscalinet.it ha scritto:
Ok, allora la via più semplice è quella del raddoppio dello start byte, pensaci e vedrai che non è nemmeno tanto difficile da implementare.
RobertoA snipped-for-privacy@tiscalinet.it ha scritto:
E vuoi che la sfiga ci veda così bene che il checksum è pure corretto? Passa a crc16.
RobertoA snipped-for-privacy@tiscalinet.it ha scritto:
Ti basta implementare il raddoppio dello start byte, se questo compare nei dati, o ovviamente ogni slave lo dovrà gestire.
Oppure usi solo caratteri ASCII per i dati (li converti in stringa numerica di n byte) e caratteri di controllo per i comandi, tipo STX ETX del handshake software.
Problemino comunicazione tra elettroniche Supponiamo abbiate delle centraline che misurano qualcosa Supponiamo che abbiate un modulo principale che deve interrogarle e comandarle Tutte le centraline sono slave, il modulo principale e' l'unico master Tutti collegati insieme via rs485 su un doppino rame La comunicazione, al fine di essere piu' rapida possibile, usera' l'invio e la ricezione di caratteri nella loro completa estensione e quindi dallo 0x00 al 0xFF, non c'e' un range di caratteri 'speciali' che possano essere interpretati come comandi piuttosto che come dati Ogni centralina e' identificabile con un byte di indirizzo, contenuto sia nel comando che il modulo principale invia sia nella risposta di ogni centralina Quindi supponiamo un modulo principale e tre centraline la n.1 la n.2 e la n.3
Il modulo principale invia il comando come una stringa da 4 caratteri, X, Y, Z, K dove:
- X e' un preambolo (supponiamo 0x01)
- Y e' il comando (supponiamo 0x02)
- Z e' l'indirizzo del destinatario (supponiamo 0x03, perche' voglio interrgoare la centralina n.3)
- K e' un checksum di chiusura (supponiamo 0x06)
Tutte le centraline ricevono il comando, verificano se sia per loro, e nel caso lo sia rispondono con una sfilza di caratteri:
- A e' un preambolo (supponiamo 0x01)
- B e' il comando cui rispondono (supponiamo 0x02)
- C e' l'indirizzo del mittente, il proprio (supponiamo 0x03)
- D e' l'indirizzo del destinatario, il modulo principale (supponiamo 0x08)
- E, F, G...V sono dei caratteri contenenti i dati in risposta (supponiamo 0x00, 0x01, 0x02, 0x03, 0x04....)
- Z e' un checksum di chiusura (supponiamo 0xAB)
Ok fin qua tutto normale
La domanda e': premesso che nella loro risposta ogni centralina possa sparare qualsiasi valore nei byte dei dati che stanno viaggiando sul cavo, come fare per evitare che nella sfilza di caratteri che costituiscono la risposta (che anche tutte le altre centraline 'vedono', sono tutte collegate su un unico cavo) ci sia una combinazione che possa essere interpretata come un comando che parte dal modulo principale?
Chiedo questo perche' potrebbe verificarsi questa condizione:
- modulo principale invia comando a centralina n.3
- tutte le centraline 'leggono' il comando sul cavo
- solo la centralina n.3 reagisce al comando e restituisce invia la propria risposta
- con riferimento ai dati sopra, se nella risposta della centralina n.3 ci fosse una sequenza del tipo 0x01 0x02 0x02 0x05 verrebbe interpretata dalla centralina n.2 come un comando a lei indirizzato e reagirebbe rispondendo
E quindi, volendo mantenere la possibilita' per ogni byte di poter contenere un valore qualsiasi, come fare per evitare l'eventualita' sopra descritta?
Intuisco che non è la cosa che chiedi ma è il motivo del perché non riesco a venire a capo dello stesso problema. Ho previsto triplette di apertura e chiusura di ciascun pacchetto, e la trasmissione dello stesso per N volte (chiaramente con N buffer su ciascun device). Nessun dispositivo fa niente fino a che non ci sono le N copie e sono uguali.
Purtroppo questo ha introdotto complicazioni con timeout e soprattutto la mia insanabile incomprensione di come funziona un protocollo seriale, mi ha reso impossibile finire il progetto. So che ci sono delle librerie ma come sempre almeno in arduino tra dipendenze e versioni diverse ma con header files con lo stesso nome, più incompatibilità col dispositivo che in quel momento si vuole usare, alla fine ho chiuso il progetto e sto provando con MySensors che è facilmente adattabile a qualcosa di simile a quel che io volevo fare e tu vuoi e riuscirai a fare.
Il 06/03/25 05:00, RobertoA ha scritto:
Proprio per risolvere questo tipo di problemi sono stati introdotti i vari protocolli seriali come, ad es, il venerando Modbus sia RTU che ASCII che funzionano dagli anni '70 del secolo scorso.
Un'altra possibilità che mi viene in mente è usare l'algoritmo COBS (Consistent Overhead Byte Stuffing).
Ci vuole un po' di sbattimento, ma google è tuo amico...
Il 06/03/2025 05:00, RobertoA ha scritto:
Tu puoi modificare il firmware sia dal modulo principale che delle centraline?Sarebbe troppo bello? A prima vista,ma proprio buttando lì,senza sconvolgere il protocollo (per esempio aggiungendo il n° dei bytes "netti" da attendersi ,come fa il Modbus)direi che è necessario lasciare un certo tempo dopo la fine di una trasmissione messaggio, quindi un timer,possibilmente hardware arriva al timeout se non vengono letti caratteri,quindi timeout >t_byte. Solo il primo byte letto da una centralina che ha il timer in timeout viene considerato preambolo. Boh,potrebbe andare?
Il 06/03/2025 09:54, pcf ansiagorod ha scritto:
Non ho capito, rimandi tre volte ogni pacchetto? E porqua? Ma sicuramente ho capito male io Non userei librerie particolari per fare ste robe, se mandi byte per byte hai il pieno controllo delle cose e fai quel che vuoi Nel mio caso volevo ottimizzare la rapidita' di trasmissione, e quindi tenere ogni byte da 0 a ff pur evitando possibili 'incomprensioni' degli slave Ad ogni modo, se hai un problema particolare, descrivilo per benino e posta, magari qualcosa salta fuori, non mi sembrano cose dell'altro mondo c'e' solo da lavorarci un po'
Il 06/03/2025 10:48, Andromeda ha scritto:
Si, il byte stuffing e' una delle possibilita', la papabile per ora Una seconda e' usare dei preamboli piu' complessi, ma questo diminuirebbe solamente la probabilita' di 'incomprensioni' Una terza e' l'utilizzo di byte 'speciali' che non possano essere usati nei dati e che quindi renderebbe la trasmssione dei dati piu' lunga
Per ora sarei orientato sul primo, ma vediamo, magari vien fuori qualche genialata mai vista e si risolve tutto con un trucchetto
Il 06/03/2025 14:51, blisca ha scritto:
Certo posso modificare tutto, software e hardware La lunghezza richieste e risposte e' fissa, 4 byte per la richiesta, 20 byte per la risposta Il problema e' che tutti gli slave 'vedono' le trasmissioni che i colleghi inviano al master, e dentro e' possibile che con una certa configurazione astrale si venga a creare una quadrupleta di byte esattamente corrispondente al comando per se, vedi esempio post iniziale
Il 06/03/2025 16:18, RobertoA ha scritto:
Visto che sono a lunghezza fissa, gli slave devono contare i byte. Lo slave interessato dal comando risponderà, gli altri contano e finché non si raggiunge la lunghezza richiesta, i valori vengono ignorati. Naturalmente c'è il problema di slave che non rispondono ... allora si va di timeout
Il 06/03/2025 18:27, logicMind23 ha scritto:
Non vorrei fare affidamento sulla lunghezza, e' possibile che qualche carattere venga perso per strada, se mi affido alla lunghezza rischio che uno slave non riconosca piu' nessun comando Gli slave devono 'riconoscere' un comando a loro impartito perche' e' una sequenza dei 4 caratteri ed il terzo e' il loro indirizzo In sostanza quando in linea appaiono dei caratteri, sono alla costante ricerca del preambolo e se lo trovano allora attendono gli altri tre caratteri successivi per verificare se e' comando a loro indirizzato
Possono anche perdere il riconoscimento di una richiesta a loro indirizzata, tanto dopo qualche decimo di secondo ne arriva un'altra
Ma quello che non deve accadere e' che riconoscano come richiesta per loro una sequenza che in realta' sono i caratteri di un altro slave che sta rispondendo Si potrebbe innescare un chiacchericcio che tecnicamente potrebbe andare avanti per sempre, poco improbabile, ma potrebbe anche E si sa che se qualcosa puo' andare storto, stai sicuro che lo fara'
Il 06/03/2025 16:18, RobertoA ha scritto:
Si,ma in questo modo non verrebbe considerato iniziale,potrei sbagliare ma non capisco dove
Il 06/03/2025 19:01, RobertoA ha scritto:
per il rischio di qualche byte perso per strada si fa affidamento sul timeout. Lo slave attende il termine della trasmissione (di un altro slave) contando i byte o fino ad un certo tempo (e comunque anche il master deve attendere il completamento della ricezione), quindi se dopo un tot non ci sono più byte, si riparte da capo ...
Grazie, so che posso sempre contare sul gruppo (o almeno fin qui così è stato). Il problema è che non ho talento per nessuna cosa, e questi non sono solo problemi di 'machinery' bensì di capacità di arrangiarsi, conoscere tante cose, mente sveglia che non ho, etc.
Esempio stupido, per un programma che mi funziona ne devo abbandonare 15 quasi sempre perché concepiti male dall'inizio. In un caso in cui lo concepii bene un overflow da qualche parte che non ho trovato con nessun debugger mi ha portato alla disperazione e ho lasciato perdere. Era un progetto grosso (quasi 4 MB di C++ che per me sono tanti) e lo scoramento per averci buttato mesi (e altri due per cercare la falla) poi ha fatto in modo che non ci provassi più.
Ma l'idea di avere arduini molto lontani che comunicano con l'RS qualcosa (insomma, lo standard a due fili bilanciati) mi farebbe ancora comodo, forse riprenderò il progetto e chiederò lumi al bisogno.
ciao :)
A.
Il 06/03/2025 10:48, Andromeda ha scritto:
Voto per questa soluzione che risolve diversi problemi.
Decidi il tuo byte di fine (e volendo anche inizio) frame, per esempio
0x00. Il COBS allunga leggermente il frame, sostituendo eventuali 0x00 del payload in altri byte. Chiaramente il ricevitore farà lo stesso al contrario.Questo ti permette di eliminare qualsiasi tipo di timeout nei ricevitori. Questi stanno sempre in ascolto, quando vedono 0x00, per loro è finito un frame e lo elaborano. Semplice ed efficace.
Se decidi di mandare 0x00 sia alla fine che all'inizio del frame, al massimo il ricevitore vedrà un frame vuoto che, chiaramente, scarterà.
Vai così e vedrai che ti troverai bene.
Il 07/03/2025 16:39, alfio ha scritto:
Un po' antipatico per il ricevente. Diciamo che lo start byte è 0x00 che delimita anche la fine del frame. Alla ricezione di uno 0x00 il ricevente non può essere sicuro subito che si tratti di fine frame oppure di uno 0x00 nel payload che verrà raddoppiato con il prossimo byte ancora da ricevere. Bisognerebbe implementare dei meccanismi a timeout, secondo me inutili.
E' vero che la lunghezza del frame fissa aiuta in questo caso, ma io non farei un protocollo che funziona solo per frame a lunghezza fissa. L'appetito vien mangiando e un domani si potrebbe voler aggiungere altri nodi sul bus che inviano più o meno cose. Meglio essere future proof.
Su questa falsa riga, i comandi potrebbero essere *tutti* ASCII e del tipo:
TX0102AAFFDE\r\n
dove TX è il prefisso di un frame, poi ci sono i dati convertiti in ASCII esadecimale (inclusi comando, indirizzo, payload, checksum, ecc) e poi \r\n è il suffisso.
Se accetti un aumento considerevole della dimensione del frame (più del doppio) ed una leggera complicazione nella decodifica (conversione ASCII esadecimale->binario) è un protocollo comodo in quanto leggibile direttamente su PC con putty.
Un bel giorno RobertoA digitò:
Esattamente come avviene per CAN bus, MODBUS ecc... ogni centralina riceve tutti i messaggi fino al checksum. Non è che appena si accorge che un messaggio non è destinato a lei cessi di riceverlo. Quindi tutte le centraline leggeranno il comando, poi tutte le centraline leggeranno la risposta della centralina 3, eccetera. Non è che una centralina si svegli al centro di un messaggio e inizi a interpretarlo a caso.
Ovviamente c'è la questione degli errori di trasmissione/ricezione: se una centralina per qualunque motivo legge un header sbagliato, potrebbe "disallinearsi". Ma questo è un altro discorso. Molti protocolli a questo scopo dispongono di una sequenza "speciale" di byte che è usata solo negli header dei pacchetti; in questo modo se una centralina si disallinea ignorerà tutto fino alla prossima sequenza speciale.
Il 07/03/2025 13:09, pcf ansiagorod ha scritto:
Sembra tu stia attraversando un momento particolare Io consiglierei di guardare al mezzo pieno, tanto guardare al mezzo vuoto serve a una sega Gia' il fatto di concepire qualcosa vuol dire che puoi figliare, e se ci pensi questo e' in definitiva il succo della vita Che poi sia stato concepito male, chi e' che lo dice? Anzi chi e' che si permette di dirlo, ehhh?
Il 07/03/2025 08:30, blisca ha scritto:
Questa e' carina dai Adesso la mando a pfc che sembra in fase di smonamento acuto, cosi' si fara' quattro risate, beh insomma, due risate
Have something to add? Share your thoughts — no account required.
Ask the community — no account required