sábado, 11 de mayo de 2013

Programación Arduino Parte 1

    En las distintas entradas he ido desarrollando el código para el funcionamiento de los bloques principales. Ahora hay que juntarlos todos. Por supuesto hay que tener en cuenta que el desarrollo del código de los distintos bloques se ha hecho pensando que tendrá que ir unido al resto.

    Cuando empecé a estudiar un poco sobre cuadricópteros y la programación en Arduino una característica que tuve claro que quería para mi proyecto fue que el código funcionara sin interrupciones. Hay aplicaciones para las que las interrupciones no suponen ningún problema. Sin embargo en un cuadricóptero lo considero un aspecto fundamental. Las interrupciones producen pequeños fallos en el timing que generan por ejemplo inexactitudes en las medidas de los canales de la emisora RC o saltos en los pulsos enviados a los ESC (y servos si los hay). Estos efectos tienen como consecuencia una mala estabilización del cuadricóptero.

    Quiero aclarar la problemática de las interrupciones. Lo que no podemos hacer es, por ejemplo, utilizar una librería ya confeccionada que utiliza interrupciones. Generalmente estas librerías no podemos activar y desactivar sus interrupciones según nos interese así que si la utilizamos sus interrupciones se producirán en cualquier momento dentro de nuestro código. En algunas partes no tendrá importancia pero en otras nos producirá grandes errores en los timing produciendo los fallos antes nombrados.
    Sin embargo sí que podríamos utilizar interrupciones si nos interesara si somos nosotros los que las controlamos, activándolas en el momento en que nos interese y desactivándolas una vez terminado ese proceso para que no intercepten el resto del código. Por ejemplo se puede desarrollar el código para el control de los motores (los disparos a los variadores) mediante interrupciones. Estas interrupciones estarán activadas justo el tiempo de duración de esta pequeña parte de código (entre 1 ms y 2,1 ms) con lo que no habrá problemas. Por el momento lo cierto es que yo no me he puesto más a fondo con las interrupciones y mis códigos los he desarrollado sin ellas pero probablemente se gane en precisión utilizándolas de esta manera. Este es un aspecto mejorable que tal vez aborde en el futuro.

    Según lo explicado, que el código no tenga interrupciones básicamente supone:

    - No poder usar la librería Servo.h para el control de los ESC (ni de servos). Esta librería funciona mediante interrupciones.
    - No poder utilizarlas para tomar las lecturas de los canales de la emisora RC (tal vez podrían utilizarse si las podemos desactivar pero no estoy seguro si conseguiríamos alguna mejora).
    - Secuencia del código totalmente lineal con estricto estudio de los tiempos de ejecución para que no se desborde el tiempo de ciclo.

    El tiempo de ejecución del código en el AHRS 9DOF Razor IMU con el envío de los datos está alrededor de los 15 ms, inferior a los 20 ms aproximados (medido en 19,58 ms) del ciclo de la emisora que marca el ciclo del programa. Por tanto en cada ciclo dispondremos de una lectura del IMU. La secuencia del programa será:

1 - Lectura de los canales de la emisora. Si queremos leer los 8 canales esto nos consume un tiempo entre 8,5 ms y 15 ms. Durante la lectura de la emisora tenemos limitado el uso del micro para otras tareas (sólo los intervalos sueltos de 1 ms anotados en el código). Por tanto nos quedan 19,58 ms del ciclo de la emisora menos los 15 ms del tiempo de ejecución, unos 4,5 ms para ejecutar el resto de tareas.

2 - Lectura de los datos del AHRS 9DOF Razor IMU enviados por puerto serie. Aunque el envío tarda unos 3 ms a la velocidad de 57600 baudios, Arduino tiene un buffer donde se van almacenando y la lectura cuando toda la trama de 17 bytes ha llegado es de sólo 0,13 ms.

3 - Ejecución de los PID para la estabilización que darán los valores necesarios para los cuatro motores. En este momento este apartado está sin terminar de desarrollar. No tengo datos de tiempos de ejecución pero la previsión es que no sean críticos.

4 - Control de los motores. Secuencia de código ya desarrollada que envía los disparos a los los ESC de los cuatro motores. El tiempo de ejecución está entre 1 ms y 2,1 ms.

5 - Otras tareas que se irán implementando con tiempos de ejecución previsibles muy cortos. Por ejemplo lectura de las tensiones de las celdas de la batería para prevenir que se descarguen en exceso.

    Con estos datos tenemos que el micro está ocupado 15 + 0,13 + 2,1 = 17,23 ms lo que nos deja 19,58 - 17,23 = 2,35 ms para la ejecución de los PID y otras tareas menores.

    En este punto he empezado a hacer pruebas con un código que engloba los puntos 1, 2, 4 y 5 y he tropezado con un problema. La velocidad de los motores no es estable, se acelera y frena un poco a intervalos regulares de algo menos de 1 segundo. Tras mucho investigar estoy llegando a una conclusión: la lectura del puerto serie produce interrupciones. Como el ciclo del envío de datos del AHRS 9DOF Razor IMU es distinto al del código en Arduino la recepción de datos se va produciendo en distintos momentos del código. Según cuándo se produzca nos interferirá en distintas partes del programa como ahora estamos viendo que lo hace en los pulsos a los motores.

    ¿Y cuál es la solución a este problema? Se me ocurre sincronizar la comunicación entre AHRS 9DOF Razor IMU y Arduino. Es decir, Arduino tiene que solicitar a AHRS 9DOF Razor IMU los datos y en ese momento es cuando tiene que enviarlos. Así tenemos que tener previsto que en ese instante de recepción de datos Arduino no esté haciendo otras tareas para que no interfiera con las mismas. Tenemos dos formas de hacerlo. Una es que AHRS 9DOF Razor IMU ejecute todo su código y envíe los datos ante la petición de Arduino. La otra es que AHRS 9DOF Razor IMU esté siempre ejecutando su código y sólo envíe los datos ante la petición de Arduino. Tendré que probar las dos opciones y ver los pros y contras de cada una. Por el momento se produce un gran inconveniente y es que al usar la transmisión de Arduino hacia el AHRS 9DOF Razor IMU ya no podemos usarlo para monitorizar resultados en el Monitor Serial del ordenador. Toca hacer pruebas y encontrar soluciones.

Tenéis una nueva entrada en Programación Arduino Parte 2.