Control de estabilidad y PID para drones

Los controladores PID junto con el control de estabilidad son el cerebro de nuestro drone. Mantendrán el drone estable en todo momento.

Í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.

Estrategias de control de vuelo para drones

Las estrategias de control más comunes utilizadas en el mundo de los drones son el modo acrobático y el modo estable. En esta entrada vamos a entender el funcionamiento de las dos estrategias.

volar drone modo estable arduino PID

Modo de control ‘Acrobático’

En este primer modo de control solo utilizaremos las lecturas de velocidad angular calculadas a partir de los datos obtenidos del sensor MPU6050. La velocidad la vamos a medir en ‘º/s’, es decir, cuantos grados rota cada eje por segundo. Si por ejemplo uno de nuestros ejes da una vuelta completa en un segundo, la velocidad será de 360º/s.

Vamos a empezar repasando unos conceptos básicos de funcionamiento. Si el eje pitch de nuestro drone rotara por cualquier razón, porque uno de los motores tiene más potencia, porque hay viento… el control tendrá que contrarrestar esta desviación actuando sobre los motores correspondientes. En este caso, habría que actuar sobre los motores de la izquierda acelerándolos, y sobre los motores de la derecha decelerándolos. De esta forma conseguiríamos contrarrestar el efecto de la perturbación que ha hecho que nuestro drone rotara en su eje pitch. Pero cuidado, en modo acrobático en drone no volverá a su posición inicial, simplemente compensaremos la rotación hasta detener el drone. Esto es debido a que únicamente estamos utilizando como referencia la velocidad de rotación de los ejes:

En modo acrobático simplemente contrarrestamos la rotación
En modo acrobático simplemente contrarrestamos la rotación

Ahora bien, ¿cuánta potencia y durante cuánto tiempo hay que acelerar cada motor para contrarrestar estas perturbaciones? En otras palabras, ¿Cómo hacemos que nuestro control sea capaz de mantener el drone estático en el aire de forma autónoma? Para esto tenemos los PID.

Empecemos por lo básico. Si representáramos el algoritmo de control de estabilidad mediante una conversación entre los diferentes componentes del drone, obtendríamos algo como esto:

  1. Humano (mediante el mando RC): Ey drone, quiero que te mantengas estático en el aire, las velocidades angulares de tus tres ejes a 0º/s (sin ninguna rotación en ningún sentido).
  2. Drone (Arduino): recibido humano. MPU6050, necesito que me digas a qué velocidad nos movemos en los tres ángulos.
  3. Drone (MPU6050): Según mis mediciones rotamos a 0º/s de pitch, 0º/s de yaw y -5º/s de roll.
  4. Drone (Arduino): Recibido MPU6050, parece que tenemos una desviación de 5º/s en el roll respecto a lo que nuestro humano nos ha pedido. Atentos motores, tenemos que corregir la desviación en la velocidad del eje roll. Acelera el motor 3 y frena el 1 → PIDS
  5. Drone (Motores): recibido Arduino. Aplicando cambios en la consigna a los motores.
  6. Y vuelta al punto 1)

Dicho de una manera más ‘técnica’ la secuencia quedaría de la siguiente manera. Como hemos visto en la entrada dedicada a la lectura del mando RC, vamos a utilizar interrupciones hardware para la función de lectura RC (si no has leído esa entrada te recomiendo que antes te la leas). El loop se ejecutará periódicamente y cada vez que haya una interrupción hardware se leerán los ángulos que transmite el mando RC.

Secuencia: Esta secuencia se ejecuta cada 6ms

  1. Arduino pide lecturas al sensor MPU6050 para calcular las velocidades de rotación en los ejes roll, pitch y yaw.
  2. El sensor MPU6050 responde con sus lecturas y se realizan los cálculos de velocidad angular en º/s.
  3. Con estas lecturas y las consignas que recibimos desde el mando, los PID calculan el error y cuanto acelerar o decelerar cada motor para compensarlo.
  4. Vuelta al paso 1)

**Si hay interrupción hardware: Leer mando RC. Cada 20ms aprox. recibimos una lectura.

