Protocolo de comunicación simple punto a punto en serie


Necesito un protocolo de comunicación simple entre dos dispositivos (un PC y un microcontrolador). El PC debe enviar algunos comandos y parámetros al micro. El micro debe transmitir una matriz de bytes (datos del sensor).

Los datos deben estar protegidos contra el ruido (además de la comprobación de paridad, creo que necesito algún otro método de corrección de datos).

¿hay alguna solución estándar para hacer esto? (Solo necesito una idea, no la solución completa).

P.d. Cualquier consejo es apreciado. P. P. S Lo siento por cualquier error gramatical, espero que lo entiendas.

Editar 1. No he decidido si será maestro / esclavo protocolo o ambas partes pueden iniciar la comunicación. El PC debe saber cuándo micro ha hecho un trabajo y puede enviar datos. Puede sondear continuamente el micro si los datos están listos, o el micro puede enviar datos cuando se realiza un trabajo. No se cual es mejor y mas simple.

Editar 2. Hardware y protocolo de capa física. Desde RS-232 C serial standard usado en el PC, usaré comunicación asíncrona . Usaré solo señales RxD, TxD y GND. No puedo usar cables adicionales porque el microcontrolador AFAIK no los soporta. Por cierto, estoy usando el chip AVR ATmega128.

Así que usaré velocidad de baudios fija, 8 bits de datos, 2 bits de parada sin comprobación de paridad (o con?).

Enlace de datos protocolo. Eso es lo que más preocupa a mi pregunta. Gracias por sugerir HDLC, Protocolos PPP y Modbus. Lo investigaré.

Author: Vanuan, 2009-05-03

12 answers

Usaría HDLC. He tenido buena suerte con él en el pasado. Para una serie punto a punto, simplemente usaría el Encuadre asíncrono y me olvidaría de todas las otras cosas de control, ya que probablemente sería exagerado.

Además de usar HDLC para enmarcar el paquete. Formateo mi paquete como el siguiente. Así es como se pasan las opciones usando 802.11

U8 cmd;
U8 len;
u8 payload[len];

El tamaño total de cada paquete de órdenes es len + 2

Luego defines comandos como

#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02

La otra ventaja es que puede agregar nuevos comandos y si diseña su analizador correctamente para ignorar comandos indefinidos, entonces tendrá cierta compatibilidad con versiones anteriores.

Así que uniendo todo el paquete se vería como el siguiente.

 // total packet length minus flags len+4
 U8 sflag;   //0x7e start of packet end of packet flag from HDLC
 U8 cmd;     //tells the other side what to do.
 U8 len;     // payload length
 U8 payload[len];  // could be zero len
 U16 crc;
 U8 eflag;   //end of frame flag

El sistema entonces monitoreará la secuencia serial para la bandera 0x7e y cuando está allí usted comprueba la longitud para ver si es pklen >= 4 y pklen=len+4 y que el crc es válido. Nota no confíe solo en crc para paquetes pequeños obtendrá una gran cantidad de falsos positivos también comprobar la longitud. Si la longitud o crc no coincide, simplemente restablezca la longitud y crc y comience con la decodificación del nuevo marco. Si es una coincidencia, copie el paquete a un nuevo búfer y páselo a su función de procesamiento de órdenes. Siempre restablezca la longitud y el crc cuando se recibe un indicador.

Para su función de procesamiento de comandos, tome el cmd y el len y luego use un interruptor para manejar cada tipo de comando. También requiero que ciertos eventos envíen un respuesta por lo que el sistema se comporta como una llamada a procedimiento remoto que está impulsada por eventos.

Así, por ejemplo, el dispositivo sensor puede tener un temporizador o responder a un comando para tomar una lectura. Luego formatearía un paquete y lo enviaría al PC y el PC respondería que recibió el paquete. Si no, entonces el dispositivo sensor podría volver a enviar en un tiempo de espera.

También cuando está haciendo una transferencia de red, debe diseñarla como una pila de red como el OSI modle como Foredecker los puntos no se olviden de la capa física . Mi post con el HDLC es la capa de enlace de datos y el RPC y el manejo de comandos es la Capa de Aplicación.

 34
Author: Rex Logan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:05

Los protocolos RS232 son complicados. La sugerencia de usar HDLC, es buena, pero no es la solución completa. Hay otras cosas que usted necesita decidir:

  • ¿Cómo se determinará la velocidad en baudios entre los dos dispositivos? ¿Autobuad? Predefinido, o establecer explicar?
  • ¿Hará control de flujo en software o hardware o ambos? Tenga en cuenta, si utiliza control de flujo de hardware, entonces debe asegurarse de que los cables estén construidos correctamente.
  • Hablando de cables, este es un dolor enorme con RS233. Dependiendo del dispositivo, es posible que necesite usar un cable recto, un cable cruzado o una variante.
  • El uso de un mecanismo de control de flujo basado en software puede ser efectivo, ya que permite el uso del cable más simple: solo tres cableados (TX, RX y common).
  • ¿Eliges una palabra de 7 u 8 bits?
  • Paridad de HW o comprobación de errores de software.

Le sugiero que vaya con 8 bits de datos, sin paridad de hardware, 1 bit de parada y use flujo basado en software control. Debe usar autobaud si su hardware lo admite. Si no, entonces autobaud es diabólicamente difícil de hacer en el software.

 10
Author: Foredecker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-03 19:08:46

Hay algunas buenas respuestas aquí, aquí hay algunos punteros útiles:

Incluso si sus paquetes no están separados por tiempo, el byte de sincronización es una forma esencial de reducir el número de lugares desde los que necesita intentar construir un paquete. Sus dispositivos a menudo tendrán que lidiar con un montón de datos basura (es decir, el final de un paquete en vuelo cuando se encienden, o el resultado de una colisión de hardware). Sin un byte de sincronización, tendrá que intentar hacer un paquete con cada byte que reciba. Sincronización byte significa que solo 1/255 bytes de ruido aleatorio podrían ser el primer byte de su paquete. También ES FANTÁSTICO cuando quieres husmear en tu protocolo.

Tener una dirección en sus paquetes o incluso un poco diciendo maestro / esclavo o pc / dispositivo es útil cuando mira los paquetes a través de una herramienta snoop de algún tipo u otro. Puede hacer esto al tener un byte de sincronización diferente para el PC que para el DISPOSITIVO. Además, esto significará que un dispositivo no responderá a su propio eco.

Usted puede que desee buscar en la corrección de errores (como Hamming ). Empaqueta 8 bits de datos en un byte protegido de 12 bits. Cualquiera de esos 12 bits se puede voltear en ruta y recuperar los 8 bits originales. Útil para el almacenamiento de datos (utilizado en CD) o donde el dispositivo no puede volver a enviar fácilmente (enlaces por satélite, rf unidireccional).

Los números de paquetes hacen la vida más fácil. Un paquete enviado lleva un número, las respuestas llevan el mismo número y una bandera que dice "respuesta". Esto significa que los paquetes que nunca llegado (sync dañado decir) son fácilmente detectados por el remitente y en modo full-duplex con un enlace lento, se pueden enviar dos comandos antes de que se reciba la primera respuesta. Esto también facilita el análisis del protocolo (un tercero puede entender qué paquetes se recibieron sin conocer el protocolo subyacente)

Tener un solo maestro es una simplificación impresionante. Dicho esto, en un entorno full-duplex no importa mucho en absoluto. Basta con decir que siempre debe hacerlo a menos que está tratando de ahorrar energía o está haciendo algo impulsado por eventos en el extremo del dispositivo (estado de entrada cambiado, muestra lista).

 8
Author: Tom Leys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:05

Mi sugerencia es modbus. Es un protocolo estándar eficiente y fácil para la comunicación con dispositivos que tienen sensores y parámetros (por ejemplo, un PLC). Puede obtener las especificaciones en http://www.modbus.org . Ha existido desde 1979 y está ganando popularidad, no tendrá problemas para encontrar ejemplos y bibliotecas.

 5
Author: Martin Liesén,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-04 21:51:06

Leí esta pregunta hace unos meses, teniendo exactamente el mismo problema, y realmente no encontré nada lo suficientemente eficiente para un pequeño micro de 8 bits con pequeñas cantidades de RAM. Así que inspirado por CAN y LIN construí algo para hacer el trabajo. Lo llamé MIN (Microcontrolador Interconnect Network) y lo he subido a GitHub aquí:

Https://github.com/min-protocol/min

Hay dos implementaciones allí: una en C embebida, otra en Python para un PC. Además de un poco de " hola mundo " programa de prueba donde el PC envía comandos y el firmware enciende un LED. Escribí en un blog sobre cómo poner esto en marcha y funcionando en una placa Arduino aquí:

Https://kentindell.wordpress.com/2015/02/18/micrcontroller-interconnect-network-min-version-1-0/

