Quando si dovrebbe passare da ASCII a protocolli seriali avanzati?


28

Tutti i miei dispositivi a microcontrollore che comunicano con il PC tramite UART utilizzano stringhe ASCII per inviare comandi e ricevere dati (come implementato in Arduino). Questo è quello che ho imparato quando ho iniziato a scavare nell'elettronica e ho sempre trovato l'invio di stringhe nude per essere abbastanza. Tuttavia ho notato che la maggior parte dei dispositivi che ho incontrato utilizzano sofisticati protocolli binari che includono codici funzione, indirizzi e controllo degli errori CRC.

Quando è accettabile la comunicazione ASCII di base e quando dovrei considerare qualcosa di più avanzato, come Modbus? I dispositivi commerciali utilizzano tali ASCII? Industriale?


3
Risposta breve: quando l'applicazione ne ha bisogno. Sì, i dispositivi commerciali utilizzano ASCII. Prendi GPS NMEA come esempio. (E di nuovo, farò qui la mia domanda )
Eugene Sh.

1
Modbus ha una modalità ASCII. Vedere la Guida di riferimento al protocollo Modicon Modbus
Tut

@EugeneSh .: Vale la pena notare che NMEA ha un campo di checksum e far cadere un singolo campione a causa di un errore di checksum (che accade più spesso di quanto si possa pensare) non è generalmente un errore critico. Molto bene potrebbe non essere il caso di altri protocolli ... e ci sono molti protocolli GPS binari in uso (ad esempio Garmin) per applicazioni in cui potrebbe essere davvero critico (o in cui una frequenza di campionamento superiore a 1Hz è richiesto, per il quale NMEA è troppo dettagliato). Anche se questo non fa che rafforzare il tuo punto di vista.
Lightness Races con Monica il

Risposte:


28
  1. ASCII e CRC non si escludono a vicenda. ASCII è una codifica e CRC è per il controllo degli errori.

  2. TUTTO può essere inviato come ASCII. Noi anziani ricordiamo sicuramente UUEncoding, che trasforma qualsiasi cosa in una stringa ASCII.

  3. A) Per me, di solito è una questione di velocità ed efficienza. L'invio di un numero di 32 bit di grandi dimensioni tramite ASCII può richiedere molto tempo, ma bastano solo 4 byte per inviarlo come binario tramite un protocollo seriale.

    B) L'invio di NUMERI tramite ASCII significa che devi convertire il numero in ASCII, il che è un chiaro passo in più (fa parte di ciò che fa "printf").

  4. Se in qualche modo perdi il tuo posto, rovini, perdi il formato, ottieni un endian sbagliato, ecc., Un protocollo di comunicazione binario può sicuramente rovinare. Se stai inviando ASCII, può essere più facile recuperare dagli errori semplicemente entrando e guardando il flusso di dati.


12
+1 per "ASCII è una codifica". Non è un protocollo; i protocolli possono essere costruiti sopra ASCII.
Pete Becker,

8
Il ripristino automatico da un errore non è intrinsecamente più semplice per un protocollo testuale come binario, ma controllarlo e eseguirne il debug sicuramente lo sarà.
Nick Johnson,

1
@NickJohnson - assolutamente. Una volta che sei sul punto di aprire un file in un editor esadecimale per vedere cosa puoi recuperare, sei già a FUBAR per quanto riguarda SOP
Scott Seidman,

1
@nickjohnson non è proprio vero. ASCII offre molte opzioni di inquadratura / delimitatore fuori banda per facilitare la sincronizzazione e il recupero, che richiederebbero ulteriori escape, bit stuffing, intervallo di tempo o altri trucchi se il canale viene utilizzato per dati binari a larghezza intera.
Chris Stratton,

2
Prediligo sempre ASCII quando scrivo protocolli per tutti gli ovvi benefici (leggibilità, logabilità, ecc.). Ci sono due casi in cui il binario ha più senso: in primo luogo, se la velocità è un problema e hai bisogno del binario per stipare il maggior numero possibile di dati nello stream, e in secondo luogo, marginalmente, se stai deliberatamente cercando di offuscare o persino crittografare i dati flusso per ostacolare o impedire il reverse engineering. A quel punto, ho invertito i protocolli binari e mi ha in gran parte irritato più di quanto abbia effettivamente impedito l'atto.
J ...

