Mando RC y receptor. Programación en Arduino (sketch)

Emisora RC y programación en Arduino

Índice:

  1. Conceptos generales sobre drones.
  2. Material necesario y montaje de los componentes hardware.
  3. → Mando RC y receptor. Programación en Arduino (código).
  4. MPU6050 y su programación en Arduino (código).
  5. Batería LiPo (código).
  6. Control de estabilidad y PID.
  7. Motores, ESC y su programación en Arduino (código).
  8. Calibración de hélices y motores (código)
  9. Software completo y esquema detallado (código).
  10. Probando el Software completo antes de volar.
  11. Como leer variables de Arduino en Matlab (código).
  12. Los mejores drones de 2018 | Comparativa y guía de compra.

Mando radio control (RC)

Una de las maneras más fáciles y baratas de comunicarse con nuestro futuro drone es utilizar un mando RC y un receptor. Son fáciles de utilizar y se pueden conseguir por 30€ en Ebay en sus versiones más básicas (4 canales). Como todo en la electrónica, el mundo de los mandos RC es muy amplio pero para nuestro primer drone es suficiente. Dispondremos de un canal para controlar el throttle, otro para el pitch, uno más para el roll y el último para el yaw. He decidido asociar los sticks con las siguientes funciones o movimientos del drone. Recomiendo seguir el mismo criterio ya que es el mas extendido por ser el mas intuitivo a la hora de controlar el drone. Aquí una foto de mi mando:

Comprar mando RC en Amazon AHORA

 

El funcionamiento de un mando RC es muy simple. El movimiento de los sticks del mando es procesado y enviado por ondas de radio a nuestro receptor, que irá situado en el frame del drone. Esta información se compone de señales PWM de 50Hz que varían en función de la posición de cada stick. Si accionamos al mínimo alguna de las palanca del mando, el ancho de pulso que recibamos en el receptor será de 1ms, y si la accionamos al máximo, el ancho del pulso será de 2ms (estos valores pueden ser diferentes en cada mando). Si dejamos la palanca en el punto central obtendremos pulsos de 1.5ms aproximadamente, siempre manteniendo una frecuencia de 50Hz. Esta información será enviada a la placa Arduino y se utilizara como referencia para mover el drone.pulso mando RC

Como vemos en la imagen anterior, el mando no da exactamente pulsos de 1ms con el stick al mínimo, ni pulsos de exactamente 2ms subiéndolo a máximo. Estos pequeños errores de precisión del mando los corregiremos mas adelante al final de esta entrada.

Conexionado mando-Arduino

El receptor ira situado en el frame y es necesario alimentarlo y cablearlo de forma adecuada. Alimentaremos el receptor a +5V en cualquiera de los canales centrales, por ejemplo con la tensión de nuestra placa Arduino. Si hemos configurado bien la unión mando-receptor, al encender el mando debería encenderse un led rojo (en mi caso) que indica que funciona correctamente.

El conexionado necesario para ejecutar el código que os dejo al final de este artículo se muestra a continuación. Simplemente hay que alimentar el receptor en cualquiera de los canales centrales y cablear las cuatro señales a las correspondientes entrada digitales, en mi caso:

  • Pitch ⇒ CH2 ⇒ IN 12
  • Throttle ⇒ CH3 ⇒ IN 8
  • Roll ⇒ CH1 ⇒ IN 9
  • Yaw ⇒ CH4 ⇒ IN 7

Antes de continuar me gustaría analizar un poco más en detalle el funcionamiento de mi receptor y la forma en la que genera los pulsos. La siguiente imagen muestra una captura sacada con osciloscopio donde visualizo las señales de pitch, roll y yaw (no he metido el canal de throttle por que mi osciloscopio solo tiene 3 canales). De esta imagen he sacado los siguientes datos:

  • El receptor genera pulsos de 3.3V.
  • Los pulsos se generan de forma secuencial, hasta que no termina un pulso no empieza el siguiente. Nunca habrá más de un canal en estado HIGH cada vez.