A este proceso se le llama ‘Lazo de control’. Es muy importante tener en mente que este lazo de control se ejecutará una y otra vez cada 6ms.

Diagrama de bloques de un controlador PID. Drone arduino
Diagrama de bloques de un controlador PID

Como vemos, los encargados de calcular el error de cada ángulo y actuar en consecuencia son los PID. Los PID son una parte fundamental de nuestro drone por lo que es necesario saber algo de teoría sobre ellos. Hay infinidad de información en todos los idiomas sobre sistemas de control basados en PIDs y sus aplicaciones en drones, por lo que no me voy a extender mucho en este tema. Recomiendo acudir a Internet y dedicar algo de tiempo a entender bien su funcionamiento. Arduino cuenta con una librería para PID, pero recomiendo no utilizarla e intentar entender el funcionamiento de estos controladores programándolos vosotros mismo (son muy sencillos). El objetivo de un PID es conseguir un error entre la consigna de velocidad y la velocidad real de 0º/s (metros, grados… según la aplicación), es decir, que la velocidad de rotación real sea igual a la consigna que llega desde el mando en todo momento. Pongamos como ejemplo uno de los ejes de nuestro drone, por ejemplo el eje Pitch:

Lo primero que hace esta estructura de control es comparar la referencia de velocidad angular que nos llega desde el mando, en la imagen ‘W Pitch* (mando)’, con la lectura que recibimos del sensor MPU6050, en la imagen ‘W Pitch (IMU)’. Haciendo la resta de estas dos señales conseguimos en valor de desviación o error en nuestro eje pitch, en la imagen, señal Err.1:

Estrategia de control drone Arduino modo acrobática

Por ejemplo, si desde el mando nos llega la consigna de 0º/s de pitch y el sensor MPU6050 está leyendo que la velocidad real es de +10º/s, la variable ‘Err.1’ tomará el valor -10º/s, es decir, tenemos un error en la velocidad del eje pitch de -10º/s. Este podría ser un ejemplo de que debido al viento, nuestro drone se está inclinando en una dirección, cuando lo que queremos es que se mantenga estable. El objetivo de nuestro PID será hacer que este error sea siempre de 0, para lo que habrá que actuar sobre los motores, contrarrestando el viento y haciendo que la lectura del sensor MPU6050 sea de 0º/s (que no gire). El error antes de contrarrestar la perturbación:

Err.1 = w Pitch* (mando) – w Pitch (IMU) = 0 rad/s – 10rad/s = -10rad/s

El error es enviado al PID y este genera la consigna en micro-segundos acelerando/decelerando los correspondientes motores hasta contrarrestar la perturbación. Cuando el drone comience a girar y se vaya corrigiendo la desviación, la variable Err.1 irá disminuyendo hasta convertirse en 0, momento en el que drone habrá detenido la rotación y no haya desviación alguna entre la consigna que enviamos desde el mando y la rotación real.Una vez corregida la desviación y que el drone a dejado de rotar, el error baja a 0º/s, CONSEGUIDO, el drone es estable:

Err.1 = w Pitch* (mando) – w Pitch (IMU) = 0 rad/s – 0 rad/s = 0 rad/s

Si por el contrario desde el mando nos llega una referencia de 10º/s, es decir, queremos que nuestro drone se incline y desplace en su eje pitch, el funcionamiento sería similar. El error pasaría a ser de 10º/s y el PID aceleraría los correspondientes motores hasta aumentar la velocidad a 10º/s, es decir, hasta hacer el error cero.

Err.1 = w Pitch* (mando) – w Pitch (IMU) = 10 rad/s – 0 rad/s = + 10rad/s

Tras acelerar los motores, el drone empezará a rotar en el sentido que hayamos indicado hasta alcanzar la velocidad deseada, momento en el que el error bajará a 0º/s y habrá finalizado la operación:

Err.1 = w Pitch* (mando) – w Pitch (IMU) = 10 rad/s – 10 rad/s = 0 rad/s

error 0 PID arduino drone estable

Este error ‘Err.1’ lo recibe el PID y genera una salida ‘Pulso (us)’ en función de los parámetros Kp, Ki y Kd que hayamos establecido. Simplemente cogemos el error y lo multiplicamos por estos valores, haciendo más o menos agresivo el control de estabilidad de nuestro drone.