MIN es bastante simple. Arreglé la representación de la capa 0 (8 bits de datos, 1 bit de parada, sin paridad) pero dejé abierta la velocidad en baudios. Cada fotograma comienza con tres bytes 0xAA que en binario es 1010101010, un buen pulsetrain para hacer detección de velocidad de autobaud si un extremo quiere adaptarse dinámicamente al otro. Las tramas son 0-15 bytes de carga útil, con una suma de comprobación de Fletcher de 16 bits, así como un byte de control y un identificador de 8 bits (para decirle a la aplicación lo que contienen los datos de carga útil).

El protocolo utiliza relleno de caracteres para que 0xAA 0xAA 0xAA siempre indique el inicio del fotograma. Esto significa que si un dispositivo sale de reset siempre se sincroniza con el inicio del siguiente fotograma (un objetivo de diseño para MIN era nunca dejar pasar un marco incompleto o incorrecto). Esto también significa que no hay necesidad de tener restricciones de tiempo específicas entre bytes y entre fotogramas. Los detalles completos del protocolo están en la wiki de GitHub repo.

Hay espacio para futuras mejoras con MIN. He dejado algunos ganchos allí para el paso de mensajes de bloque (4 bits del byte de control están reservados) y para la negociación de alto nivel de capacidades (identificador 0xFF está reservado) por lo que hay un montón de margen para agregar soporte para comúnmente requerido funcionalidad.

 5
Author: Ken Tindell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-18 16:51:00

Aquí hay un protocolo alternativo:

u8  Sync          // A constant value which always marks the start of a packet
u16 Length        // Number of bytes in payload
u8  Data[Length]  // The payload
u16 Crc           // CRC

Use RS232/UART, ya que el PC (puerto serie) y el procesador (UART) ya pueden manejar eso con un mínimo esfuerzo (solo necesita un chip MAX232 o similar para hacer el cambio de nivel).

Y usando RS232/UART, no tiene que preocuparse por maestro/esclavo si no es relevante. El control de flujo está disponible si es necesario.

Software para PC sugerido: escriba el suyo propio, o Docklight para un monitoreo y control simples (la versión de evaluación es gratuita).

Para una mayor comprobación de errores, lo más simple es la comprobación de paridad, o si necesita algo más poderoso, tal vez codificación convolucional.

En cualquier caso, hagas lo que hagas: ¡hazlo simple!

EDITAR: Usar RS232 con un PC es incluso más fácil de lo que solía ser, ya que ahora puede obtener convertidores USB a RS232/TTL. Un extremo va a la toma USB de su PC y aparece como un puerto serie normal; el otro sale a 5 V o 3.3 V señales que se pueden conectar directamente a su procesador, sin necesidad de cambiar de nivel.

Hemos utilizado TTL-232R-3V3 del chip FDTI, que funciona perfectamente para este tipo de aplicaciones.

 3
Author: Steve Melnikoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-14 17:03:40

Mi única sugerencia es que si necesita resistente al ruido, es posible que desee usar RS-422/485 full-duplex. Puede usar un IC similar a this en el lado AVR, luego un convertidor RS-232->RS-422 en el lado PC como el 485PTBR aquí . Si puedes encontrar o hacer un cable blindado (dos pares blindados retorcidos), entonces tendrás aún más protección. Y todo esto es invisible para el micro y PC - sin cambios de software.

Haga lo que haga asegúrese de que está utilizando un dúplex completo asegúrese de que las líneas de lectura/escritura habilitadas se afirman en el IC.

 2
Author: Stephen Friederichs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-06 02:35:12

Puedes echar un vistazo a Telemetry y su implementación de escritorio asociada en python Pytelemetry

Características principales

Es un protocolo basado en PubSub, pero a diferencia de MQTT es un protocolo punto a punto, no broker.

Como cualquier protocolo pubsub, puede publicar desde un extremo en un topic y ser notificado en el otro extremo sobre ese tema.

En el lado embebido, publicar en un tema es tan simple como :

publish("someTopic","someMessage")

Para los números:

publish_f32("foo",1.23e-4)
publish_u32("bar",56789)

Esta forma de enviar variables puede parecer limitada, pero el siguiente hito pretende agregar un significado adicional al análisis del tema haciendo cosas como esta :{[28]]}

// Add an indexing meaning to the topic
publish("foo:1",45) // foo with index = 1
publish("foo:2",56) // foo with index = 2

// Add a grouping meaning to the topic
publish("bar/foo",67) // foo is under group 'bar'

// Combine
publish("bar/foo:45",54)

Esto es bueno si necesita enviar matrices, estructuras de datos complejas, etc.

Además, el patrón PubSub es excelente debido a su flexibilidad. Puede crear aplicaciones maestro / esclavo, dispositivo a dispositivo, etc.

Biblioteca CVersión GitHub

El C la biblioteca es muy simple de agregar en cualquier dispositivo nuevo, siempre y cuando tenga una biblioteca UART decente en ella.

Solo tienes que instanciar una estructura de datos llamada TM_transport (definida por Telemetry), y asignar los 4 punteros de funciónread readable write writeable.

// your device's uart library function signatures (usually you already have them)
int32_t read(void * buf, uint32_t sizeToRead);
int32_t readable();
int32_t write(void * buf, uint32_t sizeToWrite);
int32_t writeable();

Para usar Telemetría, solo tiene que agregar el siguiente código

// At the beginning of main function, this is the ONLY code you have to add to support a new device with telemetry
TM_transport transport;
transport.read = read;
transport.write = write;
transport.readable = readable;
transport.writeable = writeable;

// Init telemetry with the transport structure
init_telemetry(&transport);  

// and you're good to start publishing
publish_i32("foobar",...

Biblioteca de PythonVersión PyPI

En el lado del escritorio, está el módulo pytelemetry que implementa el protocolo.

Si conozca python, el siguiente código se conecta a un puerto serie, publica una vez en el tema foo, imprime todos los temas recibidos durante 3 segundos y luego termina.

import runner
import pytelemetry.pytelemetry as tm
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = tm.pytelemetry(transport)
app = runner.Runner(transport,telemetry)

def printer(topic, data):
    print(topic," : ", data)

options = dict()
options['port'] = "COM20"
options['baudrate'] = 9600

app.connect(options)

telemetry.subscribe(None, printer)
telemetry.publish('bar',1354,'int32')
time.sleep(3)

app.terminate()

Si no conoce python, puede usar la interfaz de línea de comandos

Pitelemetría CLI Versión PyPI

La línea de comandos se puede iniciar con

pytlm

Entonces usted puede connect, ls(lista) temas recibidos, print datos recibidos sobre un tema, pub (publicar) sobre un tema, o abrir un plot sobre un tema a mostrar los datos recibidos en tiempo real

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

 2
Author: Overdrivr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-10 08:07:26

Con respecto a las comprobaciones de paridad (como ha surgido algunas veces aquí):

En su mayoría son inútiles. Si usted está preocupado de que un solo bit puede ser cambiado por error, entonces es muy probable que un segundo bit también puede cambiar y obtendrá un falso positivo de la comprobación de paridad.

Use algo ligero como CRC16 con una tabla de búsqueda - se puede calcular a medida que se recibe cada byte y es básicamente solo un XOR. La sugerencia de Steve Melnikoff es genial para micros pequeños.

Lo haría también sugiera transmitir datos legibles por humanos, en lugar de binarios sin procesar (si el rendimiento no es su primera prioridad). Hará que la depuración y los archivos de registro sean mucho más agradables.

 1
Author: Peter Gibson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-14 12:23:50

No especifica exactamente cómo se comporta el microcontrolador, pero ¿todo lo transmitido desde el micro será una respuesta directa a un comando del PC? Si lo hace, entonces parece que puede usar un protocolo maestro/esclavo de algún tipo (esta suele ser la solución más simple). Si ambas partes pueden iniciar la comunicación, necesita un protocolo de capa de enlace de datos más general. HDLC es un protocolo clásico para esto. Aunque el protocolo completo probablemente sea un exceso para sus necesidades, podría por ejemplo, al menos use el mismo formato de marco. También puede echar un vistazo a PPP para ver si hay algo partes útiles.

 0
Author: hlovdal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-02 22:59:40

Tal vez esta pregunta puede ser completamente estúpida, pero ¿alguien ha considerado el uso de uno de los protocolos X/Y/Z MODEM?

El principal beneficio de usar uno de los protocolos anteriores es la gran disponibilidad de implementaciones listas para usar en varios entornos de programación.

 0
Author: Chris Ciesielski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-07 13:25:48

SLIP y UDP. Seriamente.

Todos los PC y dispositivos similares lo hablan.

Hay un buen libro y ejemplos de TCP Lean

Jeremy Bentham ha conseguido a escondidas una FOTO haciendo trabajo TCP/IP. Un AVR es tan bueno como una FOTO ¿verdad ?

Recomendaría UDP en su lugar, es bastante fácil.

 -1
Author: Tim Williscroft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-01 03:46:52