10

Ecco alcuni pensieri a riguardo:

  • ASCII è bello perché puoi usare un monitor seriale per dare un'occhiata manuale a ciò che viene inviato.
  • se la connessione non è affidabile, è necessario prevedere errori di trasmissione e utilizzare un CRC per verificare l'integrità di ciascun messaggio ricevuto. Questo può essere fatto anche su messaggi ASCII.
  • se la connessione è troppo lenta è possibile ridurre la dimensione dei messaggi passando a un formato binario
  • Un formato binario specializzato può essere più semplice da decodificare sul lato ricevitore rispetto ad ASCII

7

Al livello più semplice, si potrebbe dire che un semplice protocollo di comunicazione ha tre livelli: fisico, trasporto e applicazione. (Esistono modelli con più come OSI con 7 o TCP / IP con 4. Il numero di livelli non è tremendamente importante nel contesto di questa domanda.)

Il livello dell'applicazione è il livello che gestisci direttamente nel tuo codice e il fulcro della domanda. Per quanto riguarda il livello di trasporto, il byte che gli è stato passato in send_data è solo un modello binario, ma è possibile interpretarlo nel codice dell'applicazione come la lettera 'A'. Il calcolo CRC o checksum sarà lo stesso indipendentemente dal fatto che si consideri il byte come 'A,' 0x41 o 0b01000001.

Il livello di trasporto è il livello del pacchetto, in cui sono presenti le intestazioni dei messaggi e il controllo degli errori, sia esso CRC o un checksum di base. Nel contesto del firmware, potresti avere una funzione come send_data, dove gli passi un byte da inviare. All'interno di quella funzione viene inserito in un pacchetto che dice "Hey, questo è un messaggio normale, richiede un riconoscimento e il checksum è 0x47, l'ora corrente è X." Questo pacchetto viene inviato attraverso il livello fisico al nodo ricevente.

Lo strato fisico è il punto in cui sono definiti l'elettronica e l'interfaccia: connettori, livelli di tensione, temporizzazione, ecc. Questo strato può variare da un paio di tracce che eseguono segnali TTL per un UART di base su un PCB, a una coppia differenziale completamente isolata come in alcuni Implementazioni CAN .

Nel nodo ricevente, il pacchetto entra nel livello fisico, viene decompresso nel livello di trasporto e quindi il modello binario è disponibile per il livello applicazione. Spetta al livello dell'applicazione del nodo ricevente sapere se quel modello deve essere interpretato come 'A,' 0x41 o 0b01000001 e cosa fare con esso.

In conclusione, è quasi sempre accettabile inviare caratteri ASCII se questo è ciò che richiede l'applicazione. L'importante è comprendere il tuo schema di comunicazione e includere un meccanismo di controllo degli errori.


Anche i protocolli Ascii possono incorporare checksum. Ho riscontrato variazioni esadecimali come ascii, usando la rappresentazione ascii dei numeri.
Eugene Sh.

@EugeneSh. Chiarito questo punto
Matt Young,

Non per nitpick, ma TCP non è a quattro livelli; è visto come adattamento nel livello quattro del modello OSI. Le comunicazioni seriali non si adattano molto bene al modello OSI.
batsplatsterson il

@batsplatsterson Questo è pignolo, e abbastanza irrilevante al punto che sto sottolineando.
Matt Young,

5

Un punto non ancora menzionato è che se si utilizza ASCII o un protocollo binario, l'invio di un carattere di eliminazione prima di ogni pacchetto assicurerà che anche se il rumore di linea o gli errori di inquadratura compaiono prima dell'inizio di un pacchetto, tutti i caratteri dopo out sarà correttamente inquadrato in assenza di ulteriore rumore. Altrimenti, se si inviano continuamente pacchetti e non si includono caratteri garantiti per la risincronizzazione, è possibile che un problema tecnico possa corrompere tutto ciò che segue fino alla prossima pausa nella trasmissione. Il carattere 0xFF è carino perché garantisce che qualsiasi destinatario sarà in grado di risincronizzarsi sul seguente carattere.

