Comunicación avanzada por puerto serie en Arduino


Llevamos una serie de entradas destinadas a hacer un uso avanzado del puerto serie en un procesador como Arduino. En esta entrada nos toca juntar todos estos puntos para hacer, por fin, una comunicación robusta entre dos dispositivos.

En resumen, queremos:

  • Enviar una estructura que contenga nuestro mensaje.
  • Que la comunicación tenga un timeOut para que no sea bloqueante si no hay mensaje que recibir.
  • Disponer de caracteres de control como delimitadores de trama para permitir una sincronización de la comunicación ante la pérdida de paquetes.
  • Disponer de una función de checksum para comprobar la integridad de los datos antes errores de la comunicación.
  • Enviar una señal de Acknowledge.

Si mezclamos todo esto ¿Cómo queda el código en el emisor?

Tenemos una enumeración que indica el estado de la comunicación. También tenemos una estructura DataMessage que contiene el mensaje que queremos enviar, y tenemos definidos los caracteres de control STX, ETC, ACK y NAK.

Cuando el emisor quiere iniciar una comunicación llama a la función SendMessage, que añade el delimitador inicial, envía la estructura como bytes, calcula y envía el Checksum, y manda el carácter de control delimitador final.

A continuación, espera la respuesta, con un timeout de 100ms. Si recibe ACK, ejecuta la acción okAccion(). Si no recibe respuesta, o recibe NAK, ejecuta la acción errorAction().

El código del receptor es similar aunque, como de costumbre, ligeramente más complejo. Tenemos también definida la estructura del mensaje, los códigos de control, y la enumeración del resultado de la comunicación.

El receptor emplea la función ProcessSerialData(), que a su vez llama a la función TryGetSerialData(). Esta función espera la llegada de un mensaje con timeout de 100ms.

Si recibe un mensaje, comprueba que este delimitado por los caracteres de control, recibe la estructura que contiene el mensaje, y comprueba el checksum recibido. Finalmente, devuelve el resultado del intento de comunicación.

Si el mensaje es correcto, la función ProcessSerialData ejecuta la acción okAction(). Si el mensaje es erróneo ejecuta errorAction(). En caso de que expire el timeout no se ejecuta acción alguna.

Con estos dos códigos, empezamos a tener una comunicación suficientemente robusta entre dos procesadores por puerto serie.

Librería ComCenter

¿Y si mejoramos este código y lo metemos en una librería para que sea más cómodo de usar? ¡Por supuesto que sí! En una próxima entrada veremos la librería ComCenter para C++ y C#, que realiza esta comunicación por puerto serie de forma fácil y con más funciones.

Si te ha gustado esta entrada y quieres leer más sobre Arduino puedes consultar la sección
tutoriales de Arduino

Previous Caracteres de control en el puerto serie en Arduino
Next Comprobar la integridad de datos en Arduino con checksum