Código Arduino (Sketch)

La forma más sencilla de leer este tipo de pulsos es utilizar la función PulseIn de Arduino. Lamentablemente esta función tan fácil de utilizar no sirve para esta aplicación (aunque sí para muchas otras). Pero, ¿Por qué? Como todos a estas alturas sabemos, el código de Arduino se ejecuta de manera secuencial, línea tras línea y de arriba abajo. Arduino no ejecuta una línea si no ha terminado de ejecutar la anterior. Cuando llegue a la línea PulseIn(), Arduino se quedará esperando en ella el tiempo que haga falta hasta recibir un pulso y medirlo. Como sabemos, el mando solo nos enviará un pulso por canal cada 20ms, por lo que esta función PulseIn estará esperando a recibir el pulso (y sin hacer nada mas) durante 20ms. Teniendo en cuenta que contamos con 4 canales, la demora se puede prolongar hasta 80ms. Este intervalo de tiempo que a priori puede parecer muy corto, para nuestros drone es toda una eternidad y hará que nunca sea estable (esto lo veremos en otro apartado más adelante).

Localización del receptor en el frame

¿Cómo podemos leer las señales recibidas desde el mando de una forma eficiente? Utilizando interrupciones hardware, una por canal. El funcionamiento de una interrupción hardware es muy simple: ante un flanco positivo (cambio de estado de LOW a HIGH) o negativo (cambio de estado de HIGH a LOW) en alguna de las interrupciones (pins), Arduino detendrá la ejecución normal del programa y ejecutara la parte del código que hayamos asociado a esa interrupción en concreto. Una vez ejecutado esta parte de código, Arduino regresará al programa principal y seguirá ejecutándolo donde lo dejó. A continuación os explicaré como leer los canales de vuestro mando RC de forma que la lectura solo lleve unos poco microsegundos (100 veces menos que con la función PulseIn). Para poder poner esto en marcha necesitamos 4 interrupciones hardware, una por cada canal que queremos leer. La paca Arduino Nano cuenta únicamente con dos interrupciones hardware, pero existen librerías como EnableInterrupt.h que permiten convertir casi cualquier pin analógico o digital en interrupción. Esta librería es extremadamente simple de usar como veremos mas adelante.

Al final de este artículo podréis encontrar el sketch completo que utilizo para medir los pulsos con interrupciones hardware. El sketch es muy simple como veréis a continuación. Cuando se detecta un pulso (flanco positivo o negativo) en alguna de las cuatro interrupciones, se ejecuta la parte del código asociado a esa interrupción. El primer paso es identificar si hemos detectado un flanco positivo o uno negativo, para lo que bastará con leer el estado de la propia entrada digital. Si está en estado HIGH significará que hemos detectado un flanco positivo (comienzo del pulso) y si está en LOW, uno negativo (fin del pulso). Cuando se detecta un flanco positivo se registra el tiempo (el instante) en el que se ha dado la interrupción, para lo que utilizaremos la función micros() y lo guardamos en una variable. Una vez hecho esto Arduino sale de la interrupción y sigue ejecutando el código principal. Un tiempo después se detecta un flanco negativo (cambio de estado de HIGH a LOW), por lo que se vuelve a ejecutar la interrupción. Volvemos a leer el estado de la entrada que esta vez estará en estado LOW. Finalmente detenemos el correspondiente contador y calculamos el tiempo que ha transcurrido desde que lo hemos activado, que será el tiempo que ha durado el pulso. A continuación os dejo el código completo para que podáis leer los canales de vuestro mando:

La diferencia de mi sketch con la función PulseIn es que mi programa no está esperando (y sin hacer nada mas) hasta recibir un pulso para seguir ejecutando el loop principal. El programa solo deja de ejecutarse mediante interrupciones para poner en marcha un contador y después detenerlo. Todo el tiempo restante continúa funcionando y ejecutando el control principal. Gracias a esto conseguimos leer los 4 canales del mando RC prácticamente sin consumir nada de tiempo. Os dejo el código completo para que podáis leer los canales de vuestro mando. El conexionado necesario es el mismo que hemos visto mas arriba:

  • Roll ⇒ IN 9
  • Pitch ⇒ IN 12
  • Yaw ⇒ IN 7
  • Throttle ⇒ IN 8

Para poder seguir es importante que hayas conseguido poner en marcha esta parte de forma adecuada. Os tenéis que asegurar que cada canal del mando corresponde con los movimientos del drone que hemos asignado. Moved la palanca asociada al Pitch y comprobad que es la variable PulsoPitch la que cambia y haced lo mismo con los demás canales. En caso de no estén bien asignados, podéis modificar el nombre de las variables (recomendado) o modificar el cableado, pero asegurad que moviendo el stick asociado al movimiento Pitch es la variable PulsoPitch la que cambia y no ninguna otra.

Los canales de mi mando esta configurados de la siguiente manera. Comprobad como están configurados los vuestros con el sketch de arriba. En caso de que alguno este invertido respecto a lo que pongo a continuación, habrá que ajustarlo mas adelante. En mi caso, el canal de throttle está invertido de fábrica (es cuestión de como esté diseñado el mando que compremos), ya que leo 2000us con el stick al mínimo y 1000us con el stick al máximo:

  • Stick de Pitch arriba: 1000us aprox
  • Stick de Pitch abajo: 2000us aprox
  • Stick de Roll derecha: 2000us aprox
  • Stick de Roll izquierda: 1000us aprox
  • Stick de Yaw derecha: 1000us aprox
  • Stick de Yaw izquierda: 2000us aprox
  • Stick throttle arriba: 1000us aprox
  • Stick throttle abajo: 2000us aprox

Como hemos visto mas arriba, el mando no da exactamente pulsos de 1ms con el stick al mínimo, ni pulsos de exactamente 2ms subiéndolo a máximo. Estos pequeños errores de precisión del mando han de ser corregidos, especialmente para el canal destinado al throttle. Para ello utilizaremos en siguiente código, que simplemente lee los cuatro canales y visualiza los valores máximo y mínimos mientras movemos los stick de un lado a otro. Anotaremos la duración de los cuatro pulsos en los extremos de cada canal, moviendo los cuatro stick del mando arriba/abajo e izquierda/derecha hasta conseguir los valores máximos y mínimos de pulso.

Estos valores después serán utilizados para escalar las lecturas del mando a nuestras necesidades para utilizarlos como consigna (referencia) para los controladores PID.

También podéis descargar el archivo en el siguiente enlace, archivos ‘mandoCompletoINT‘ y ‘MaxMinArduino‘.

Ir al archivo

Estos números después se utilizarán para escalar el throttle. Para el Pitch, Roll y Yaw asumo que el mando es ideal y los pulsos varían exactamente entre 1ms y 2ms, ya que son menos críticos. Es importante que en el código que os dejo mas adelante para poner en marcha y controlar los motores modifiquéis los siguientes parámetros en función de lo que haya arrojado el software de arriba:

Ahora que ya sabemos cómo leer pulsos con nuestra placa Arduino, ¿qué hacemos con esta señal? ¿Cómo le decimos a nuestro drone que avance o que gire en una dirección determinada mediante un pulso en microsegundos?

Como ya sabemos, para poder girar o avanzar, el drone tiene que ser capaz de inclinarse manteniéndose estable en el aire. Para ello, tenemos que indicar al drone cuantos grados queremos que se incline en una dirección determinada para poder desplazarse hacia donde se le ha indicado.  Por lo tanto, habrá que usar estas señales del mando RC como referencia para inclinar el drone en un eje o en otro. Al fin y al cabo, esa es la función final del mando: indicar al drone cuantos grados queremos que se incline en un eje determinado para poder desplazarnos en una dirección concreta. Para ello, es necesario ‘procesar’ la información en microsegundos que nos llegar del receptor y convertirla a una señal proporcional en grado de inclinación.

Porgamos como ejemplo el stick asociado al eje Pitch. Tenemos que procesar la señal que recibimos del receptor (variable PulsoPitch), de forma que con el stick es su posición central (sin moverlo ni arriba ni abajo), el drone reciba una consigna de 0º de inclinación, es decir, que se mantenga estable y sin inclinarse.

PulsoPitch = 1500us (stick en posición central) ⇒ 0º de inclinación

Que, si por el contrario movemos el stick hasta arriba, el drone reciba la orden de inclinarse unos -30º en ese eje para desplazarse en esa dirección.

PulsoPitch = 1000us (stick arriba)  ⇒ -30º de inclinación

Y que, si movemos el stick hacia abajo, el drone reciba la orden de inclinarse unos +30º en ese eje para desplazarse en dirección contraria.

PulsoPitch = 2000us (stick abajo)  ⇒ +30º de inclinación

Le estamos indicando al drone que se incline en el eje Pitch en un sentido o en otro (-30º/+30º) en función de la posición del stick del mando RC.

Para procesar las señales obtenidas del mando y transformarlas en consigna de inclinación, utilizaremos las siguientes ecuaciones. Hacen exactamente lo mismo que la función map() de Arduino. El simplemente la ecuación de una recta que pasa por dos puntos:

Os dejo el software completo con las ecuaciones de procesamiento ya metidas. Podéis también descargarlo en el siguiente enlace:

Ir al archivo

Lo mas importante es asegurar que una vez procesadas las señales, el canal de throttle no ha quedado invertido. Es decir, con el stick al mínimo tenemos que obtener una salida de 1000us aproximadamente, y con el stick al máximo una salida de 2000us aproximadamente. Si tenéis el canal invertido, corregirlo cambiando de orden los parámetros de entrada. De esto:

A esto:

Comprobar también los demás canales, y en caso de tener alguno invertido, seguid el mismo procedimiento que con el canal throttle hasta ajustarlos como se muestra a continuación:

  • Moviendo stick de Pitch hacia arriba, wPitchConsigna = -30º aprox.
  • Moviendo stick de Pitch hacia abajo, wPitchConsigna = +30º aprox.
  • Moviendo stick de Roll hacia la derecha, wRollConsigna = +30º aprox.
  • Moviendo stick de Roll hacia la izquierda, wRollConsigna = -30º aprox.
  • Moviendo stick de Yaw hacia la derecha, wYawConsigna = +30º aprox.
  • Moviendo stick de Yaw hacia la izquierda, wYawConsigna = -30º aprox.

Las implicaciones de no hacer esta modificación en los canales Pitch, Roll y Yaw no son tan graves, simplemente, cuando ordenáramos al drone ‘avanzar’, este retrocedería. Nada grave, pero conviene corregirlo.

Acordaos de cambiarlo también cuando descargues el software principal en la entrada número 9.


Continuar con la siguiente entrada:

  1. Conceptos generales sobre drones.
  2. Material necesario y montaje de los componentes hardware.
  3. Mando RC y receptor. Programación en Arduino (código).
  4. → MPU6050 y su programación en Arduino (código).
  5. Batería LiPo (código).
  6. Control de estabilidad y PID.
  7. Motores, ESC y su programación en Arduino (código).
  8. Calibración de hélices y motores (código).
  9. Software completo y esquema detallado (código).
  10. Probando el Software completo antes de volar.
  11. Como leer variables de Arduino en Matlab (código).
  12. Los mejores drones de 2018 | Comparativa y guía de compra.

 

Mando RC y receptor. Programación en Arduino (sketch)
5 (100%) 3 votes

Comentar

avatar
  Subscribe  
Notify of