(*) 0xFF - chiamato rub-out perché qualcuno che digita un carattere errato durante la digitazione di dati su un nastro di carta può premere il pulsante "step tape backward" e premere rub-out per sostituire il carattere perforato erroneamente con 0xFF, che essere ignorato dalla maggior parte dei destinatari).


2

Un vantaggio dell'invio di stringhe ASCII è che i codici di controllo possono quindi essere utilizzati per segnalare l'inizio / la fine del messaggio. ad es. STX (carattere 2) ed ETX (carattere 3) possono segnalare l'inizio della trasmissione e la fine della trasmissione. In alternativa è possibile aggiungere un semplice avanzamento riga per contrassegnare la fine della trasmissione.

Quando si inviano dati binari, questo diventa più complicato poiché nessun particolare schema di bit può essere riservato per un codice di controllo (senza un sovraccarico o complessità in più) in quanto un byte di dati valido può avere lo stesso schema.


3
Molti protocolli binari riservano uno o più pattern di bit come codici di controllo, ma includono anche un meccanismo di escape per gestire tali codici quando compaiono nei dati.
Dave Tweed

Puoi riservare qualsiasi motivo per contrassegnare tutto ciò che vuoi in binario. Ad esempio, sono su un progetto con un flusso di dati veloce e un flusso di dati lento che esce allo stesso modo. Ho riservato il più grande int32 negativo come bandiera per i miei dati lenti e ho semplicemente saturato i miei dati negativi al più grande negativo + 1.
Scott Seidman

Concordato. L'ho chiarito nella risposta modificata, spero.
Transistor

2

ASCII va bene, lo uso praticamente in tutti i progetti. Rende molto più facile il debug per il monitoraggio della porta e diventerebbe un problema solo se ci fossero molti dati da inviare.

Un altro vantaggio, utilizzo i dispositivi radio seriali per ricevere messaggi tra gli arduinos e posso usare un monitor seriale collegato al mio laptop e iniettare messaggi per far accadere determinate cose. Ottimo per i test.

Inoltre, inviare cose come binarie non è impossibile da eseguire il debug e, a seconda dei tuoi strumenti, puoi avere il binario estratto e convertito in qualcosa di leggibile. Oppure, se sai cosa stai cercando, puoi ispezionare visivamente il flusso di dati e riconoscere i valori in cui dovrebbero trovarsi e trovare l'errore in questo modo, anche se non così facilmente. cioè, riconoscerai i modelli di byte e riconoscerai i valori previsti


2

Invece di Modbus considerare HDLC . Ottieni il rilevamento degli errori (che è importante su linee seriali rumorose). La sincronizzazione è solida, la fuga è solida.

Ho usato l'HDLC nelle reti RS-485 senza problemi e anche PPP lo usa.


2
Sarebbe bello se facessi notare perché lo consigli su Modbus.
Non ho idea di cosa sto facendo il

1

ASCII su UART è il più popolare in parte perché:

  • È leggibile dall'uomo durante il debug (devo ancora vedere un analizzatore di logica che non decodifica ASCII).

  • È molto facile da implementare, hai una tabella ASCII tramite google veloce che è ben standardizzata.

  • Ha una sincronizzazione integrata con i bit di avvio / arresto.

  • Praticamente tutto il mondo degli hobbisti si è impostato con ASCII su seriale, quindi ogni nuovo metodo dovrà affrontarlo, e non è affatto facile.

Quindi ti trovi in ​​una situazione quando inizi a inviare una codifica specifica, come l'invio della rappresentazione in memoria di un float rispetto alla conversione di un float in ASCII, l'invio su seriale che può essere di oltre 4 byte e quindi riconvertirlo a una rappresentazione in memoria sull'host. Invece, devi solo inviare la rappresentazione a 4 byte ogni volta. Certo, puoi iniziare a gestire tu stesso la codifica, ma poi devi impostare tag di inizio / fine, ordine, ecc.

Invece, si possono usare cose come Protobuf . Questo è stato effettivamente utilizzato in un progetto a cui stavo lavorando ed è stato estremamente vantaggioso, fa messaggi di lunghezza variabile, gestisce endian per te e alcune altre interessanti funzioni. Inoltre, non è così grande nella dimensione del codice e puoi specificare tutto da assegnare staticamente all'avvio. Dovresti comunque lanciarti nel checksum, se ne hai bisogno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.