lunes, 9 de marzo de 2020

Actualización #05

Implementando la librería



Ahora que tengo pruebas de la viabilidad del proyecto, es el momento de comenzar a escribir una librería que simplifique el trabajo.

Abstracción del tipo de serial

La librería debería funcionar igual independientemente de si los datos se reciben por un HardwareSerial o por un SoftwareSerial. Su superclase común más cercana es la clase Stream.
Stream tiene los métodos de lectura, pero hereda de Print, que tiene los métodos de escritura.
Como el compilador para AVR de C++ no tiene dynamic_cast, incluiré un booleano para identificar qué tipo de serial se utiliza y hacer así un casting estático cuando sea necesario.
De momento solo es necesario hacer el casting en la inicialización, porque si Stream ni sus superclases tiene el método begin y de hecho es diferente para los dos tipos de serial. Por lo demás se comportan idénticamente.

Detección de tramas

Las tramas comienzan con un byte 0x00, acaban en un byte 0x00 y tienen 25 bytes. También sabemos que los cuatro últimos bits del penúltimo byte son siempre 0, pero esos 4 bits están reservados y podrían cambiar si fuera necesario, no se tendrán en cuenta.

El código que controla la detección de tramas tiene un contador para saber en qué byte está. Guarda en un buffer temporal la trama cruda. El contador aumenta cuando un byte se transfiere con éxito. Si hay un error de paridad SoftwareSerial ignora todo el byte es transparente para la librería SBUS. Si estamos en el byte 0 y el valor no es 0x0F el contador no aumenta, asume que  hay un descuadre y continua descartando bytes hasta encontrar el inicio de una trama. Si estamos en el byte 24 pero el valor no es 0x00, algún byte se ha perdido, en lugar de actualizar los canales y reiniciar el contador, solo reinicia el contador descartando la trama completa.

Alternativamente se podría asumir que la trama empieza con dos bytes 0x00 y 0x0F y para aceptar una trama se debe empezar con la siguiente para verificar que la trama acaba sin que se pierdan bytes. Pero esta implementación solo resulta más eficiente en un caso muy específico y sería más costosa. Como ese fragmento de código se tiene que ejecutar muchas veces es mejor dejarlo como está.

Esta función se ha puesto a prueba a conciencia , de hecho la versión descrita aquí es la segunda iteración que he realizado. De momento no he logrado hacer fallar a esta nueva revisión.

División de canales

En una actualización anterior publiqué un código que realizaba la división y composición de los 16 canales de 11 bits en 22 bytes. Hacer funcionar la librería ha sido tan sencillo como copiar esos fragmentos de código en las funciones que descomponen y componen las tramas.

Siguiente paso

Dicho todo esto, la recepción de datos está completa. Me gustaría agregar funciones de utilidad para convertir tipos de datos fácilmente. pero eso puede esperar.
El próximo hito a conseguir es la transferencia de telemetría.

viernes, 6 de marzo de 2020

Actualización #04

Recibiendo datos del X8R y R9 por HardwareSerial


Objetivo

Establecer una comunicación por Hardware con el X8R y  R9 y obtener datos significativos.
Usando una placa MEGA 2560.

Resultado

Ante la imposibilidad de usar el módulo R9 por SoftwareSerial, me veo obligado a incorporar una opción en la librería para usar HardwareSerial.

Para conectar el módulo mediante HardwareSerial hay que invertir la señal antes de introducirla a la placa porque la librería de Arduino no permite configurar la lógica inversa como SoftwareSerial.
Comencé usando el circuito integrado séxtuple inversor 7004 de Texas Instrument. El tiempo de propagación es varios órdenes de magnitud inferior al periodo de la señal. Aún así los dos IC que he usado han acabado fallando. Al final he tenido que construir mi propio inversor con un transistor y dos resistencias.

El cable azul es la entrada y el amarillo la salida. La resistencia en horizontal es de 10K y la vertical de 1K. El transistor es un BJT NPN, concretamente he probado con un 2N3904.


Ahora he probado repetido las dos pruebas anteriores pero mediante HardwareSerial en lugar SoftwareSerial.

Finalmente ha funcionado. Logré recibir datos correctamente de los dos módulos.
La calidad ha mejorado. Claramente la velocidad de las placas es demasiado baja para realizar correctamente el timing y acaban fallando muchos bits, gracias al bit de paridad descarta algunos bytes erróneos. Pero si el bit error rate es lo suficientemente alto y aleatorio, un bit de paridad no impedirá recibir tramas con errores ocultos.
Tengo que especificar en la documentación que determinados módulos, como es el caso del R9, solo funcionan por HardwareSerial.

jueves, 5 de marzo de 2020

Actualización #03

Recibiendo datos del R9 por SoftwareSerial


Objetivo

Establecer una comunicación por software con el R9 y obtener datos significativos.
En una placa UNO y MEGA 2560.

Resultado

Habiendo tenido éxito en la prueba del R9, el procedimiento para hacer funcionar el R9 debería reducirse a conectarlo correctamente.

Esta vez no he logrado obtener datos significativos, los bytes son prácticamente aleatorios.
Todo indica a que el módulo R9 envía más tramas por segundo que el X8R, las suficientes para saturar la placa. MEGA tiene la misma velocidad de reloj que UNO, quizás en una placa más rápida funcione.

miércoles, 4 de marzo de 2020

Actualización #02

Recibiendo datos del X8R por SoftwareSerial


Objetivo

Establecer una comunicación por software con el X8R y obtener datos significativos.
Probado en una placa UNO y MEGA 2560.

Resultado

He realizado una modificación de la librería SoftwareSerial para que funcione con 8E2 en lugar de 8E1.  Antes de intentar la conexión con el módulo receptor, he probado a usar dos arduinos para ver cómo responden a 100000 baudios. Si se introducen pausas, funciona sin problemas. Pero cuando se usa la línea a plena capacidad la placa se satura y se vuelve inútil. Sabiendo esto, la viabilidad de SoftwareSerial dependerá de que el receptor tenga un tiempo entre tramas lo suficientemente largo.

Ahora sí, lo enlazo con el receptor. El Arduino se conecta a las señales SBUS OUT y SBUS IN por pines digitales usados como RX y TX respectivamente.
Para mostrar de forma más visible los datos, he escrito un pequeño sketch que muestra los bytes recibidos de 25 en 25. La trama comienza en un byte con el valor 15 y termina 25 bytes más a delante en 0.

El resultado ha sido todo un éxito, cuando el transmisor varía el primer canal se observa un cambio en el segundo byte y parte del siguiente como cabría esperar. Aunque ocurren problemas, cada cierto tiempo la posición del inicio de la trama retrocede, eso indica que se pierden bytes. Pese a esto, que es fácilmente corregible en la librería SBUS, el resultado es muy bueno.