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?
microcontroller
serial
communication
uart
protocol
No tengo ni idea de lo que estoy haciendo
fuente
fuente
Respuestas:
ASCII y CRC no son mutuamente excluyentes. ASCII es una codificación y CRC es para verificación de errores.
CUALQUIER COSA se puede enviar como ASCII. Nosotros, los viejos, ciertamente recordamos UUEncoding, que convierte cualquier cosa en una cadena ASCII.
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").
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.
fuente
Aquí hay algunos pensamientos al respecto:
fuente
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.
fuente
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).
fuente
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.
fuente
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
fuente
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.
fuente
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.
fuente