¿Cuándo se debe cambiar de ASCII a protocolos seriales avanzados?

28

Todos mis dispositivos microcontroladores que se comunican con la PC a través de UART usan cadenas ASCII para enviar comandos y recibir datos (como se implementa en Arduino). Eso es lo que aprendí cuando comencé a cavar en electrónica y siempre encontré que enviar cadenas desnudas era suficiente. Sin embargo, noté que la mayoría de los dispositivos que encontré usan protocolos binarios sofisticados que incluyen códigos de función, direcciones y verificación de errores CRC.

¿Cuándo es aceptable la comunicación básica ASCII y cuándo debería considerar algo más avanzado, como Modbus? ¿Los dispositivos comerciales usan tales ASCII? ¿Industrial?

No tengo ni idea de lo que estoy haciendo
fuente
3
Respuesta corta: cuando su aplicación lo necesita. Sí, los dispositivos comerciales usan ASCII. Tome GPS NMEA como ejemplo. (Y nuevamente, haré referencia a mi propia pregunta aquí )
Eugene Sh.
1
Modbus tiene un modo ASCII. Consulte la Guía de referencia del protocolo Modicon Modbus
Tut
@EugeneSh .: Vale la pena señalar que NMEA tiene un campo de suma de verificación, y dejar caer una sola ráfaga de muestra debido a una falla de la suma de verificación (que ocurre con más frecuencia de lo que parece) generalmente no es una falla crítica. Es muy posible que ese no sea el caso para otros protocolos ... y hay muchos protocolos binarios de GPS en uso (por ejemplo, Garmin) para aplicaciones en las que de hecho puede ser crítico (o en las que una frecuencia de muestreo superior a 1Hz es requerido, para lo cual NMEA es demasiado detallado). Aunque esto realmente solo solidifica tu punto.
Lightness compite con Monica el

Respuestas:

28
  1. ASCII y CRC no son mutuamente excluyentes. ASCII es una codificación y CRC es para verificación de errores.

  2. CUALQUIER COSA se puede enviar como ASCII. Nosotros, los viejos, ciertamente recordamos UUEncoding, que convierte cualquier cosa en una cadena ASCII.

  3. A) Para mí, generalmente es una cuestión de velocidad y eficiencia. Enviar un número grande de 32 bits por ASCII puede llevar mucho tiempo, pero solo se necesitan 4 bytes para enviarlo como binario a través de un protocolo en serie.

    B) Enviar NÚMEROS a través de ASCII significa que debe convertir el número a ASCII, que es un paso adicional claro (esto es parte de lo que hace "printf").

  4. Si de alguna manera pierdes tu lugar, te equivocas, pierdes el formato, obtienes el endian incorrecto, etc., un protocolo de comunicación binario puede arruinarlo. Si está enviando ASCII, puede ser más fácil recuperarse de los problemas simplemente entrando y MIRANDO el flujo de datos.

Scott Seidman
fuente
12
+1 para "ASCII es una codificación". No es un protocolo; Los protocolos se pueden construir sobre ASCII.
Pete Becker
8
La recuperación automática de un error no es intrínsecamente más fácil para un protocolo basado en texto como binario, pero la inspección y depuración ciertamente puede serlo.
Nick Johnson
1
@NickJohnson, absolutamente. Una vez que está a punto de abrir un archivo en un editor hexadecimal para ver lo que puede recuperar, ya está en FUBAR en lo que respecta a SOP
Scott Seidman
1
@nickjohnson eso no es realmente cierto. ASCII le ofrece muchas opciones de encuadre / delimitador fuera de banda para ayudar a la sincronización y recuperación, lo que requeriría escape adicional, relleno de bits, intervalo de tiempo u otros trucos si el canal se usa para datos binarios de ancho completo.
Chris Stratton
2
Siempre prefiero ASCII cuando escribo protocolos para todos los beneficios obvios (legibilidad, logabilidad, etc.). Hay dos casos en que el binario tiene más sentido: primero, si la velocidad es un problema y necesita binario para meter la mayor cantidad de datos posible en la secuencia, y segundo, marginalmente, si está tratando de ofuscar o incluso cifrar los datos deliberadamente transmisión para obstaculizar o prevenir la ingeniería inversa. En ese momento, tengo protocolos binarios de ingeniería inversa y en gran medida me ha irritado más de lo que realmente evitó el acto.
J ...
10

Aquí hay algunos pensamientos al respecto:

  • ASCII es bueno porque puede usar un monitor en serie para tener una apariencia manual en lo que se envía.
  • Si su conexión no es confiable, debe esperar errores de transmisión y debe usar un CRC para verificar la integridad de cada mensaje recibido. Esto también se puede hacer en mensajes ASCII.
  • Si su conexión es demasiado lenta, puede reducir el tamaño de sus mensajes cambiando a un formato binario
  • Un formato binario especializado puede ser más fácil de decodificar en el lado del receptor que ASCII
MrSmith42
fuente
7

En el nivel más simple, se podría decir que un protocolo de comunicación simple tiene tres capas: física, transporte y aplicación. (Hay modelos con más, como OSI con 7 o TCP / IP con 4. El número de capas no es muy importante en el contexto de esta pregunta).

La capa de aplicación es la capa con la que trata directamente en su código, y el foco de la pregunta. En lo que respecta a la capa de transporte, el byte que le pasó en send_data es solo un patrón binario, pero puede interpretarlo en su código de aplicación como la letra 'A'. El cálculo de CRC o suma de verificación será el mismo independientemente de si considera que el byte es 'A', 0x41 o 0b01000001.

La capa de transporte es el nivel de paquete, donde tiene sus encabezados de mensajes y verificación de errores, ya sea CRC o una suma de verificación básica. En el contexto del firmware, puede tener una función como send_data, donde le pasa un byte para enviar. Dentro de esa función, se coloca en un paquete que dice: "Hola, este es un mensaje normal, requiere un acuse de recibo y la suma de comprobación es 0x47, la hora actual es X". Este paquete se envía a través de la capa física al nodo receptor.

La capa física es donde se definen la electrónica y la interfaz: conectores, niveles de voltaje, temporización, etc. Esta capa puede variar desde un par de trazas que ejecutan señales TTL para un UART básico en una PCB, hasta un par diferencial completamente aislado como en algunos Implementaciones CAN .

En el nodo receptor, el paquete entra en la capa física, se desempaqueta en la capa de transporte y luego su patrón binario está disponible para la capa de aplicación. Depende de la capa de aplicación del nodo receptor saber si ese patrón debe interpretarse como 'A', 0x41 o 0b01000001, y qué hacer con él.

En conclusión, es casi siempre aceptable enviar caracteres ASCII si eso es lo que requiere la aplicación. Lo importante es comprender su esquema de comunicación e incluir un mecanismo de verificación de errores.

Matt Young
fuente
Los protocolos Ascii también pueden incorporar suma de verificación. He encontrado variaciones Hex-as-ascii, usando la representación ascii de números.
Eugene Sh.
@EugeneSh. Aclaró ese punto
Matt Young
No es una trampa, pero TCP no son cuatro capas; se ve como apropiado en la capa cuatro del modelo OSI. Las comunicaciones en serie realmente no se ajustan muy bien al modelo OSI.
batsplatsterson
@batsplatsterson Eso es muy curioso y bastante irrelevante para el punto que estoy haciendo.
Matt Young
5

Un punto que aún no se menciona es que si uno está usando ASCII o un protocolo binario, enviar un carácter de borrado antes de cada paquete garantizará que, incluso si aparecen ruidos de línea o errores de trama antes del inicio de un paquete, todos los caracteres después del borrado fuera se enmarcará correctamente en ausencia de más ruido. De lo contrario, si uno envía paquetes de forma continua y no incluye ningún carácter que garantice la resincronización, es posible que una falla pueda corromper todo lo que sigue hasta la próxima pausa en la transmisión. El carácter 0xFF es bueno porque garantiza que cualquier destinatario podrá resincronizar con el siguiente carácter.

(*) 0xFF: llamado eliminación porque alguien que escribe un carácter erróneo mientras escribe datos en una cinta de papel puede presionar el botón "paso atrás de la cinta" y presionar el borrado para reemplazar el carácter perforado erróneamente con 0xFF, que ser ignorado por la mayoría de los destinatarios).

Super gato
fuente
2

Una ventaja de enviar cadenas ASCII es que los códigos de control se pueden usar para señalar el inicio / fin del mensaje. Por ejemplo, STX (char 2) y ETX (char 3) pueden indicar la transmisión de inicio y finalización de la transmisión. Alternativamente, puede agregar un avance de línea simple para marcar el final de la transmisión.

Cuando se envían datos binarios, esto se vuelve más complicado ya que ningún patrón de bits particular puede reservarse para un código de control (sin cierta sobrecarga o complejidad adicional) ya que un byte de datos válido puede tener el mismo patrón.

Transistor
fuente
3
Muchos protocolos binarios SÍ reservan uno o más patrones de bits como códigos de control, pero también incluyen un mecanismo de escape para manejar esos códigos cuando aparecen en los datos.
Dave Tweed
Puede reservar cualquier patrón para marcar lo que desee en binario. Por ejemplo, estoy en proyectos con un flujo de datos rápido y un flujo de datos lento que sale por el mismo canal. Reservé el int32 negativo más grande como una marca para mis datos lentos, y solo saturo mis datos negativos en el negativo más grande + 1.
Scott Seidman
Convenido. Aclaré esto en la respuesta editada, espero.
Transistor
2

ASCII está bien, lo uso en casi todos los proyectos. Hace que la depuración sea mucho más fácil para monitorear el puerto, y solo se convertiría en un problema si hubiera muchos datos para enviar.

Otra ventaja es que uso dispositivos de radio en serie para recibir mensajes entre arduinos, y puedo usar un monitor en serie conectado a mi computadora portátil e inyectar mensajes para que ciertas cosas sucedan. Genial para probar.

Además, enviar cosas como binario no es imposible de depurar y, dependiendo de sus herramientas, puede extraer el binario y convertirlo en algo legible por humanos. O si sabe lo que está buscando, puede inspeccionar visualmente el flujo de datos y reconocer los valores donde deberían estar, y encontrarlos de esa manera, aunque no con tanta facilidad. es decir, reconocerá los patrones de bytes y reconocerá los valores esperados

Madivad
fuente
2

En lugar de Modbus, considere HDLC . Obtiene detección de errores (que es importante en las líneas seriales ruidosas). La sincronización es robusta, el escape es robusto.

He usado HDLC en redes RS-485 sin problemas y PPP también lo usa.

teambob
fuente
2
Sería bueno si señalaras por qué lo sugieres sobre Modbus.
No tengo idea de lo que estoy haciendo el
1

ASCII sobre UART es el más popular en parte porque:

  • Es legible para humanos cuando se depura (todavía tengo que ver un analizador lógico que no decodifique ASCII).

  • Es muy fácil de implementar, tiene una tabla ASCII a través de google rápido que está bien estandarizada.

  • Se ha construido en sincronización con los bits de inicio / parada.

  • Casi todo el mundo más aficionado se ha establecido con ASCII en serie, por lo que cualquier método nuevo tendrá que lidiar con eso, y eso no es fácil de ninguna manera.

Luego, te encuentras en una situación en la que comienzas a enviar codificación específica, como enviar la representación en memoria de un flotante en comparación con la conversión de un flotante a ASCII, enviarlo en serie que puede tener más de 4 bytes y luego convertirlo de nuevo a una representación en memoria en el host. En cambio, solo envía la representación de 4 bytes cada vez. Claro, puede comenzar a manejar la codificación usted mismo, pero luego debe configurar las etiquetas de inicio / fin, el orden, etc.

En cambio, se pueden usar cosas como Protobuf . Esto realmente se usó en un proyecto en el que estaba trabajando y fue extremadamente beneficioso, envía mensajes de longitud variable, maneja endian para usted y algunas otras características interesantes. Tampoco es tan grande en tamaño de código, y puede especificar todo lo que se asignará estáticamente al inicio. Sin embargo, tendrías que agregar la suma de control si lo necesitas.

hak8or
fuente