La parte Kp (PID) es proporcional al error, simplemente multiplicamos ambos términos. Si por ejemplo tenemos un valor de Kp de 10 y tenemos un error de 10º:

10*10º = 100us

Si el motor estaba girando con un PWM de 1.5ms, aceleraría hasta 1.5ms+0.1ms = 1.6ms.

La parte Ki (PID) es proporcional al error que vamos acumulando en cada ciclo. Cogemos el error actual y lo multiplicamos por el término Ki, pero en cada nuevo ciclo de control sumamos el valor obtenido en el ciclo anterior. De esta forma conseguimos que el error en régimen permanente sea de 0.

La parte Kd (PID) es proporcional a la diferencia de error entre ciclos. Sirve para suavizar la respuesta del control.Mas adelante en esta entrada veremos como programar los PID en Arduino.

La salida de los PID se da en milisegundos. Si recordáis esta entrada donde hablé sobre los motores (si no, id a releedla), hablábamos de cómo variando el tiempo en el que el PWM está en estado HIGH podíamos aumentar o reducir la velocidad de los motores. Por esta razón, la salida de los PID se da en milisegundos, porque para corregir las desviaciones o el error, necesitamos variar el tiempo en el que el PWM está en estado HIGH. Como ya habréis imaginado, necesitamos un PID para cada eje del drone que queramos controlar, en nuestro caso 3: Pitch, Roll y Yaw.

Finalmente todas las señales se combinan para generar una señal para cada motor. Al cálculo de estas cuatro señales he decidido llamarlo MODULADOR. ¡Recordad que estas cuatro señales se miden en milisegundos!

esc1 = throttle – salida PID pitch + salida PID roll + salida PID yaw
esc2 = throttle – salida PID pitch – salida PID roll – salida PID yaw
esc3 = throttle + salida PID pitch – salida PID roll + salida PID yaw
esc4 = throttle + salida PID pitch + salida PID roll – salida PID yaw

Importante, las señales esc1, esc2, esc3 y esc 4 nunca deben superar los 2ms, que es la consigna de máxima potencia para los motores. Si alguna de las señales supera esta cifra significa que algo hemos hecho mal, ¡no podemos enviar al motor una consigna mayor a 2ms! Como veremos más adelante, vamos a capar por software estas señales para que nunca sean mayores de 2ms, aunque esta protección nunca debería entrar en funcionamiento si hemos programado bien el software. Para ello recordad limitar la señal máxima de throttle a un máximo de 1.7ms aproximadamente, para dejar margen para los PID. Los PID también tendrán que ser limitados a un valor aproximado de 300us.

El signo de cada término de la ecuación puede variar en función de cómo tengáis orientada la IMU en vuestros drone o de la disposición de los motores. Es importante asegurar que los signos están bien puestos para evitar accidentes catastróficos el primer día de vuelo. Para ello, es imprescindible montar nuestro MPU6050 en el sentido que indico en esta entrada. Una vez hecho esto, recomiendo situar el drone en el suelo e ir inclinándolo manualmente en sus tres ejes mientras visualizamos las señales esc1, esc2, esc3 y esc4 para comprobar que todo esté en orden.

MPU6050 colocación en el drone Arduino

La estrategia de control completa representada en bloques quedaría de la siguiente forma. Únicamente programando esto nuestro drone podría volar sin problemas.

Estrategia de control drone Arduino modo acrobática

Pasemos a entender cómo programamos todo esto en Arduino. Partiremos asumiendo que ya hemos leído y procesado los datos del mando RC y del sensor MPU6050 en Arduino. Primero vamos a analizar todas las partes por separado, y finalmente pondré el código completo.

En primer lugar hay que hacer que el lazo de control se ejecute de forma constante exactamente cada 6ms (en mi caso). Hacer esto en Arduino es extremadamente simple:

Como veis, es muy fácil de entender, simplemente hacemos los cálculos pertinentes y esperamos sin hacer nada hasta que pasen 6ms. Más adelante veremos cómo aprovechar estos tiempos muertos donde Arduino no hace nada (solo espera) para ejecutar pequeñas acciones que no necesitan de mucha carga de procesamiento, como puede ser medir la tensión de la batería o gestionar algún led. De esta forma nos aseguramos de que aunque el tiempo de ejecución del lazo de control varíe por lo que sea (mas adelante en este apartado veremos porque), siempre se ejecutará una vez exactamente cada 6ms. El resto del tiempo estará esperando a llegar al tiempo fijado.

** El tiempo de ejecución no tiene por qué ser de 6ms, pueden ser de 4ms, 10ms o el valor que sea, vosotros elegís el valor que queráis utilizar, a mi con 6ms me va bien. Evidentemente cuanto más rápido sea el control, mayor estabilidad tendrá nuestro drone.

El siguiente paso es programar los PID. Como ya he dicho, sobre este tema se han escrito ríos de tinta, por lo que no voy a entrar a explicarlo una vez más. Como veis, es bastante simple de entender, simplemente calculamos en error como hemos hecho más arriba, y lo multiplicamos por los valores de Kp, Ki y Kd. Partiendo de que ya dominamos el tema del sensor MPU6050 y la lectura de las variables recibidas desde el mando, vamos a ver como se programan los famosos PID utilizando Arduino. Este código no es ejecutable como tal, es simplemente para que veías como se programa y entendíais el código. Intentad entender en código y la función de los tres parámetros del PID:

El siguiente paso es generar las señales PWM para los motores en función las salidas de los controladores PID (recordad que los motores se gobiernan con salidas PWM). ¿Por qué no utilizar la función milliseconds() que ya incorpora Arduino? Esto generaría una señal PWM del ancho de pulso que indiquemos entre paréntesis. Pues la respuesta es bien sencilla: porque estas salidas PWM se ejecutan a 50Hz (cada 20ms), y ¿de qué serviría ejecutar el lazo de control cada 6ms, si luego esa información no puede transmitirse a los motores hasta pasados 20ms? Para ello, tenemos que hacer que la frecuencia de las salidas PWM de nuestra placa Arduino sea la misma que la de nuestro lazo de control, 6ms, de esta forma logramos que salida de los PID se aplique sin ningún retraso.

Vamos a analizar la siguiente imagen donde resumo el funcionamiento del lazo de control y la generacion PWM. Todos los ciclos comienzan con las cuatro señales PWM en estado HIGH, siempre. La duración del pulso es calculada por los controladores PID en el ciclo anterior. Cuando la señal paso a estado LOW, se hace la lectura del sensor MPU6050, la lectura del mando, y el cálculo de los PID del periodo siguiente. En el ejemplo de la imagen inferior, el primer cálculo arroja como resultado 1.6ms de PWM, que se aplica al pulso del siguiente ciclo.:

El tiempo que el pulso está en estado HIGH puede variar entre 1ms (parado) y 2ms (máxima velocidad). Esto hace que para que cada periodo dure exactamente 6ms, el tiempo de espera varíe en la misma proporción, de ahí la importancia de controlar el tiempo de ejecución.

Para generar las salidas PWM y que estas estén sincronizadas con la frecuencia de ejecución del lazo de control vamos a utilizar el siguiente código. Al principio puede que resulte un tanto complicado de entender, pero en cuento lo tengáis, comprenderéis que es una solución muy simple. Lo primero que hacemos al comienzo de cada nuevo periodo de 6ms es poner las 4 salidas PWM en estado HIGH:

Después, sumamos al tiempo calculado por el modulador (señales esc1, esc2, esc3 y esc4) el tiempo total transcurrido desde el inicio del programa (loop_timer). Por ejemplo, si el modulador calcula un tiempo de PWM de 1.6ms para el motor número 1, y desde que hemos inicial el programa han transcurrido 1s (1000ms):

accion_m1 = 1000ms + 1.6ms = 1001.6ms

Finalmente, utilizando el siguiente bucle while, pasamos a estado LOW las cuatro señales PWM, cada una cuando corresponda. Cuando la variable esc_loop_timer (el tiempo real transcurrido) sea igual a la variable , significará que el pulso ha estado en estado HIGH exactamente 1.6ms, por lo que es hora de pasarlo a estado LOW:

Arduino no saldrá de este bucle while hasta que las cuatro señales PWM estén en estado LOW. ¡Ya tenemos señales PWM de frecuencia personalizada!

Una vez que las cuatro señales PWM están en estado HIGH, sabemos que tenemos un margen de tiempo de 1ms (que es el ancho de pulso mínimo para las señales PWM) donde Arduino no va a hacer nada, solo esperar. Podemos aprovechar este mili-segundo para hacer alguna pequeña tarea que para Arduino suponga un tiempo de procesado menor a 1ms. Yo, por ejemplo, utilizo este tiempo para leer la tensión de la batería y activar la correspondiente alarma en caso de que la tensión sea demasiado baja:

Estrategia de control drone Arduino modo acrobática

Realmente el tiempo de espera de Arduino varía entre 1ms (parado) y 2ms (máxima potencia) dependiendo del estado de los motores. Aun así siempre hay que asegurarse de que la tarea que realizamos en este tiempo muerto sea inferior a 1ms, en caso contrario no será posible controlar los motores a bajas velocidades ya que el pulso no pasará a estado LOW hasta haber acabado esta tarea. Imaginemos que en el tiempo muerto realizamos una tarea que requiere 1.5ms de tiempo de ejecución, ¡el ancho de pulso mínimo de las señales PWM que conseguiríamos sería de 1.5ms! los motores nunca llegarían a detenerse por completo, cosa muy peligrosa.

Como hemos visto, el modo acrobático se basa únicamente en las lecturas de velocidad angular obtenidas del sensor MPU6050. Cuando giramos alguna de las palancas de nuestro mando, estamos ordenando al drone que gire en una determinada dirección a una determinada velocidad, por lo que al soltar la palanca el drone se mantendrá inclinando en el punto donde lo hayamos dejado, no volverá a su posición inicial a 0º de inclinación, solo se habrá detenido la rotación (0º/s). Imaginemos que giramos la palanca de pitch y el drone empieza a gira sobre su eje a una determinada velocidad. Cuando soltemos la palanca y esta vuelva a su posición inicial, el drone recibirá la nueva consigan de velocidad 0, es decir, que se quede quieto en su posición, por lo que quedará inclinado. Para que el drone vuelva a su posición inicial de 0º de inclinación, habrá que girar la palanca en sentido contrario y mandar una consigna de velocidad negativa hasta que quede nivelado y podamos soltar la palanca. El modo acrobático es muy difícil de controlar, únicamente los pilotos experimentados puede hacerlo forma segura. Para nosotros es un paso intermedio antes de conseguir el drone estable que veremos en el siguiente apartado.

¿Veis? ¡No es tan complicado! Acudid al apartado donde os dejo el software completo y dedicadle algo de tiempo a entender bien todos estos conceptos. Si habéis llegado hasta aquí entendiéndolo todo, ya tenéis en 80% hecho. Vayamos a por el modo estable.

Modo de control ‘Estable’

Este modo necesita de dos PID en cascada por cada eje a controlar, además de lecturas de velocidad de rotación y aceleración del sensor MPU6050 a partir de los cuales calcular el ángulo de inclinación de cada eje en grados (º). La ventaja de este modo de vuelo es que el drone es completamente estable y por lo tanto mucho más fácil de manejar. Al contrario que en el modo acrobático, cuando soltemos alguna de las palancas del mando RC el drone volverá automáticamente a su posición de 0º de inclinación. La consigna que mandamos desde el mando es de grados de inclinación (º), no de velocidad (º/s) como en el caso acrobático.

Drone Arduino modo estable
En modo estable contrarrestamos la inclinación

El funcionamiento de la estrategia de control es muy simple. Si detectamos una inclinación, ordenamos al drone que gire en dirección contraria a una velocidad determinada hasta contrarrestar esta inclinación:

Secuencia: Esta secuencia se ejecuta cada 5ms (200Hz)

  • Arduino pide lecturas de velocidad angular y aceleración en los tres ejes al sensor MPU6050.
  • El sensor responde con sus lecturas y se realizan los cálculos de velocidad angular (º/s) e inclinación (º).
  • Con las lecturas de inclinación y las consignas que recibimos desde el mando, el primer PID calcula el error de inclinación y genera la consigna de velocidad para contrarrestarla.
  • El segundo PID toma esta consigna del lazo exterior y con la lectura de velocidad de la del sensor MPU6050, genera la salida en microsegundos para enviar a los motores. Los motores aceleran y contrarrestan la desviación de velocidad, que a la vez está contrarrestando la desviación en la inclinación.
  • Vuelta al paso 1)

**Si hay interrupción hardware: Leer mando RC → Cada 20ms aprox. recibimos una lectura.

Lo primero que hace esta estructura de control es comparar la consigna de inclinación (º) que nos llega desde el mando, en la imagen ‘Pitch* (mando)’, con la lectura que recibimos del sensor MPU6050, en la imagen ‘Pitch (IMU)’. Fijaos en que en este modo de vuelo el mando fija la consigna de inclinación (º) y no de velocidad de rotación (º/s) como en el modo acrobático. Haciendo la resta de estas dos señales conseguimos en valor de desviación o error en nuestro eje pitch, en la imagen, señal Err.1. Esta variable se da en grados de inclinación (º), 5º, 10º… la que sea:

Estrategia de control drone Arduino modo estable

Esta variable Err.1 pasa por el primer PID (PID_angulo o PID estable) y genera una salida que se utilizará como referencia para el siguiente lazo o lazo de velocidad (el utilizado en el modo acrobático). Lo que conseguimos con esto es indicar al drone que si está inclinado, tiene que aumentar/reducir la velocidad en los motores y rotar a una determinada velocidad y en dirección contaría a la inclinación para contrarrestarla y volver a la posición inicial de 0º:

Estrategia de control drone Arduino modo estable

Como hemos dicho, se compara la consigna que nos llega desde el lazo estable, en la imagen ‘w* pitch’, con la lectura de velocidad de rotación que recibimos del sensor MPU6050, en la imagen ‘w Pitch (IMU)’, para generar el error ‘Err.2’. Este error representa la desviación entre la velocidad que necesitamos para contrarrestar la inclinación y la velocidad real de rotación del drone. Finalmente la variable Err.2 pasa por el PID de velocidad (PID_w) y generamos la salida para el modulador que actuará sobre los motores.

Estrategia de control drone Arduino modo estable

Cuando el drone comience a girar y se vaya corrigiendo la desviación, tanto las variables Err.1 y Err 2 irán disminuyendo hasta convertirse en 0, momento en el que drone habrá vuelto a su posición inicial y no haya desviación alguna entre la consigna que enviamos desde el mando y la inclinación real.

La siguiente figura muestra la estrategia de control total utilizada en el modo estable representada con bloques. Es parecida a la figura mostrada para el modo acrobático, solo que utilizando un PID más en los ejes pitch y roll (el eje yaw no requiere de otro PID). El primer PID toma la lectura de inclinación (º) calculada a partir de las lecturas del sensor MPU6050 y la compara con la consigna del mando. Si hay una desviación de inclinacion, este primer PID genera una referencia de velocidad para el siguiente lazo, acelerando los correspondientes motores y contrarrestando la inclinación. El segundo PID controla la velocidad a que que rota el drone mientras contrarresta la inclinación. Es una estrategia bastante intuitiva:

Estrategia de control drone Arduino modo estable

Utilizando este método conseguiremos que al soltar la palanca del mando, el drone vuelva automáticamente a su posición inicial de 0º sin tener que mandar una consigna de velocidad negativa para contrarrestar la inclinación. El funcionamiento de los dos métodos es evidente, el acrobático  simplemente compensa la rotación (º/s), mientras que el estable compensa la inclinación (º): 

Drone Arduino modo acrobático
En modo acrobático simplemente contrarrestamos la rotación
Drone Arduino modo estable
El modo estable contrarresta la inclinación

En el apartado ‘código completo’ podéis descargaros el software completo que utilizo yo. Utilizad esta entrada para entender el código.


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. Como leer variables de Arduino en Matlab (código).
  11. Los mejores drones de 2018 | Comparativa y guía de compra.
4 Comentarios

Añadir un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *