martes, 28 de agosto de 2012

Control motores Parte 2

    Como continuación a Control motores Parte 1 escribo esta entrada en la que explico el cambio en la concepción del código que permite tener una gran precisión en los tiempos, sumamente importantes para que las señales enviadas a los variadores produzcan una regulación suave y precisa. Es tan grande el cambio en la concepción del programa y su precisión que paso a la versión 2.0.

    El código está preparado para el control de los 4 motores si bien su estructura permite de forma fácil ampliarlo para el control de más motores o servos.

    Para no aburrir con todo el largo proceso de prueba y error de las distintas formas que se me ocurría y que finalmente no funcionaban, paso a describir el funcionamiento de la opción adoptada.
    Hay que tener en cuenta que donde necesitamos gran precisión es en el tiempo que están activadas (en HIGH) las salidas. El tiempo de ciclo de 20 ms no tiene gran importancia que tenga pequeñas variaciones, de hecho las hay de una emisora a otra (en mi emisora Turnigy TGY 9X tengo calculado unos 19 ms) y si movemos varias palancas de la emisora a la vez el tiempo de ciclo de cada canal puede variar en algún milisegundo. Es más, podéis hacer la prueba en el código a cambiar el tiempo de ciclo en

if (micros() - TiempoControlCiclo >= 20000)

y en lugar de los 20000 µs poner valores mayores o inferiores. Si lo probáis con un servo con tiempos inferiores (por ejemplo 5000) veréis que al intentar mover la palanca del servo su respuesta es más limpia y no tiembla tanto ya que está actualizando su posición más veces por segundo (el cuádruple para un tiempo de 5000). En cambio si hacemos la prueba con valores más grandes, por ejemplo 50000, comprobamos que podemos mover más fácilmente la palanca de su posición ya que el servo está actualizándose menos veces por segundo, en nuestro ejemplo 2,5 veces más lento.

    Para conseguir la mayor precisión en tiempo en el HIGH tenemos que utilizar la instrucción delaymicroseconds() que tiene una precisión de 1 µs. Si utilizamos la función micros() su precisión es de 4 µs. La idea es ordenar los pulsos de menor a mayor, activar todas las salidas e ir desactivándolas con los delay. El tema es que esas instrucciones llevan un tiempo ejecutarlas además de que no se puede utilizar el delay si queremos que sea de 0 segundos. La solución es decalar los pulsos, es la constante "Retardo" que establezco en 10 µs. Así siempre podemos utilizar la instrucción delaymicroseconds() cuyo valor para cada salida se calcula según el pulso, el retardo y el tiempo de ejecución de las instrucciones que ha sido calculado empíricamente. Los cálculos de ordenar los pulsos y recalcular los tiempos de delay se calculan antes de establecer los HIGH de modo que conseguimos tener unos tiempos muy precisos para los pulsos. Además todo el código es ejecutado en un tiempo reducido, unos 32 µs los primeros cálculos más el decalaje (para 4 motores son 30 µs) más el tiempo del mayor pulso que en el caso de motores es de unos 2000 µs y para servos 2500 µs.

    Aquí tenéis el código con algún comentario que espero sea suficiente para entenderlo. Mi idea a medio plazo es sacar otra versión preparada para manejar algunos servos además de los 4 motores.

Archivo para Arduino 1.0.1: Control motores v2.0