¿Cuándo debería uno cambiar de ASCII a protocolos seriales avanzados?

27

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 implementó en Arduino). Eso es lo que aprendí cuando comencé a indagar en la electrónica y siempre encontré que enviar cadenas desnudas era suficiente. Sin embargo, me di cuenta de que la mayoría de los dispositivos que encontré utilizan sofisticados protocolos binarios que incluyen códigos de función, direcciones y verificación de errores CRC.

¿Cuándo es aceptable la comunicación ASCII básica y cuándo debo considerar algo más avanzado, como Modbus? ¿Los dispositivos comerciales utilizan tal ASCII? Industrial?

    

8 respuestas

28
  1. ASCII y CRC no se excluyen mutuamente. ASCII es una codificación, y CRC es para la comprobación de errores.

  2. CUALQUIER COSA puede enviarse como ASCII. Nosotros, los antiguos, sin duda recordamos UUEncoding, que convierte cualquier cosa en una cadena ASCII.

  3. A) Para mí, generalmente es una cuestión de velocidad y eficiencia. El envío de un gran número 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 tienes que convertir el número a ASCII, lo que es un paso adicional claro (esto es parte de lo que hace "printf").

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

respondido por el Scott Seidman
10

Aquí hay algunos pensamientos al respecto:

  • ASCII es bueno porque puedes usar un monitor en serie para tener un aspecto manual de 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 los 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
respondido por el MrSmith42
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 terriblemente 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 enfoque de la pregunta. En lo que respecta a la capa de transporte, el byte que le pasaste en send_data es solo un patrón binario, pero puedes interpretarlo en el código de tu aplicación como la letra 'A'. El cálculo de CRC o suma de comprobació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 los encabezados de sus mensajes y la comprobación de errores, ya sea CRC o una suma de comprobació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: "Oye, 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 abarcar 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 algunas implementaciones de CAN .

En el nodo receptor, el paquete entra en la capa física, se desempaqueta en la capa de transporte y, a continuación, 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 comprobación de errores.

    
respondido por el Matt Young
5

Un punto que aún no se menciona es que si uno usa ASCII o un protocolo binario, enviar un carácter de borrado antes de cada paquete asegurará que incluso si el ruido de línea o los errores de trama aparecen antes del inicio de un paquete, todos los caracteres después el borrado se encuadrará correctamente en ausencia de más ruido. De lo contrario, si uno envía paquetes continuamente y no incluye ningún carácter que garantice la resincronización, es posible que una falla pueda dañar todo lo que sigue hasta la siguiente pausa en la transmisión. El carácter 0xFF es agradable porque garantiza que cualquier destinatario podrá volver a sincronizarse con el siguiente carácter.

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

    
respondido por el supercat
2

Una de las ventajas de enviar cadenas ASCII es que los códigos de control se pueden usar para indicar el inicio / final del mensaje. p.ej. STX (char 2) y ETX (char 3) pueden indicar la transmisión de inicio y finalizació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 complica, ya que no se puede reservar un patrón de bits en particular para un código de control (sin una sobrecarga o complejidad adicional), ya que un byte de datos válido puede tener el mismo patrón.

    
respondido por el 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 adicional: 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. Ideal para pruebas.

Además, enviar cosas como binario no es imposible de depurar y, dependiendo de sus herramientas, puede hacer que el binario se extraiga y se convierta 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 encontrar los fallos de esa manera, aunque no tan fácilmente. es decir, reconocerá los patrones de bytes y reconocerá los valores esperados

    
respondido por el Madivad
2

En lugar de Modbus, considere HDLC . Obtiene detección de errores (lo cual es importante en 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.

    
respondido por el teambob
1

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

  • Es legible para los humanos cuando se realiza la depuración (aún no he visto un analizador lógico que no descodifique ASCII).

  • Es muy fácil de implementar, tienes una tabla ASCII a través de Google rápida que está bien estandarizada.

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

  • Casi todo el mundo de hobbyst se ha configurado con ASCII en serie, por lo que cualquier nuevo método 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 una codificación específica, como enviar la representación en memoria de un flotador en comparación con la conversión de un flotador a ASCII, enviarlo por serial, que puede ser de más de 4 bytes, y luego convertir eso de nuevo a una representación en memoria en el host. En su lugar, solo envías la representación de 4 bytes cada vez. Claro, puede comenzar a manejar la codificación usted mismo, pero luego necesita configurar etiquetas de inicio / finalización, orden, etc.

En su lugar, se pueden usar cosas como Protobuf . Esto realmente se usó en un proyecto en el que estaba trabajando y fue extremadamente beneficioso, hace 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á de forma estática en el inicio. Sin embargo, usted tendría que tirar la suma de comprobación, si la necesita.

    
respondido por el hak8or

Lea otras preguntas en las etiquetas