FUNDAMENTOS
¿Qué es un dron?
Un vehículo aéreo no tripulado (VANT), o en inglés UAV (Unmanned Aerial
Vehicle) es una aeronave que vuela sin tripulación y es capaz de mantener
de manera autónoma un nivel de vuelo controlado y sostenido, y propulsado
por un motor de explosión, eléctrico o de reacción.
Dado su particular sonido al volar (en especial los multirrotor) se les llama
comúnmente en inglés "drones", que en castellano significa "zánganos". La
RAE ya introdujo el término de manera oficial a nuestro idioma, por lo que
nos hemos de referir en singular a un DRON (no drone, como se escribe
usualmente en muchas partes).
¿Qué tipos de drones existen?
En general, podemos utilizar la misma clasificación que existe para las
aeronaves de tamaño real. Según el medio de sustentación que utilicen,
existen aeronaves más livianas que el aire, que se basan, como su nombre
lo indica, en utilizar un elemento más liviano que el aire para lograr elevarse
y sostener el vuelo. Por otro lado, las aeronaves más pesadas que el aire
utilizan diferentes principios aerodinámicos para lograr la sustentación. En
la gráfica que se presenta a continuación se puede observar las diferentes
variantes que existen.
Fig. 1 - Clasificación de aeronaves
Como ya mencionamos, en el mundo de los drones existen versiones de
prácticamente todos los tipos de aeronaves mencionados anteriormente; sin
embargo, los más conocidos serían dos tipos en particular: los aviones y los
multirrotores. Como indica la gráfica, los aviones utilizan el principio de ala
fija, mientras los segundos utilizan alas rotatorias con las que producen
sustentación. A pesar de esta notable diferencia, el principio físico que
gobierna las alas es el mismo, que veremos a continuación.
Funcionamiento de un ala
La física del vuelo en las aeronaves se explica a partir de varias teorías; sin
embargo, las más populares están basadas en dos principios muy
conocidos: el Principio de Bernoulli y la Tercera Ley de Newton. A
continuación revisaremos de una manera simple ambos conceptos que
intentan explicar cómo se genera la sustentación y veremos si en efecto
proveen una explicación acertada.
El Principio de Bernoulli
En términos generales, el principio de Bernoulli nos dice que en un fluido
ideal en régimen de circulación por un conducto cerrado, la energía que
posee el fluido permanece constante a lo largo de su recorrido. Ahora bien,
la energía de un fluido está compuesta por tres componentes principales:
energía cinética: es la energía debida a la velocidad que posea el fluido;
energía potencial o gravitacional: es la energía debido a la altitud que
un fluido posea;
energía de presión: es la energía del fluido debido a la presión que
posee.
Ahora bien, el teorema de Bernoulli nos dice que la suma de estas energías
es constante, por lo que ante el aumento o disminución de alguna de ellas,
las demás también se verán afectadas para mantener dicha relación
constante. Para comprender esto más fácilmente se propone usualmente un
ejemplo donde tenemos una manguera en la cual fluye agua. En condiciones
normales, la presión y la velocidad del fluido serán iguales y constantes en
cualquier punto. Pero, ¿qué sucedería si presionamos la manguera en algún
punto? Si tomamos al agua como un fluido incompresible, significa esto que
la misma cantidad de agua que pasaba por la sección original tendrá que
pasar por un área menor (la que tenemos presionada) y en el mismo tiempo.
Para que eso suceda el fluido tendrá que incrementar su velocidad
(acelerarse). Si se mide la presión en las dos zonas (ver figura) notaremos
que hay menos presión en la zona en la que el fluido se acelera. En resumen,
según Bernoulli, si se incrementa la velocidad de un fluido, se consigue que
su presión disminuya.
Fig. 2 -
Principio de Bernoulli
Fig.
3 - Principio de Bernoulli en un ala
Transponiendo este mismo fenómeno al aire como fluido y colocando el
corte de un perfil del ala de un avión (o el rotor de un helicóptero),
observamos que debido a la curvatura de la superficie superior del ala
(técnicamente conocida como "extradós"), el aire tiende a acelerar en esta
zona superior y por lo tanto su presión disminuye, mientras el aire por
debajo del ala (parte conocida como "intradós") mantiene su velocidad y por
ende su presión. De esta manera se produce una diferencia de presión entre
la parte superior y la inferior. Esta diferencia de presión es la que origina la
fuerza de sustentación.
Sin embargo, esta explicación tiene sus aristas. Primero, muchos de sus
adeptos asumen que las moléculas de aire que se separan al principio del
ala deben llegar al mismo tiempo al final (y por eso las que van "por arriba"
deben ir más rápido). Esta asunción es incorrecta, ya que
experimentalmente se ha demostrado que las moléculas separadas no
tienen por qué llegar al mismo tiempo y "reunirse" al final del ala. Por otro
lado, esta explicación se basa en que el ala tiene una mayor curvatura en su
parte superior, algo que no siempre es cierto (existen perfiles de alas
simétricos). Y de ser así, no explicaría por qué los aviones pueden volar
invertidos, como se observa en muchos casos en aviones de combate o en
exhibiciones aéreas.
La Tercera Ley de Newton
Esta ley nos dice que toda acción tiene una reacción de igual magnitud pero
de sentido opuesto. ¿Cómo se aplica esto a las alas?
Imaginemos el ala como una especie de barrera inclinada donde las
moléculas del aire que vienen por debajo chocan contra ella y son desviadas
hacia abajo, produciendo la reacción en el ala de "ir hacia arriba".
Adicionalmente, el aire que fluye por arriba y por abajo sigue la curvatura
del ala y es desviado hacia abajo, aportando igualmente un reacción en
sentido opuesto. Es a la suma de estos efectos a la que debemos la
sustentación.
Aquí el problema radica en la extrema simplificación que se hace sobre el
aire en la parte superior. Sus moléculas rebotan igualmente sobre el
extradós, lo que anularía cualquier sustentación significativa producida por
este mecanismo en el intradós (una empuja hacia arriba y la otra hacia
abajo).
Fig.
4 - Aparente aplicación de la Tercera Ley de Newton en un ala
¿Y entonces? ¿Cuál es la explicación real?
En realidad las explicaciones anteriores no son totalmente incorrectas;
podrían considerarse mejor como incompletas, pues en efecto existe
diferencia de presiones que contribuye a la sustentación, así como
deflexión de aire en una dirección que causa un efecto opuesto. Lo más
exacto es decir que la sustentación se produce por "desviación" del flujo de
aire. En efecto, para un cuerpo inmerso en un fluido en movimiento, el fluido
permanece en contacto con la superficie del cuerpo. Si el cuerpo está
moldeado o (más importante aún, como veremos) es inclinado de forma que
produzca una deflexión neta del flujo, la velocidad local del fluido cambiará
en magnitud y/o dirección (un cambio de velocidad significa aceleración, lo
cual produce una fuerza). La fuerza neta producida en el cuerpo por este
fenómeno es la sustentación.
Se observa que con relación a la figura anterior, en la figura 5 la diferencia
es el flujo de aire. En la teoría anterior, se considera solo el flujo de aire por
abajo, el cual simplemente rebota contra el intradós, mientras que el aire
del extradós es irrelevante. En realidad debe considerarse el aire en ambas
partes y no considerar su efecto sobre el ala como un "rebote" sino como
una desviación de flujo. ¿Pero entonces, cómo se garantiza que el flujo de
aire neta se desvíe "hacia abajo" causando la reacción opuesta de una
fuerza ascendente en el ala? Cómo mencionamos antes, la forma del perfil
alar no es tan relevante como su inclinación en relación al viento, lo que
más técnicamente se conoce como "ángulo de ataque". Ampliaremos este
concepto en la siguiente sección.
El lector puede obtener más información sobre la manera cómo se genera
sustentación y el debate entre las teorías expuestas anteriormente en este
breve pero interesante artículo de la NASA sobre el tema -> ver artículo.
Fig. 5 - Sustentación por
desviación del flujo de aire
Fig. 6 - Fórmula de la
sustentación
La fórmula de sustentación
La figura 6 nos presenta la fórmula de la sustentación para un perfil alar.
Como se observa, depende de cuatro cantidades particulares: la densidad
del aire, la velocidad (al cuadrado), la superficie del ala y una variable
importante denominada "coeficiente de sustentación". Para obtener fuerza
de sustentación sería necesario entonces jugar con estos parámetros. Es
evidente que no tenemos ningún control sobre la densidad del aire, e
igualmente, una vez construida, la superficie del ala es una cantidad fifa
(salvo algunos "trucos" que se usan en aeronaves reales para modificarla
levemente, pero no entremos en detalles). Nos quedan, pues, la velocidad
de desplazamiento del ala y el coeficiente de sustentación como
parámetros modificables durante el vuelo para controlar la sustentación.
Vemos entonces en qué consiste el coeficiente de sustentación. Esta
cantidad adimensional está constituida tanto por una componente fija,
dependiente de los parámetros de construccióndel ala, como por un
importante componente variable, que es el mencionado ángulo de ataque.
Así, como se observa en la figura 7, conforme incrementa el ángulo de
ataque (hasta un valor límite) aumenta este coeficiente y por tanto la
sustentación.
Observamos que la curva del coeficiente de sustentación puede variar en
función del perfil alar utilizado, pero el mensaje a rescatar es que la
variación del ángulo de ataque es un factor importante para el control de la
sustentación. De esta manera, tenemos dos posibles parámetros que nos
permiten variar la sustentación: la velocidad del ala y su ángulo de ataque.
¿Cuál utilizar? En las aeronaves tripuladas se usa principalmente el ángulo
de ataque, aunque al inicio de los vuelos y esporádicamente durante los
mismos se varía la velocidad.
Todo lo que hemos visto hasta el momento es aplicable tanto para
aeronaves tripuladas (de tamaño "real") como para drones. Sin embargo, es
el momento de destacar una pequeña diferencia en cuanto a este tema. Si
bien para aeronaves de ala fija el método de control de sustentación es
igual tanto para aviones tripulados como para no tripulados, en el caso de
ala rotatoria, que es nuestro principal foco de interés en esta página, el
método varía. En helicópteros tripulados, se prefiere dejar el rotor principal
con una velocidad (RPM) usualmente fija y variar la sustentación con el
ángulo de ataque de las aspas (de manera más concreta, se varía el ángulo
de paso o "pitch", pero no entremos en este detalle). Se hace así porque es
una manera más eficiente para el trabajo del motor y permite una mayor
controlabilidad para el piloto (recordemos que la sustentación varía con el
cuadrado de la velocidad, lo cual dificulta la relación entre velocidad del ala
y sustentación generada). Para el caso de los drones tipo helicóptero y
multirrotor, es la velocidad de rotación el factor clave. Tratándose de
motores pequeños y naves controladas electrónicamente en una gran parte,
la relación cuadrática entre velocidad y sustentación no es un factor tan
grave, mientras que la necesidad de un mecanismo de control del paso de
las hélices sugiere una considerable complicación mecánica que se puede
evitar.
Fig. 7 - Coeficiente de
sustentación
Las fuerzas aerodinámicas
La sustentación es la fuerza más importante para la existencia de cualquier
aeronave, y por ello le hemos dedicado la mayor parte de este estudio. Sin
embargo, es claro que no es la única. En realidad, podemos generalizar las
fuerzas a las que está expuesta una aeronave en cuatro: la ya mencionada
sustentación, el peso, el empuje y el arrastre o resistencia (figura 8). Estas
cuatro fuerzas son conocidas como "fuerzas aerodinámicas" y son todas
muy importantes en el diseño, construcción y operación de una aeronave.
Acá vemos surgir otra gran diferencia entre los tipos de aeronave más
utilizados, ala fija y rotatoria. En este caso, los primeros utilizan motores
específicamente para producir empuje, anteriormente siendo propulsores de
hélice y hoy en día siendo de turbina en aeronaves tripuladas.
Fig. 8 - Fuerzas
aerodinámicas
Fig. 9 - Fuerzas aerodinámicas
en un multirrotor
En el caso de los helicópteros y multirrotores, tripulados o no, tenemos las
mismas fuerzas, pero hemos de hacer una diferenciación semántica. Como
la acción de los motores está dedicada únicamente a la rotación de las
hélices, en este caso hemos de asimilar la sustentación con el término
"empuje". Ahora bien, cuando la aeronave se inclina hacia un lado, la fuerza
de empuje apunta en la misma dirección (ya no es totalmente vertical). En
este caso, por descomposición de fuerzas podemos observar que surge una
componente horizontal. Con base en esta apreciación podemos concluir que
la fuerza de desplazamiento lateral se obtiene por la inclinación del rotor
principal hacia el lado de dirección de movimiento deseado.
En todo caso, en ambas situaciones, el arrastre o resistencia es la fuerza
surgida que se opone al movimiento.
En conclusión, ¿cuáles son los fundamentos mecánicos
aplicables a nuestro dron?
En esta página guiaremos a nuestros lectores en la construcción de un dron
tipo cuadricóptero, es decir, de cuatro rotores. Con base en los
fundamentos de vuelo que hemos expuesto previamente, estas serían las
características aplicables a esta aeronave en particular.
1. La aeronave contará con cuatro rotores o hélices, donde cada uno de
los cuales requiere su propio motor dedicado. Con base en lo expuesto,
esto significa que contaremos con cuatro fuentes independientes de
empuje vertical. Es importante, pues, pensar en la manera como se
pueden controlar estas cuatro fuentes para obtener un vuelo estable y
además en la dirección deseada.
2. Considerando solo el desplazamiento vertical, es necesario lograr que
los cuatro rotores produzcan exactamente el mismo empuje al mismo
tiempo. Físicamente, esto es imposible, pues así se tengan cuatro
hélices junto a sus respectivos motores aparentemente iguales,
siempre habrá una mínima diferencia en el empuje producido y por tanto
se requiere compensar esta situación.
3. Para obtener desplazamiento lateral es necesario inclinar la aeronave
en la dirección de vuelo deseada. Para lograrlo, debemos producir una
diferencia en el empuje generado por dos rotores contiguos con
relación a los otros dos.
4. Finalmente, cuando un rotor gira en una dirección, por la misma tercera
ley de Newton, se produce una fuerza (en este caso un torque) en la
dirección opuesta sobre el cuerpo en el que va instalado el rotor. Esta
es la razón de la existencia de los rotores de cola en los helicópteros,
pues este rotor permite generar un torque de compensación sobre el
cuerpo de la aeronave que impide que este rote en el sentido opuesto al
de su rotor principal. En nuestro caso, teniendo cuatro rotores, esto se
resume en que dos de ellos deben rotar en una dirección, mientras los
otros dos lo harán en la opuesta. De esta manera los torques de
reacción generados por cada rotor se cancelarán entre sí, obteniendo
un torque neto nulo.
5. Las fuerzas y torques producidas por nuestro cuadricóptero pueden
observarse en la figura 10. Se observa que las cuatro fuerzas de empuje
apuntan en dirección perpendicular a cada rotor. Los torques indican la
dirección de rotación de cada rotor, que como dijimos, deben alternarse
en cada rotor subyacente. En términos prácticos, esto significa que al
momento de comprar nuestras hélices, requerimos dos pares en
sentidos opuestos (en el mercado se conocen como rotores CW y CCW
por "clockwise" y "counter-clockwise" respectivamente).
Fig. 10 - Fuerzas y torques en nuestro cuadricóptero
MATERIALES
Como indicamos previamente, en esta página haremos un dron tipo
cuadricóptero. Para ello, podemos clasificar los materiales en dos
categorías: materiales estructurales y materiales electrónicos. Los primeros
serán los que conformarán la parte mecánica de nuestro aparato, brindando
tanto soporte como las características aerodinámicas requeridas. La parte
electrónica tendrá varios componentes, entre sensores, actuadores y el
"cerebro" de nuestro aparato.
A continuación veremos el desglose de estos materiales requeridos, así
como el funcionamiento de cada uno de ellos.
NOTA: Si estás en Colombia, puedes visitar directamente nuestra mini-
tienda (CLIC ACÁ), donde encontrarás algunos de ellos y podrás de paso
apoyar nuestro proyecto.
Fig. 1 - Posible apariencia final de nuestro dron
Materiales estructurales
En esta categoría debemos contar con los siguientes materiales:
1. Soporte
2. Hélices (4 en total)
Ahora veremos la descripción en detalle de cada uno de estos.
Soporte
Como su nombre lo indica, será el componente que conforme la estructura
principal y dé sustento a todos los demás componentes de nuestro dron. En
mis diseños personales he usado dos tipos de soporte, que pongo a
consideración del lector para que use al que más le convenga.
La opción más popular cuando se trata de construir drones propios es usar
un marco armable como el que se aprecia en la figura 2. Este marco fue
desarrollado originalmente por DJI, pero hoy existen muchas réplicas de
excelente calidad y resistencia. El marco se puede ensamblar y desarmar
fácilmente; adicionalmente provee los agujeros para el montaje de los
motores y viene con caminos de distribución de potencia ya incorporados
(son los cuadrados dorados en la foto, aunque no todos son visibles), lo cual
es de mucha utilidad en el montaje de la electrónica. En resumen, si se
quiere una opción práctica, resistente y fácil de montar, este sería el marco
a utilizar. Es importante tener en cuenta que vienen en tamaños
predefinidos (el de la foto se llama F330, por sus 330 mm de diagonal), por
lo que es importante saber el tipo de rotores que se van a utilizar para tener
el marco adecuado. Una buena medida de referencia para los tamaños de
marcos y hélices más populares es la siguiente: para hélices de 8" usar el
marco F330, para hélices de 10" usar el marco F450.
Fig. 2 - Marco o soporte armable
Fig. 3 - Opción de marco de madera para el dron
También es posible utilizar un marco de madera para nuestro dron. En mi
trabajo con estas aeronaves construí prototipos con estos marcos como el
que se observa en la figura, que aunque rudimentario, resultó bastante bien
para las pruebas y los vuelos iniciales. Desde luego, su resistencia no es
comparable con el marco de fibra de vidrio, y tras un golpe fuerte
posiblemente resultará averiado. Sin embargo, es bastante barato y no será
mucho problema de reemplazar. Al mismo tiempo, es posible diseñarlo con
un mayor espacio en la parte central que nos permitirá acomodar de una
manera más libre los elementos de electrónica como la tarjeta de control y
los sensores que deseemos instalar.
Hélices
También conocidos como rotores o palas, son el elemento más importante
en cuanto a la aerodinámica de nuestro cuadricóptero. Evidentemente, el
número requerido es cuatro, de las cuales requerimos dos pares en sentidos
opuestos (en el mercado se conocen como rotores CW y CCW por
"clockwise" y "counter-clockwise" respectivamente, o "de giro en sentido
horario" y "giro en sentido anti-horario", en castellano). Sin embargo nunca
está de más (de hecho es altamente recomendado) contar siempre con
respuestos, pues es un elemento propenso a dañarse por los choques,
especialmente en los primeros vuelos.
Existe gran variedad de hélices en el mercado, teniendo varios factores
diferenciales como el material o el tamaño. En cuanto al primero, hay de
diversos tipos como plástico, nylon, fibra de carbono e incluso madera. En
cuanto al tamaño, igualmente hay gran variedad en función del tamaño y
función del dron a construir. Lo importante a conocer es la denominación de
las hélices: usualmente vienen con una denominación de cuatro cifras,
como 5030 o 1045. En este caso el primer par de números indica la longitud
de la hélice de punta a punta en pulgadas (50 sería 5.0, mientras 10 es en
efecto 10), mientras el segundo par representa el avance o "pitch" de la
pala en grados (30 y 45 para los ejemplos mencionados). Nuevamente
resalto la importancia de que haya una concordancia entre el tamaño del
marco y el de las hélices a utilizar. Adicionalmente, surge un nuevo
parámetro a tener en cuenta: hay que asegurarse de que las hélices sean
también apropiadas para el motor a utilizar. Por un lado el agujero central
debe ser consistente con el eje del motor escogido (nótese en la figura que
muchas hélices son suministradas con anillos adaptadores para este
propósito); por otro lado el tamaño de la hélice debe corresponder a la
potencia del motor para obtener un rendimiento adecuado de la aeronave.
Fig. 4 - Rotores o
hélices
Materiales electrónicos
En esta categoría debemos contar con los siguientes materiales:
1. Motores (4 en total)
2. Variadores de velocidad (4 en total)
3. Tarjeta de control
4. Sensor inercial
5. Módulo de comunicación
6. Batería
7. Tarjeta de distribución
Ahora veremos la descripción en detalle de cada uno de estos.
Motores
Como en todo, existen diferentes clases de motores según la aplicación (y
el presupuesto). En particular, para drones del nivel de desarrollo como el
que aquí construiremos, se suelen considerar dos tipos de motores: DC con
escobillas y sin escobillas o "brushless". Los primeros se suelen usar solo
en los drones muy pequeños y de bajo costo. Su ventaja es su pequeño
tamaño en general, así como su facilidad de operación, pues simplemente
reciben un voltaje DC hasta cierto nivel y en función del mismo producen
una velocidad de salida proporcional. Sin embargo, usualmente requieren
una caja reductora para producir un torque capaz de mover las hélices, así
como tienen un mayor y más rápido desgaste debido a sus escobillas, pues
con cada rotación existe un contacto entre partes mecánicas.
La opción más popular y recomendada es el uso de motores "brushless", los
cuales se componen de dos partes principales, una es el estator, donde se
haya el bobinado con un numero determinado de polos, y la otra parte es la
campana, que es la parte móvil y en la que van alojados los imanes. Al
estator se envían impulsos eléctricos, los cuales repelen los imanes
situados en la campana, conmutando entre unos y otros a gran velocidad
para producir el giro continuo de esta. Por tanto, se tiene como gran ventaja
que no hay partes mecánicas en contacto con otras para producir el giro del
motor, lo cual posibilita que tenga una larga vida útil en comparación con un
motor DC convencional. Igualmente, el torque producido es lo
suficientemente alto para conectar el eje directamente a la hélice
respectiva. Sin embargo, la señal eléctrica requerida para la operación es
una señal trifásica de alta frecuencia, la cual no es sencilla de generar. Por
tanto, se requiere un elemento intermedio entre el suministro de potencia y
el motor, conocido como variador de velocidad o ESC, del cual nos
ocuparemos más adelante.
En la mayoría de los motores, junto al modelo del motor aparece una
numeración muy importante para identificar sus características.
Inicialmente, aparecen cuatro dígitos estilo 2205 o 2306, lo cual indica el
tamaño del estator en milímetros, donde los dos primeros dígitos señalan su
diámetro y los dos siguiente su altura del estator. El siguiente dato
importante son las KV, este número nos indica las revoluciones por minuto
(RPM) del motor sin carga, y es el numero indicado multiplicado por el
voltaje a utilizar. Cuantas mayor sea el número KV, más revoluciones
producirá el motor pero menos torque tendrá, por lo que tendremos que
tener cuidado con las hélices que usemos. En el apartado siguiente, acerca
de los variadores, presentaremos un método para escoger una acertada
combinación motor-ESC-hélices.
Fig. 5 -
Partes de un motor "brushless"
Variadores
También conocidos como ESC (Electronic Speed Controller), son
dispositivos requeridos para generar la señal eléctrica adecuada que
requieren los motores "brushless" para su operación, a partir de una señal
DC entregada por la batería del dron. Se componen de dos cables de entrada
y tres cables de salida gruesos. Los primeros corresponden a la entrada de
alimentación de la batería, mientras los segundos son la señal de salida
hacia los motores. Adicionalmente cuentan con un conector con dos o tres
cables notoriamente más delgados, los cuales van conectados a la tarjeta
de control, de la cual se reciben los datos para mover el motor. El número
de cables dependerá de si el ESC lleva incluido BEC (3 cables) o no (2
cables). Las siglas BEC significan "Battery Elimination Circuit", o Circuito de
Eliminación de Batería, el cual permite alimentar los demás componentes
electrónico (tarjeta de control, sensores, etc) a partir de este, eliminando la
necesidad de un regulador o inclusive de una batería adicional.
El criterio más importante para la elección del variador es la corriente. Con
base en la máxima corriente que, según información suministrada por el
fabricante, requiera el motor para su operación, se debe seleccionar una
variador que suministre un valor superior a dicha corriente.
En la sección de fabricación del dron de esta página trabajaremos con un
conjunto de materiales ya predefinidos, que en mi experiencia hacen una
buena combinación de hélices - motores - variadores (y batería, inclusive).
El lector es bienvenido a trabajar con este conjunto de materiales
recomendados; sin embargo, para aquellos que quieran conocer un poco
más sobre los principios de selección de los materiales e inclusive hacer
modificaciones a su propio criterio, recomiendo leer este enlace (ver
enlace) y a su vez los temas contenidos en el mismo, que ofrecen excelente
información sobre los materiales que hemos descrito y los criterios de
selección a utilizar.
Fig. 6 -
Variador de velocidad
Tarjeta de control
Es el cerebro del dron; un elemento esencial para asegurar el
funcionamiento de nuestra aeronave a través de la integración de todos los
elementos que forman parte de ella. En el mercado existen infinidad de
tarjetas controladoras para drones, algunas bastante buenas y que permiten
gran integración de sensores y elementos adicionales para dotar a la
aeronave de mayores funcionalidades sin requerir una nueva tarjeta. La
verdad están bastante bien, pero, como es de suponer, con estas
características vienen asociados costos mayores.
Para este proyecto no utilizaremos una tarjeta de control convencional. En
su lugar haremos algo más interesante: utilizaremos una placa Arduino
adaptada como controlador, en la cual nosotros mismos programaremos
nuestro propio código para controlar el dron y nos aseguraremos de realizar
el acondicionamiento necesario de las señales de alimentación, entrada
(sensores) y salida (control de los motores).
Pero, ¿qué es Arduino? Probablemente la mayoría de los lectores ya
conocen esta popular tarjeta, pero para aquellos que no, de manera
resumida puede describirse como un sistema que acepta información en
forma de señal de entrada, desarrolla ciertas operaciones sobre ésta y
luego produce señales de salida. Es decir, es un sistema de desarrollo de
hardware libre, basado en un microcontrolador (usualmente Atmel) con el
cual se pueden hacer miles de proyectos electrónicos, de diferentes grados
de complejidad. Desde luego, existen diferentes versiones de Arduino, que
utilizan microcontroladores con diferentes capacidades de procesamiento y
velocidades, así como con más o menos opciones de entradas y salidas,
tanto analógicas como digitales. El lector es libre de escoger la versión de
su preferencia; sin embargo acá se utilizará como base el Arduino Uno, ya
que es probablemente la versión más popular de Arduino y por tanto fácil de
conseguir, su precio es bastante accesible y tiene una capacidad de
procesamiento así como de entradas y salidas adecuadas para el proyecto
que realizaremos.
¿Por qué hemos decidido usar Arduino en vez de una tarjeta de control
específica para drones? Aparte del factor costo, considero que el mayor
nivel con el que se puede asimilar el funcionamiento de un dron es a través
de un conocimiento real de cómo opera cada uno de sus componentes, lo
cual lo podemos obtener precisamente con el uso de esta herramienta,
donde para desarrollar nuestro código debemos conocer a fondo las
particularidades de cada elemento, a un grado tal que posiblemente no
lograríamos si solo usáramos una tarjeta pre-fabricada para la aeronave tipo
"plug-and-play". Y por esta razón, el proyecto es más desafiante y a la vez
divertido, y mil veces más gratificante cuando veamos el resultado final de
nuestro trabajo. En todo caso en esta página ofreceremos diferentes niveles
de detalle en las explicaciones, para que el lector pueda sumergirse a
profundidad en el proyecto o no según el grado que le convenga.
Fig. 7 - Arduino
como tarjeta de control
Sensor inercial
Un dron puede contar con una gran variedad de sensores según sus
prestaciones, pero hay uno fundamental que todos, incluso los más simples,
deben tener. Se trata del sensor de medición inercial, o IMU (Inertial
Measurement Unit), dispositivo electrónico que mide e informa acerca de la
velocidad, orientación y fuerzas gravitacionales del aparato, usando una
combinación de sensores inerciales. El tipo de sensores que contiene una
IMU puede variar, pero en general el término IMU es usado ampliamente
para referirse a una caja que contiene tres acelerómetros y tres
giroscopios. Los acelerómetros, que miden la aceleración inercial, está
colocados de tal forma que sus ejes de medición son ortogonales entre sí.
Los tres giroscopios están colocados en un patrón ortogonal similar,
midiendo la velocidad angular en referencia a un sistema de coordenadas
seleccionado arbitrariamiente.
El tipo de IMU a utilizar variará de costo conforme sus sensores. Por
ejemplo, aparte de los mencionados, algunos también incluyen
magnetómetros, uno por cada eje, con los cuales se mide la orientación
magnética. Para propósitos de este proyecto, la IMU estándar (3 giroscopios
y 3 acelerómetros) nos sirve perfectamente, así que es la que usaremos. Un
modelo muy conocido y de bajo costo es la MPU-6050 (ver figura 8) y por
tanto será el modelo a usar en este proyecto.
Fig. 8 - Unidad de
medición inercial
Módulo de comunicación
Para controlar el dron, como es de suponer, necesitamos un sistema de
comunicaciones a través del cual enviar los comandos al aparato. Tal
sistema de comunicaciones contará con dos elementos: el transmisor,
desde donde el usuario envía los comandos, y el receptor que va en la
aeronave. De manera simple, el transmisor lee los comandos transmitidos
con las palancas y botones que el usuario manipula y envía las señales de
manera inalámbrica al receptor de forma aparentemente instantánea. El
receptor en el dron recibe esta información y la transmite a su vez al
módulo de control, el cual procesará estas señales y moverá la aeronave de
acuerdo a ellas.
En general se usarán ondas de radio para esta comunicación, en la banda de
2.4 GHz. El sistema contará al menos con cuatro canales diferentes, uno por
cada comando de las palancas (elevación, cabeceo o "pitch", alabeo o "roll"
y guiñada o "yaw"), pudiendo incluir más canales para funcionalidades
adicionales. El rango, o distancia de operación entre transmisor y receptor,
suele ir desde unos cientos de metros hasta un kilómetro, variando en
función de la potencia del transmisor, la sensibilidad del receptor y la
calidad de las antenas en ambos extremos.
Es posible comprar transmisor y receptor por separado, teniendo en cuenta
que el protocolo de comunicación que usen ambos sea el mismo para
garantizar su compatibilidad. Sin embargo, se recomienda inicialmente
adquirir el conjunto completo y con base en la experiencia, posteriormente
ensayar otras opciones de combinaciones si así se considera. Existen gran
variedad de opciones para el sistema de comunicación, pero así se utilice la
opción más simple, este componente suele ser uno de los más costosos de
la aeronave, por lo cual acá trabajaremos con la opción más sencilla.
Fig. 9 - Módulo de
comunicación
Batería
Desde luego, todos los componentes electrónicos que hemos mencionado
requieren ser alimentados desde alguna parte. Ese es el papel de la batería,
la cual debe contar con la energía suficiente para alimentar todos los
componentes y aún así ser lo más compacta posible. De todos los tipos de
batería que existen, para nuestra aplicación las baterías que se han
popularizado son las de polímero de litio o LiPo, que ofrecen una
relativamente alta densidad de energía y eficiencia en comparación con
otros tipos de baterías.
Hay dos factores de importancia al seleccionar la batería. En primera
instancia, la corriente que puede suministrar, tanto en capacidad nominal
como su valor máximo. Para ello, las baterías son denominadas con unas
cifras, por ejemplo 5100mAh - 10C. En este caso, el primer número indica la
capacidad nominal de corriente de la batería, en este caso 5100
miliamperios-hora (o 5.1 Ah). El segundo número es el valor de descarga, y
permite obtener el máximo valor de corriente suministrada al multiplicarlo
por la capacidad de la batería. En este caso, al multiplicar 5.1 por 10
tenemos 51 amperios, que puede entregar la batería en operación máxima.
Teniendo en cuenta el consumo de los motores (principalmente) y del resto
de la electrónica en general se sabe qué valor de corriente nominal y
máxima se requieren. Evidentemente, al seleccionar una batería con los
valores más altos posibles, esta será más pesada y costosa, por lo que
conviene evaluar las condiciones de operación y seleccionar una batería
apropiada sin excederse.
El otro criterio importante es la tensión (el voltaje) de operación de la
batería. Estas baterías vienen en paquetes de celdas (usualmente de 3.7 V),
siendo común usar baterías 2S o 3S (de dos o tres celdas), lo que sería
equivalente a 7.4 V y 11.1 V respectivamente. De nuevo, a más tensión
nominal, más potencia puede ser entregada, pero más peso y costo.
Usualmente un buen criterio para decidir el número de celdas viene dado
por el fabricante de los motores, que suelen entregar tablas experimentales
donde recomiendan el tipo de batería a usar en función de la combinación
motor - hélices que se vaya a usar.
Fig. 10 - Batería de
polímero de litio
Tarjeta de distribución
Todos los elementos mencionados reciben su alimentación de la batería. Sin
embargo, aunque técnicamente es posible, no es nada práctico ni estético
conectar cables de la batería a cada uno de los componentes. Por eso es
necesario considerar algún elemento que permita distribuir la alimentación
de una manera más ordenada. Es acá donde aparece la necesidad de una
tarjeta de distribución como la que se observa en la figura 10, en la cual la
batería solo se conecta a un punto (en este caso los cables que salen hacia
arriba) y existen puntos de conexión para cada uno de los pares motor -
variador. Solo se consideran estos elementos dado que son los más
demandantes en términos de corriente (por ello los cables son tan gruesos)
y además sólo ellos pueden recibir alimentación directa de la batería. Se
asume que los demás elementos, como la tarjeta de control, los sensores y
el sistema de comunicación, reciben su alimentación de otra parte,
usualmente el BEC de alguno de los variadores.
Sin embargo, este elemento no siempre es necesario. Recordemos que
cuando hablamos del marco, mencionamos que algunos incluyen rutas de
distribución embebidas dentro de su misma estructura, como es el caso de
las rutas doradas en el marco mostrado en la foto 2. En consecuencia, el
uso de esta tarjeta distribuidora puede ahorrarse bajo esta circunstancia.
Fig. 11 - Tarjeta de
distribución
Materiales varios
Aparte de los anteriores, que son propiamente componentes del dron,
requerimos algunos materiales e instrumentos adicionales para su
construcción, para la integración de sus componentes y para las
respectivas pruebas. He acá una lista, no necesariamente exhaustiva, de
algunos elementos que llegaremos a necesitar en determinado momento de
este proceso:
Multímetro: Útil para verificar continuidad al realizar las conexiones,
para medir voltajes y corrientes en el proceso.
Cautín y soldadura de estaño: Serán requeridos precisamente para
soldar algunas conexiones entre componentes, como pueden ser los
motores, los ESCs, los conectores de la batería y todo el cableado a
nuestro marco o tarjeta de distribución.
Cables y jumpers: Indispensables para las conexiones de los
componentes electrónicos al Arduino.
Protoboard: No es indispensable, pero puede ser útil para la prueba
individual de algunos componentes, como el caso de la IMU.
Resistencias: Requeriremos algunas, específicamente para la
medición del nivel de la batería y para limitar la corriente al LED.
LED: Proveerá una indicación visual del estado de nuestro dron.
Diodo: Lo usaremos para aislar el suministro de alimentación de la
batería de otras fuentes de alimentación eventuales, como el puerto
USB del computador durante las pruebas y programación o el BEC de
los ESCs.
CONSTRUCCIÓN
Sin más preámbulos, vamos a la guía paso a paso para la construcción de
nuestro cuadracóptero.
Fig. 1 - El gratificante final del proceso
Paso 1: Revisión de información y obtención de materiales
Aunque no es estrictamente necesario, recomiendo altamente leer un poco
sobre los fundamentos de vuelo del dron. Para ello el lector puede leer la
página de FUNDAMENTOS como un pequeño abrebocas para familiarizarse
con los conceptos básicos.
Y evidentemente, previo a comenzar el proceso de construcción, es
necesario reunir todos los materiales que vamos a requerir. Por ello, si el
estimado lector aún no lo ha hecho, es necesario visitar la página
de MATERIALES para conocer los elementos que se necesitarán, entender
la importancia y el funcionamiento de cada uno y conocer los modelos
recomendados y los sitios donde pueden conseguirlos.
Mira acá el video correspondiente a este paso del tutorial.
Paso 2: Montaje del soporte
Inicialmente debemos preparar el marco que soportará la estructura de
nuestro dron. Asumiendo que se haya elegido el marco F330 o F450, este no
vendrá ensamblado, por lo que debemos proceder con su montaje utilizando
los tornillos y la llave Bristol provistos como parte del kit (aunque a veces la
llave no está incluida, por lo que hará falta conseguirla por nuestra cuenta.)
En esta etapa es importante definir la distribución de los componentes en el
marco. Recomiendo dejar el nivel inferior exclusivamente para la batería. En
el nivel superior la distribución dependerá de la elección del lector sobre si
utilizar el "shield" para el Arduino o no. En caso de no usarlo, se requerirá
adaptar un tercer nivel para el marco, dejando el segundo nivel para la IMU
y el receptor de comunicaciones y el tercer nivel para el Arduino. Con el
"shield" esto no será necesario, ya que este cuenta con las conexiones
necesarias para cada elemento.
Fig. 2 - Marco después de su ensamblaje
Paso 3: Montaje de los motores
Una vez el marco esté listo, podemos montar los cuatro motores en cada
uno de los extremos. Los huecos para los tornillos en el marco y los motores
nos indicarán con facilidad dónde deben ser montados. Algunas personas
ensamblan primero las hélices a los motores antes de ponerlos en el marco;
yo recomiendo primero montar los motores solos para hacer unas pruebas
preliminares en vacío cuando la electrónica esté montada, ya que hacerlo
con las hélices puestas desde el comienzo puede ser peligroso.
Podemos aprovechar para ir soldando algunos componentes que
requeriremos luego. Por ejemplo, el conector de la batería e incluso los
variadores en cuanto a sus cables de alimentación. Podemos verificar que
las conexiones sean correctas con la ayuda de un multímetro.
Fig. 3 - Montaje de un motor en
el marco
Mira acá el video correspondiente a los pasos 2 y 3 del tutorial.
Paso 4: Preparación del Arduino
Vamos a dejar por el momento la parte mecánica para entrar de lleno en la
electrónica y comenzar a construir el algoritmo que permitirá controlar a
nuestra aeronave. Para ello es tiempo de comenzar a trabajar con el cerebro
del dron, la tarjeta Arduino, que funcionará como controlador del aparato.
Al adquirir normalmente una tarjeta Arduino, cualquiera que sea su modelo
(recordemos que en este proyecto usaremos un Arduino Uno, aunque es
posible trabajar concualquier versión, incluso más pequeña como un Nano o
más grande como un Mega) usualmente nos entregarán la tarjeta
acompañada de un cable USB para su programación desde un PC.
Requerimos entonces descargar el programa necesario para esto.
Afortunadamente, al ser Arduino una plataforma de hardware libre, cuenta a
su vez con software gratuito para trabajar con él. El entorno de desarrollo
integrado (IDE) de Arduino es una aplicación multiplataforma que se utiliza
para escribir y cargar programas en la placa, disponible directamente desde
la página de Arduino (ver enlace). Recomiendo encarecidamente leer y
aprovechar los recursos disponibles en esa misma página en cuanto a
literatura sobre Arduino y el lenguaje de programación, así como los
tutoriales ofrecidos para sumergirse de lleno en esta magnífica plataforma.
Fig. 4 - Programando Arduino a través del IDE
Fig. 4.1 - Diagrama de bloques
4.1. Diseño conceptual
Como al hacer cualquier programa, antes de meternos directamente con el
código, es necesario plasmar sobre el papel una conceptualización de lo
que se va hacer. ¿Cuál es el propósito de nuestro programa? ¿Cuáles son las
entradas disponibles y las salidas deseadas? ¿Cuál es el orden más
apropiado para seguir en nuestro algortimo para resolver nuestro problema?
Con esto en mente, debemos plasmar un bosquejo inicial estilo diagrama de
bloques, con base en los elementos que conformarán nuestro dron. La figura
4.1 nos presenta este diagrama, teniendo como elemento central la tarjeta
de control (la placa Arduino) en relación a los demás componentes. Aquellos
relacionados con flechas azules representan entradas al controlador; las
flechas verdes son salidas.
Como bosquejo inicial, la figura anterior nos sirve para darnos una idea de la
relación entre los componentes de la aeronave. SIn embargo, como
siguiente paso es necesario refinar un poco más este diagrama incluyendo
información clave que nos permita dimensionar adecuadamente nuestra
arquitectura de control y por ende nuestro código. Para ello necesitamos
dos consideraciones adicionales: tener en cuenta los tipos y cantidades de
señales manejados por cada elemento, y pensar también si requerimos
algún otro tipo de señales adicionales a las ya mostradas. Veamos cada
punto en detalle:
1. Hemos definido las relaciones entre los componentes y el controlador
(Arduino) como de entrada y salida. Pero, ¿sí es así? ¿Qué tipo de
entradas y salidas serían? ¿Y cuántas cantidades de estas señales
deben considerarse, con miras a saber cuántas conexiones
requerimos desde cada componente hasta el Arduino? Analicemos
cada componente:
o IMU: El sensor inercial que vamos a utilizar se comunica con el
exterior a través de un protocolo digital llamado I 2C. Hemos
considerado este elemento como "entrada" para nuestro
Arduino, pero en realidad la comunicación por este protocolo es
bidireccional, pues el sensor envía la información como
respuesta a una petición del Arduino. Hemos de incluir esta
anotación en el diagrama, y a nivel de hardware tener en cuenta
que el Arduino que utilicemos cuente con pines para
comunicación I2C. Usualmente se requieren cuatro pines: dos
para alimentar el sensor (+3.3V y GND) y dos propiamente para
la comunicación (SCL y SDA).
o Variadores / Motores: Son cuatro, así que es natural concluir
que requerimos cuatro salidas. La señal enviada a estos
elementos es de tipo PWM (Pulse Width Modulation o
Modulación por Ancho de Pulso), la cual puede ser considerada
como un híbrido entre analógica y digital. Arduino provee varios
pines disponibles para este tipo de salidas, así que hemos de
reservar cuatro de ellos para nuestra aplicación.
o Receptor de comunicaciones: Este elemento recopila las
comunicaciones inalámbricas y las transmite a través de
señales de PWM. Sin embargo, desde el punto de vista de
nuestro Arduino, este las recibe como señales digitales de
entrada (las llamaremos DI por Digital Input en el diagrama).
Por tanto, requerimos cuatro pines de este tipo para recibir
estas señales (elevation, roll, pitch, yaw).
2. ¿Necesitaremos considerar algún elemento más (y con ello más
señales en nuestro Arduino)? Podemos y es recomendado incluir
algunos elementos secundarios sencillos para hacer nuestro dron
más funcional. Para este proyecto recomiendo incluir estos
elementos:
o LED de señalización: Una sencilla indicación luminosa para
observar si nuestro dron está activo o no en determinados
momentos del vuelo y para mostrar otras enventualidades (no
hay señal del transmisor, la batería esta baja, etc.).
Requeriremos una salida digital para este propósito (DO - Digital
Output).
o Nivel de la batería: Para saber si podemos seguir volando o
requerimos recargar la batería es útil leer su nivel de tensión.
Para ello destinaremos una entrada analógica del Arduino (AI -
Analog Input).
Fig. 4.2 - Diagrama de bloques más detallado
Al proceso anterior lo llamaremos "conceptualización de hardware". En un
nivel básico hemos considerado cómo se han de integrar los elementos de
nuestro dron con la tarjeta de control en cuanto al tipo y cantidades de
señales. Esto con miras a saber cómo será la conexión física entre los
elementos y conocer de antemano las consideraciones respectivas en
cuanto a cableado y espacio requerido por estos elementos.
Ahora es necesario proceder con la "conceptualización de software", esto
es, considerar a nivel funcional cómo va a operar el dron con miras a
desarrollar el programa que controlará el aparato. Como buenos
diseñadores, apelaremos nuevamente al uso de un diagrama, esta vez será
un diagrama de flujo que de manera breve pero concisa ilustre el proceso
secuencial que seguirá nuestro programa de control. El diagrama propuesto
se presenta en la figura 4.3.
En principio notamos que el diagrama esta dividido en dos fases: una que
llamaremos "inicial" y otra "cíclica". Esto se debe a que la programación del
Arduino (o en general de cualquier solución basada en microcontrolador)
debe contar con estas dos partes en el programa (en Arduino son
denominadas "setup" y "loop"). La primera, que solo se ejecuta una vez,
sirve para inicializar el programa en cuanto a las entradas/salidas y tipos de
comunicación que se usarán, así como para crear y cargar variables
globales y en general para ejecutar procesos que solo se requieran una vez
al inicio del programa. La otra fase, como su nombre lo indica, es cíclica y
se repite de manera "infinita" y es básicamente donde va toda la parte
operativa del programa: lectura de variables o entradas, algoritmo donde se
procesan dichas señales y generación de algún tipo de salida.
En nuestra fase inicial asignaremos las entradas y salidas que requerimos
utilizar durante el resto del programa. Inicializaremos variables globales que
contendrán información importante que se requerirá durante toda la
ejecución del programa. También inicializaremos los protocolos de
comunicación que se requerirán (por ejemplo, el I 2C). Finalmente,
pondremos a punto la IMU para su funcionamiento con base a la información
suministrada por su fabricante.
En cada fase cíclica haremos una lectura de las señales de la IMU
(giroscopios y acelerómetros) y procesaremos esta información para
convertirla en la velocidad angular y los ángulos de inclinación que
realmente necesitamos. También debemos leer las señales recibidas del
control remoto para saber hacia dónde debe moverse el dron en función del
comando enviado por el usuario. Con toda esta información recopilada,
hemos de programar el algoritmo de control de actitud, para mantener
estable el dron mientras se desplaza en la dirección requerida. Siempre
debemos prever alguna falla (pérdida de comunicación, bajo nivel de la
batería, etc.) por lo que debemos tener esto en cuenta también dentro de
nuestro código. Finalmente, con todas estas consideraciones se generarán
las señales de control (aquellas que se enviarán a los variadores) y
finalmente serán efectivamente enviadas, para luego repetir el proceso una
y otra vez (de manera REGULAR, es decir, a una tasa de tiempo constante).
Fig. 4.3 - Diagrama de flujo del programa de control
Paso 5: Integración y pruebas de los componentes
Antes de proceder a conectar todos los componentes y tratar de operar el
dron es preferible integrar los elementos uno por uno, hacer pruebas con
cada uno de ellos e ir escribiendo el programa completo de forma modular,
de forma que sea más ordenada y que nos permita identificar fallos en caso
de presentarse.
NOTA: Esta sección es recomendada para aquellos que quieran tener un
conocimiento más profundo y detallado de la operación del dron y sus
partes, y en ella iremos armando el código parte por parte. Sin embargo, el
lector que quiera simplemente construir y poner a volar la aeronave sin
preocuparse por los detalles de funcionamiento puede saltarse este paso.
Más adelante se podrá descargar el código completo para programar el
Arduino.
5.1. IMU
Hemos decidido trabajar con la IMU MPU-6050, la cual lleva tres
acelerómetros y tres giroscopios, uno por cada eje (X, Y y Z). Estos
dispositivos miden velocidad angular y aceleración en cada uno de esos
ejes. Sin embargo, nosotros requerimos obtener los ángulos de orientación
en cada momento, por lo la información obtenida de la IMU no puede usarse
directamente; se requieren algunos cálculos para obtener los datos que
necesitamos. El MPU-6050 opera con 3.3 voltios, aunque algunas versiones
llevan un regulador que permite conectarla a 5V. El Arduino provee salidas
de ambos niveles de tensión, así que la alimentación de la IMU no será un
problema.
Existe infinidad de recursos y tutoriales en internet sobre esta IMU y su
conexión con Arduino. Por lo pronto, recomiendo seguir este (ver tutorial),
bastante completo y claro, desde los fundamentos de la IMU hasta un
código de ejemplo para ver su funcionamiento. Igualmente se da una
introduciión al protocolo I2C, necesario para la comunicación entre el
Arduino y la IMU.
Fig. 5.1.1 - Integración de
la IMU MPU-6050
Una vez leída y asimilada la información sobre la IMU MPU-6050 y seguido el
tutorial, podemos, ahora sí, comenzar a escribir el código que usará nuestro
Arduino para controlar el dron. El código suministrado a continuación está
debidamente comentado, pero sin embargo haremos una descripción
general de las líneas que lo componen. Como recursos adicionales se
sugiere también revisar la hoja de datos (ver enlace) y la descripción de los
registros (ver enlace) del MPU-6050 para comprender algunas partes del
código en cuanto a la configuración previa de la IMU y la manera de acceder
a sus datos.
Como ya se explicó en el tutorial, inicialmente debe agregarse la librería
"Wire", que permite la comunicación del Arduino a través del protocolo I 2C.
También definimos una constante IMU_ADDRESS, que de acuerdo a las
especificaciones suministradas por el fabricante, es la dirección del MPU-
6050 a través del protocolo I2C. El '0x' antes del número indica que el valor
está escrito en formato hexadecimal. Definimos luego unas cuantas
variables globales que usaremos en los cálculos que haremos con las
lecturas de la IMU para obtener la información que realmente necesitamos.
Algunas variables son para procesar las lecturas directamente desde la
IMU, otras son para la operación de filtrado, que como se vio en el tutorial,
es necesaria para obtener una buena mezcla entre las lecturas ruidosas de
los acelerómetros y las lecturas a largo plazo inestables de los giroscopios.
En el "setup" inicializaremos la comunicación serial para poder ver la salida
de nuestros cálculos en pantalla, recordando que en el código final esto no
es necesario y deberá ser comentado, junto con todas las líneas
"Serial.print" que son solo para referencia en esta parte del proceso.
Iniciamos también "Wire" para activar el protocolo I 2C y luego invocaremos
una función escrita por nosotros (init_IMU, se explica más adelante) donde
se inicializa la IMU a través de un procedimiento de escritura en sus
registros indicado por el fabricante. Luego invocaremos otra función
definida por nosotros (calibrate) que nos permite calibrar la IMU
inicialmente. Finalmente, inicializaremos un "timer" en milisegundos, cuya
funcionalidad se verá más adelante.
En el "loop" comenzaremos por leer los datos "crudos" de la IMU a través de
otra función personalizada (read_IMU). Comenzamos por ajustar los datos
del acelerómetro con los "offset" encontrados en la calibración.
Posteriormente, obtenemos el dato en 'g' dividiendo por la sensitividad de
cada lectura según indicaciones del fabricante. Con la fórmula de la
arcotangente explicada en el tutorial, obtenemos los valores en radianes
para los ángulos de "roll" y "pitch" y finalmente los convertimos en grados.
Hacemos un proceso similar para los datos obtenidos del giroscopio, con
unas consideraciones adicionales. Primero, observamos un "dampening" o
amortiguamiento, que consiste en combinar la lectura anterior con la nueva
lectura para obtener un dato más estable en el tiempo. Luego, como el dato
obtenido es velocidad angular y requerimos el ángulo, debemos "integrar"
esta información (recordemos que la velocidad es la derivada de la posición,
por lo que para obtener posición a partir de velocidad se debe hacer la
operación inversa). Para integrar la velocidad, multiplicamos su valor por el
tiempo transcurrido desde la última lectura (por ello usamos el "timer") y
finalmente este valor se suma al valor actual del ángulo. Vemos que
acotamos las lecturas al rango entre -180° y 180°. Finalmente, se guardan
las lecturas de velocidad actuales para utilizar en la fase de "dampening"
del siguiente ciclo.
Los ángulos obtenidos con el giroscopio también deben ser corregidos en
caso de "transferencia" cuando hay un movimiento de "yaw" (ver la
explicación en este excelente VIDEO de Joop Brokking). Finalmente,
aplicamos un filtro complementario como el que se explica en el tutorial,
para obtener la mejor lectura posible con la cual trabajar.
Aparte de "setup" y "loop" que son procedimientos "por defecto", podemos
crear funciones o procedimientos propios que pueden invocarse desde
cualquier parte del programa. Hemos creado tres, comenzando por
init_IMU(), donde se inicializa la IMU MPU-6050 en función de las
indicaciones del fabricante. Vemos que hay tres partes importantes, en la
primera se activa la IMU enviando un cero al registro PWR_MGMT_1. Luego
se configura el rango (y con ello la sensitividad) del giroscopio escribiendo
en el registro GYRO_CONFIG. Igual se hace para el acelerómetro con el
registro ACCEL_CONFIG. Luego hacemos un chequeo para ver si la
comunicación está marchando bien, verificando que uno de los registros
donde acabamos de escribir tenga el valor esperado. Si hay algún error el
programa quedará en un bucle infinito, por lo que será la indicación para
revisar hardware y conexiones. En caso contrario, se hace una última
configuración en el registro CONFIG activando un filtro pasa-bajas para
obener lecturas aún más estables.
En read_IMU() hacemos una lectura de los datos del MPU-6050 de acuerdo al
protocolo I2C, leyendo 14 registros contiguos. Esto porque cada registro es
de 8 bits (o un byte) y la lectura de cada acelerómetro y giroscopio (por
cada uno de los 3 ejes) ocupa 16 bits, es decir, dos registros. Entonces
tenemos 6 bytes para los acelerómetros más 6 para los giroscopios más 2
bytes adicionales para una lectura de temperatura, o sea 14 bytes. Cada
lectura la asignamos a su variable global correspondiente.
En calibrate() hacemos cien lecturas de la IMU para obtener un buen
promedio de cada lectura. Si el dron está perfectamente nivelado y la IMU
fuera perfecta, deberíamos obtener ceros, pero evidentemente este no es el
caso. Obtendremos un valor de "offset" que debemos restar siempre dentro
del "loop" a las lecturas obtenidas. Adicionalmente, aprovechamos para
inicializar el filtro con los ángulos actuales promediados obtenidos de los
acelerómetros.
NOTA: Cuando corras este programa, es importante tomar nota de los offset
del acelerómetro, ya que debemos utilizar estos valores en el programa final
del dron.
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
// IMU - MPU6050
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Lectura de datos de la IMU MPU-6050
// Cálculo de ángulos de inclinación
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Incluimos algunas librerías adicionales que vamos a utilizar
#include <Wire.h> // Librería para protocolo I2C
// ALGUNAS DEFINICIONES
#define IMU_ADDRESS 0x68 //Direccion I2C de la IMU
// Variables IMU
int acc[3];
int gyro[3];
int temperature;
float rawX, rawY, rawZ;
float X, Y, Z;
float gyroX, gyroY, gyroZ;
float gx_rate, gy_rate, gz_rate;
float last_gx_rate, last_gy_rate, last_gz_rate;
float rollrad, pitchrad;
unsigned long mtime, looptime;
float angleAx, angleAy, angleAz;
float angleGx, angleGy, angleGz;
float aoffsetX, aoffsetY, aoffsetZ;
float goffsetX, goffsetY, goffsetZ;
float angleFx, angleFy;
// Variable solo para visualización, borrar en el algoritmo final
unsigned long showtime;
void setup()
{
// Inicio del puerto serial a 115200 baudios y mensaje de bienvenida
Serial.begin(115200);
Serial.println("Bienvenido, sistema iniciando...");
// Inicio de comunicación I2C
Wire.begin();
// Inicializamos la IMU
init_IMU();
// Un pequeño "delay" e iniciamos la calibración de la IMU
delay(1000);
Serial.println("Calibrando...");
Serial.println("Mantener la IMU quieta y en posición horizontal");
calibrate();
delay(500);
Serial.println("Calibración finalizada.");
mtime = millis(); // Inicializamos la variable
mtime con el valor actual en milisegundos (para uso del giroscopio)
showtime = 500; // Iniciamos esta variable en
500 ms
}
void loop()
{
// Leemos la IMU
read_IMU();
// Obtenemos ángulos de roll and pitch de lecturas del acelerómetro
rawX = acc[0] - aoffsetX;
rawY = acc[1] - aoffsetY;
rawZ = acc[2] - (4095 - aoffsetZ); // Debemos considerar la gravedad;
en este caso 1g es igual a 4095
// 1/4096 = 0.0002 (4096 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
X = rawX*0.0002;
Y = rawY*0.0002;
Z = rawZ*0.0002;
rollrad = atan(Y/sqrt(X*X+Z*Z)); // Ángulo en radianes
pitchrad = atan(X/sqrt(Y*Y+Z*Z)); // Ángulo en radianes
// 180/pi = 57.2958 (factor para convertir a grados)
angleAx = rollrad*57.2958; // Ángulo de roll en grados
angleAy = pitchrad*57.2958; // Ángulo de pitch en grados
// Código para giroscopio (roll, pitch, yaw)
looptime = (millis() - mtime);
mtime = millis();
gyroX = gyro[0] - goffsetX;
gyroY = gyro[1] - goffsetY;
gyroZ = gyro[2] - goffsetZ;
// 1/65.5 = 0.0153 (65.5 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
gx_rate = gyroX*0.0153;
gy_rate = gyroY*0.0153;
gz_rate = gyroZ*0.0153;
float gx1 = gx_rate;
float gy1 = gy_rate;
float gz1 = gz_rate;
// Filtrado inicial de las mediciones de velocidad angular usando una
proporción de la medida anterior y la actual
gx_rate = (0.7*last_gx_rate) + (0.3*gx_rate);
gy_rate = (0.7*last_gy_rate) + (0.3*gy_rate);
gz_rate = (0.7*last_gz_rate) + (0.3*gz_rate);
// Integramos para obtener los ángulos
angleGx = angleGx + (gx_rate * looptime)*0.001; // Convertir a segundos
(1/1000)
angleGy = angleGy - (gy_rate * looptime)*0.001; // Medición de pitch rate
está invertida
angleGz = angleGz - (gz_rate * looptime)*0.001; // Medición de yaw rate
está invertida
// Corrección de "yaw" para los ángulos obtenidos del giroscopio
// pi/180 = 0.0174 (para convertir a radianes, luego *0.001 para convertir a
segundos
angleGx -= angleGy * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de pitch a roll
angleGy += angleGx * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de roll a pitch
// Limitamos los ángulos al rango entre -180 y 180 grados
if (angleGx < -180) angleGx += 360;
if (angleGx > 180) angleGx -= 360;
if (angleGy < -180) angleGy += 360;
if (angleGy > 180) angleGy -= 360;
if (angleGz < 0) angleGz += 360;
if (angleGz > 360) angleGz -= 360;
// Guardar valores actuales para el próximo ciclo
last_gx_rate = gx_rate;
last_gy_rate = gy_rate;
last_gz_rate = gz_rate;
// Corrección de "yaw" para los ángulos obtenidos del giroscopio
// pi/180 = 0.0174 (para convertir a radianes, luego *0.001 para convertir a
segundos
angleFx -= angleFy * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de pitch a roll
angleFy += angleFx * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de roll a pitch
// Aplicar el Filtro Complementario a los ángulos originales
angleFx = 0.995*(angleFx + (gx_rate * looptime*0.001)) + 0.005*angleAx;
angleFy = 0.995*(angleFy - (gy_rate * looptime*0.001)) + 0.005*angleAy;
// Limitamos los ángulos al rango entre -180 y 180 grados
if (angleFx < -180) angleFx += 360;
if (angleFx > 180) angleFx -= 360;
if (angleFy < -180) angleFy += 360;
if (angleFy > 180) angleFy -= 360;
// Sección para visualización de las lecturas
if (millis() > showtime){
// Leemos por el puerto serial cada 500 ms
// Valores crudos
Serial.println("Valores crudos");
Serial.print("AcX: "); Serial.print(rawX); Serial.print("\t");
Serial.print(" AcY: "); Serial.print(rawY); Serial.print("\t");
Serial.print(" AcZ: "); Serial.println(rawZ);
Serial.print("GyX: "); Serial.print(gyroX); Serial.print("\t");
Serial.print(" GyY: "); Serial.print(gyroY); Serial.print("\t");
Serial.print(" GyZ: "); Serial.println(gyroZ);
Serial.println("");
// Valores finales
Serial.println("Valores calculados de ángulos");
Serial.print("Roll: "); Serial.print(angleFx); Serial.print("\t");
Serial.print("Pitch: "); Serial.println(angleFy);
Serial.println("Velocidad angular");
Serial.print("Eje x: "); Serial.print(gx_rate); Serial.print("\t");
Serial.print("Eje y: "); Serial.print(gy_rate); Serial.print("\t");
Serial.print("Eje z: "); Serial.println(gz_rate);
Serial.println("");
showtime += 500; // Incrementar variable en 500 ms
}
}
// ------------Funciones complementarias---------------
// Inicializar la IMU
void init_IMU() {
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x6B); //
Escribir al registro PWR_MGMT_1 (6B hex)
Wire.write(0x00); //
Escribir 00000000 para activar la IMU
Wire.endTransmission(); //
Finalizar la transmisión
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1B); //
Escribir al registro GYRO_CONFIG (1B hex)
Wire.write(0x08); //
Escribir 00001000 (Rango 500 °/s)
Wire.endTransmission(); //
Finalizar la transmisión
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1C); //
Escribir al registro ACCEL_CONFIG (1A hex)
Wire.write(0x10); //
Escribir 00010000 (Rango +/- 8g)
Wire.endTransmission(); //
Finalizar la transmisión
// Pequeña revisión para verificar los valores enviados
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1B); //
Leer registro 0x1B
Wire.endTransmission(); //
Finalizar la transmisión
Wire.requestFrom(IMU_ADDRESS, 1); //
Solicitar 1 byte
while(Wire.available() < 1); //
Esperar la recepción de la información
if(Wire.read() != 0x08){ //
Verificar que el valor es 0x08
while(1) delay(10); //
Quedarse en este "loop"
}
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1A); //
Escribir al registro CONFIG (1A hex)
Wire.write(0x03); //
Escribir 00000011 (Low Pass Filter to ~43Hz)
Wire.endTransmission(); //
Finalizar la transmisión
}
// Leer la IMU
void read_IMU(){
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x3B); //
Leer desde registro 3B
Wire.endTransmission(); //
Finalizar la transmisión
Wire.requestFrom(IMU_ADDRESS,14); //
Solicitar 14 bytes
while(Wire.available() < 14); //
Esperar recepción de la información
acc[0] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje x.
acc[1] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje y.
acc[2] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje z.
temperature = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte en la variable temperature.
gyro[0] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje x.
gyro[1] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje y.
gyro[2] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje z.
}
// Rutina de calibración
void calibrate() {
// Leemos cien datos de la IMU y obtenemos los respectivos promedios
for (int i = 0; i < 100; i++) {
read_IMU();
if (i == 0) {
aoffsetX = acc[0];
aoffsetY = acc[1];
aoffsetZ = acc[2];
goffsetX = gyro[0];
goffsetY = gyro[1];
goffsetZ = gyro[2];
}
if (i > 0) {
aoffsetX = (acc[0] + aoffsetX);
aoffsetY = (acc[1] + aoffsetY);
aoffsetZ = (acc[2] + aoffsetZ);
goffsetX = (gyro[0] + goffsetX);
goffsetY = (gyro[1] + goffsetY);
goffsetZ = (gyro[2] + goffsetZ);
}
}
aoffsetX = aoffsetX*0.01;
aoffsetY = aoffsetY*0.01;
aoffsetZ = aoffsetZ*0.01;
goffsetX = goffsetX*0.01;
goffsetY = goffsetY*0.01;
goffsetZ = goffsetZ*0.01;
// Los valores obtenidos son el "offset" inicial de los giroscopios y
acelerómetros
Serial.print("Los offset del GYRO son: ");
Serial.print(goffsetX);
Serial.print(", ");
Serial.print(goffsetY);
Serial.print(", ");
Serial.println(goffsetZ);
Serial.print("Los offset del ACC son: ");
Serial.print(aoffsetX);
Serial.print(", ");
Serial.print(aoffsetY);
Serial.print(", ");
Serial.println(aoffsetZ);
// Esta parte es para dar un valor inicial a los ángulos calculados con el
giroscopio y el filtro, a partir del acelerómetro
// Volvemos a leer la IMU para obtener datos promedio del acelerómetro
float acc_x = 0, acc_y = 0, acc_z = 0;
for (int i = 0; i < 10; i++) {
read_IMU();
acc_x += acc[0];
acc_y += acc[1];
acc_z += acc[2];
}
// Promedio de 10 lecturas
acc_x *= 0.1;
acc_y *= 0.1;
acc_z *= 0.1;
rawX = acc_x - aoffsetX;
rawY = acc_y - aoffsetY;
rawZ = acc_z - (4095 - aoffsetZ); // Debemos considerar la gravedad;
en este caso 1g es igual a 4095
// 1/4096 = 0.0002 (4096 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
X = rawX*0.0002;
Y = rawY*0.0002;
Z = rawZ*0.0002;
rollrad = atan(Y/sqrt(X*X+Z*Z)); // Ángulo en radianes
pitchrad = atan(X/sqrt(Y*Y+Z*Z)); // Ángulo en radianes
// 180/pi = 57.2958 (factor para convertir a grados)
angleAx = rollrad*57.2958; // Ángulo de roll en grados
angleAy = pitchrad*57.2958; // Ángulo de pitch en grados
// Inicializamos los filtros con estos ángulos obtenidos
angleGx = angleAx;
angleGy = angleAy;
angleFx = angleAx;
angleFy = angleAy;
}
5.2. Módulo de comunicaciones
Como describimos en la sección de "Materiales" nuestro sistema de
comunicaciones contará con dos elementos: el transmisor, desde donde el
usuario envía los comandos, y el receptor que va en la aeronave. De manera
simple, el transmisor lee los comandos transmitidos con las palancas y
botones que el usuario manipula y envía las señales de manera inalámbrica
al receptor de forma aparentemente instantánea. El receptor en el dron
recibe esta información y la transmite a su vez al módulo de control, el cual
procesará estas señales y moverá la aeronave de acuerdo a ellas.
En general se usarán ondas de radio para esta comunicación, en la banda de
2.4 GHz. El sistema contará al menos con cuatro canales diferentes, uno por
cada comando de las palancas (potencia, cabeceo o "pitch", alabeo o "roll"
y guiñada o "yaw"), pudiendo incluir más canales para funcionalidades
adicionales. En el receptor estas señales tendrán, usualmente, los nombres
de las superficies de control que manejarían cada tipo de movimiento en un
avión. Es decir, el cabeceo en un avión sería controlado por el elevador
(elevator), el alabeo por los alerones (ailerons), la guiñada por el timón de
dirección (rudder) y la potencia por el suministro de combustible (throttle).
Así pues, estos serán los nombres de los pines que encontraremos en el
receptor.
Retomando las características del sistema de comunicaciones, podemos
mencionar que el rango, o distancia de operación entre transmisor y
receptor, suele ir desde unos cientos de metros hasta un kilómetro,
variando en función de la potencia del transmisor, la sensibilidad del
receptor y la calidad de las antenas en ambos extremos.
El proceso desde que las señales son leídas en el control remoto hasta su
interpretación en la tarjeta de control consiste de varias etapas, pero de
una forma muy general podemos ver en la figura 5.2.1 cómo la señal de RF
generada varía su período (o su frecuencia, recordemos que una es el
inverso de la otra) en función de la magnitud del comando enviado por el
usuario.
Sin embargo, para propósitos de la programación de nuestro controlador, lo
que más nos interesa es lo que sucede en el receptor. La señal es recogida
por este elemento, el cual genera a su vez una señal de salida por cada uno
de los canales. El estándar de estas señales, tal cual como es
implementado en gran parte de los dispositivos en el mercado, consiste en
un pulso que varía su período entre 1000 y 2000 microsegundos, como se ve
en la figura 5.2.2. En otras palabras, recibimos una señal de modulación de
ancho de pulso o PWM. Así pues, nuestra misión es leer apropiadamente
cuál es el ancho del pulso que estamos recibiendo por cada canal y traducir
ese valor en el movimiento deseado. ¿Cómo haremos tal cosa? A
continuación lo explicaremos.
Fig. 5.2.1. - Esquema de comunicación
Fig. 5.2.2 - Señal producida por el receptor
En este proceso debemos tener en cuenta dos conceptos relacionados con
Arduino: el uso de contadores o "timers" y las interrupciones. De manera
sencilla, un "timer" es un elemento que contabiliza el tiempo transcurrido
desde que se energizó el Arduino hasta el momento "actual". Ya hemos
hecho uso de uno de ellos en la parte anterior al integrar la IMU; sin
embargo, valga decir que puede haber "timers" en milisegundos o en
microsegundos. Para esta parte usaremos del segundo tipo, pues nos darán
una medida más exacta del pulso que estamos leyendo del receptor.
En Arduino un programa corre de manera secuencial. Sin embargo, si
queremos estar atentos a algún evento que suceda independientemente de
la secuencia de nuestro programa y reaccionar al mismo, debemos utilizar
las interrupciones. Como su nombre lo indica, consisten en una herramienta
que permite "interrumpir" temporalmente la ejecución del programa
principal para ejecutar algún sub-proceso en respuesta a algún evento.
Recomiendo revisar algún tutorial sobre el tema, como este (ver enlace)
para una mayor comprensión sobre su uso.
Una vez leída y asimilada la información sobre el funcionamiento del
sistema de comunicaciones, pasamos a escribir el código que usará nuestro
Arduino para controlar el dron involucrando este sistema. El código
suministrado a continuación está debidamente comentado, pero sin
embargo haremos una descripción general de las líneas que lo componen.
Comenzamos definiendo unas cuantas variables globales que usaremos para
llevar la cuenta del valor en microsegundos del período de cada pulso
recibido del receptor por parte del Arduino. Entre estas variables
destacamos la que hemos llamado receiver_input[4], que es básicamente un
arreglo de 4 campos en cada uno de los cuales guardaremos el valor
respectivo del comando de elevación, cabeceo, alabeo y guiñada.
En el "setup" iniciamos configurando unas interrupciones necesarias para
leer las señales enviadas por el receptor. Cuando trabajamos con Arduino
UNO, podemos usar dos pines para interrupciones externas a través del
lenguaje Arduino. Sin embargo, como ya hemos dicho, en este caso se
requieren cuatro pines, uno por cada salida del receptor. En ese caso,
debemos programar a un nivel más "bajo" para poder acceder a un número
mayor de interrupciones externas. Con "nivel más bajo" me refiero a
programar directamente los registros del microcontrolador, lo cual también
está permitido a través de la interfaz de Arduino. Para ello debemos
consultar la hoja de datos del microcontrolador sobre el cual está basado el
Arduino UNO, que es el AtMega328P (ver enlace). Al revisar el apartado
sobre interrupciones, allí encontraremos qué registros debemos modificar
dependiendo de los pines que queramos utilizar. En este proceso usaremos
los pines 4, 5, 6 y 7 del Arduino, que corresponden a los campos PCINT20,
PCINT21, PCINT22 y PCINT23 del registro PCMSK2 del microcontrolador
AtMega328P. A su vez, para activar el registro PCMSK2 debemos activar el
campo PCIE2 en el registro PCICR. Todo este proceso que suena
aparentemente complicado, en realidad es bastante simple y se resume en
las cinco líneas de código que se muestran abajo correspondientes a este
párrafo (líneas 21 a 25). Una explicación más detallada puede encontrarse
en un tutorial sobre el tema, como este (ver enlace).
En el "loop" comenzaremos por leer los valores recibidos de cada pin
conectado al receptor y almacenarlos en variables apropiadas. Pero, ¿de
dónde han salido estos valores? En efecto, el arreglo "receiver_input[4]"
está siendo modificado en otra parte. Como dijimos anteriormente, esta
variable es afectada por la interrupción en cada uno de los pines que hemos
configurado para tal efecto. Las interrupciones son manejadas por rutinas
especiales, aparte del "setup" y del "loop" que ya conocemos. Esta rutina
vendrá más adelante en el código. Por lo pronto, para efectos de esta parte,
simplemente mostraremos en el monitor serial de Arduino los valores leídos
de cada variable.
La rutina especial para las interrupciones que hemos decidido utilizar se
llama ISR(PCINT2_vect). ISR viene de "Interruption Service Rutine", de las
cuales existen varias asociadas a diferentes vectores, conforme se explica
en los tutoriales ya referidos. En este caso debemos utilizar el vector
PCINT2_vect que es el que corresponde a una interrupción por cambio en
cualquiera de los pines asociados al registro PCINT2, lo cual es el caso de
los cuatro pines que hemos configurado. Ahora bien, esta rutina se ejecuta
cuando hay un cambio de valor alto a bajo o viceversa en CUALQUIERA de
los pines, razón por la cual lo primordial en esta rutina es establecer cuál
pin produjo la interrupción. Veamos el proceso para el canal 1, tras lo cual
el procedimiento es similar para todos los demás. Podemos ver que
comenzamos leyendo el valor actual de tiempo transcurrido en
microsegundos a través de la función micros(). Luego debemos revisar qué
canal produjo la interrupción. Para ello primero debemos echar un vistazo
de nuevo a la hoja de datos del AtMega328P (o mejor, a un diagrama
"pinout" entre Arduino UNO y microcontrolador como este, donde
verificamos que los pines 7 a 4 del Arduino corresponden a los pines PD7 a
PD4 del micro (la D hace referencia a que estos pines pertenecen al puerto
D) y por consiguiente, si se quiere leer el valor actual de entrada en esos
pines, debemos consultar los campos 7 a 4 del registro PIND.
Al verificar "if(PIND & B10000000)" estamos haciendo una operación bit a
bit, dónde el resultado será 1 (o "true") si y sólo sí el primer campo de PIND,
que corresponde a PD7, es ALTO actualmente. Si ese es el caso, como
hemos guardado el valor anterior de este pin, verificamos si hubo un cambio
de BAJO a ALTO (o de 0 a 1), guardamos el nuevo valor del pin y también el
valor actual en microsegundos, o en otras palabras, empezamos a correr
una variable "timer". En caso de que el valor del pin sea BAJO, verificamos
si se produjo un cambio de ALTO a BAJO (de 1 a 0), recordamos el estado
para la próxima interrupción y hacemos una resta entre el tiempo actual y el
valor de la variable "timer" que guardamos cuando se produjo al cambio
inicial de 0 a 1. En otras palabras, estamos contando en microsegundos el
valor de un pulso ALTO como el de la figura 5.2.2 que es la señal que
esperamos del receptor. El procedimiento es igual para cada uno de los
demás canales.
El resultado obtenido al leer estas señales debería variar siempre entre
1000 y 2000. Además, verificando cuál es la variable que cambia podemos
saber cómo están configuradas las palancas de nuestro control, es decir,
cuál es la elevación, cuál el cabeceo y así.
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
// Comunicaciones: Transmisor + Receptor
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Lectura de los pulsos recibidos del sistema transmisor / receptor
// Decodificación de señales de pulsos a números enteros
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Variables control remoto
volatile int rollref, pitchref, yawref, href;
byte last_channel_1, last_channel_2, last_channel_3, last_channel_4;
int receiver_input[4];
unsigned long timer_1, timer_2, timer_3, timer_4, current_time;
void setup()
{
// Inicio del puerto serial a 115200 baudios y mensaje de bienvenida
Serial.begin(115200);
Serial.println("Bienvenido, sistema iniciando...");
// Configuramos las interrupciones para recibir los comandos remotos
PCICR |= (1 << PCIE2); // PCIE2
activado para habilitar PCMSK2 scan.
PCMSK2 |= (1 << PCINT23); // PCINT23
(D7) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT22); // PCINT22
(D6) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT21); // PCINT21
(D5) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT20); // PCINT20
(D4) activado para disparar una interrupción si hay cambio de estado.
Serial.println("Interrupciones configuradas.");
}
void loop()
{
// Leemos las entradas del transmisor remoto
href = receiver_input[0];
rollref = receiver_input[1];
pitchref = receiver_input[2];
yawref = receiver_input[3];
// Vemos las lecturas de las señales recibidas
Serial.println("Señales recibidas: ");
Serial.print("Throttle: "); Serial.print(href); Serial.print("\t");
Serial.print("Roll: "); Serial.print(rollref); Serial.print("\t");
Serial.print("Pitch: "); Serial.print(pitchref); Serial.print("\t");
Serial.print("Yaw: "); Serial.println(yawref);
// Un "delay" para facilitar la lectura, pero que debe eliminarse en operación
normal.
delay(500);
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// RUTINA DE INTERRUPCIÓN
// Esta rutina es invocada cada vez que alguno de los pines 7, 6, 5 o 4 cambia
de estado, para leer las señales del receptor.
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
ISR(PCINT2_vect){
current_time = micros();
//Channel 1=========================================
if(PIND & B10000000){ //
¿El pin 7 está ALTO?
if(last_channel_1 == 0){ //
Si cambió de 0 a 1...
last_channel_1 = 1; //
Guardar estado actual.
timer_1 = current_time; //
Guardar tiempo actual en timer_1.
}
}
else if(last_channel_1 == 1){ //
Si el pin 7 está en BAJO y pasó de 1 a 0.
last_channel_1 = 0; //
Guardar estado actual.
receiver_input[0] = current_time - timer_1; //
El valor de este canal es current_time - timer_1.
}
//Channel 2=========================================
if(PIND & B01000000 ){ //
¿El pin 6 está ALTO?
if(last_channel_2 == 0){ //
Si cambió de 0 a 1...
last_channel_2 = 1; //
Guardar estado actual.
timer_2 = current_time; //
Guardar tiempo actual en timer_2.
}
}
else if(last_channel_2 == 1){ //
Si el pin 6 está en BAJO y pasó de 1 a 0.
last_channel_2 = 0; //
Guardar estado actual.
receiver_input[1] = current_time - timer_2; //
El valor de este canal es current_time - timer_2.
}
//Channel 3=========================================
if(PIND & B00100000 ){ //
¿El pin 5 está ALTO?
if(last_channel_3 == 0){ //
Si cambió de 0 a 1...
last_channel_3 = 1; //
Guardar estado actual.
timer_3 = current_time; //
Guardar tiempo actual en timer_3.
}
}
else if(last_channel_3 == 1){ //
Si el pin 5 está en BAJO y pasó de 1 a 0.
last_channel_3 = 0; //
Guardar estado actual.
receiver_input[2] = current_time - timer_3; //
El valor de este canal es current_time - timer_3.
}
//Channel 4=========================================
if(PIND & B00010000 ){ //
¿El pin 4 está ALTO?
if(last_channel_4 == 0){ //
Si cambió de 0 a 1...
last_channel_4 = 1; //
Guardar estado actual.
timer_4 = current_time; //
Guardar tiempo actual en timer_4.
}
}
else if(last_channel_4 == 1){ //
Si el pin 4 está en BAJO y pasó de 1 a 0.
last_channel_4 = 0; //
Guardar estado actual.
receiver_input[3] = current_time - timer_4; //
El valor de este canal es current_time - timer_4.
}
}
5.3. Motores / Variadores
Como se ha explicado ya en la sección de "Materiales", los motores y
variadores van de la mano y por eso nos referiremos a ellos como una única
entidad en esta sección. Acá presentaremos el código para incorporar estos
elementos a nuestro "código maestro" del sistema de control, pero también
es útil mostrar un programa alternativo que podemos usar para calibrar
adecuadamente los motores (y al mismo tiempo verificar el sentido de giro
de los motores).
Los variadores o ESCs se componen de dos cables de entrada y tres cables
de salida gruesos. Los primeros corresponden a la entrada de alimentación
de la batería, mientras los segundos son la señal de salida hacia los
motores. Los cables de alimentación deben conectarse entonces, ya sea al
marco o a la tarjeta de distribución de potencia. Para la conexión a los
motores no es claro cómo hacerla al comienzo, por lo que mi
recomendación es simplemente conectar los cables centrales entre sí, y los
extremos de cualquier manera. Durante la calibración verificaremos
también el sentido de giro que tenga el motor y en caso de no ser correcto,
simplemente invertiremos la conexión de los cables de los extremos.
Ahora tenemos el conector con dos o tres cables más delgados, los cuales
van conectados a la tarjeta de control. Ya vimos que el tercer cable
significa que el ESC lleva incluido BEC. Cuando tenemos estos tres cables,
normalmente sus colores son naranja para la señal, rojo para +5 VDC del
BEC y café para tierra (ver imagen 5.3.1). Por tanto, respetaremos esa
convención para la conexión con el Arduino, del cual usaremos los pines 8,
9, 10 y 11 para las señales de control de los cuatro variadores.
Fig. 5.3.1 - Conexiones de motor y ESC
Comenzaremos con la elaboración de un código simple para calibrar y
probar los motores. Para comenzar es necesario decir qué tipo de señal
esperan recibir los variadores como señal de control. Convenientemente, así
como vimos en la sección anterior sobre el módulo de comunicaciones,
donde la salida de este es una señal de PWM con un ancho de pulso variable
entre 1000 y 2000 microsegundos, igualmente ese es el tipo de señal que
cada ESC debe recibir para operar su motor respectivo. Es decir, con un
pulso de 1000 microsegundos debemos esperar los motores totalmente
quitos, mientras con 2000 microsegundos estos operarán a máxima
velocidad.
Para asegurar que los motores/variadores operarán en ese rango, debe
realizarse inicialmente un procedimiento de calibración, que en términos
simples consiste en enviar a los variadores la señal máxima esperada,
seguida de la mínima. El variador responderá a esta secuencia con unos
pitidos caracterísiticos que nos indicarán que la calibración fue exitosa.
Vamos a construir entonces el código con este objetivo.
Inicialmente agregaremos la librería "Servo", que permite controlar
servomotores, como su nombre lo indica. Sin embargo, dado el parecido en
el tipo de señales requeridas para esos motores con la que requerimos para
nuestros motores sin escobillas, esta librería nos será igualmente útil.
Declararemos entonces los cuatro variadores, cada uno como un elemento
SERVO, utilizando la librería previamente definida. También declaramos una
variable "option" para seleccionar el motor a calibrar o probar.
En el "setup" comenzaremos por asignar cada ESC a un pin del Arduino,
utilizando la función "attach()" en la cual tenemos como argumentos el pin a
asignar (usaremos 8, 9, 10 y 11 en este tutorial), el valor mínimo y el valor
máximo a usar en microsegundos (1000 y 2000, respectivamente, como ya
se explicó). Luego debemos "armar" los motores escribiendo un cero a cada
uno. Este paso no es estrictamente necesario para la calibración si solo
tenemos un motor conectado a la vez. Sin embargo, en este caso asumimos
que los cuatro están conectados (aunque solo vamos a calibrar uno a la vez)
por lo cual este paso evita algún arranque accidental de los motores que no
están siendo utilizados en este momento. A continuación escribimos el valor
MÁXIMO (2000) al motor que vamos a calibrar. Recomiendo hacerlo con un
solo motor a la vez, para poder escuchar claramente la serie de pitidos que
emite el motor durante el proceso y no mezclarlos con los demás.
Finalmente iniciamos el puerto serial para interactuar con el Arduino a
través de la consola, invocamos una función "menu()" definida por nosotros
(se explica más adelante) y enviamos un mensaje para introducir un valor
entre 1000 y 2000.
En el "loop" simplemente leemos lo que se esté enviando por el puerto
serial. Se recomienda al lector seguir tutoriales sencillos para familiarizarse
con la lectura y escritura del puerto serial a través de Arduino en caso de
requerirlo. Básicamente en este proceso estamos leyendo una cadena de
caracteres enviado por el usuario, donde se espera que este introduzca un
número entre 1000 y 2000 seguido de la tecla "enter". Si los datos
introducidos no corresponden a este patrón, se enviará un mensaje
solicitando los datos correctos. Si el número introducido es correcto,
simplemente se escribe ese valor al motor escogido.
Nuetra función menu() simplemente envía un mensaje pidiendo seleccionar
el motor a probar o calibrar, lo cual corresponde a un número del 1 al 4 y
carga este valor en la variable "option". Si el valor digitado no es correcto,
simplemente solicita repetir el procedimiento hasta que el número
ingresado sea válido. Esta función hace uso a su vez de una función
read_serial() que es básicamente otra función para leer lo que se envía por
el puerto serial y en el caso particular de que sea un número entero válido,
convertirlo a tipo numérico para poder trabajar con él.
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
// Motores / ESC (Variadores)
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Lectura de los pulsos recibidos del sistema transmisor / receptor
// Decodificación de señales de pulsos a números enteros
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Librería para el manejo de los motores
#include
// Declaración de los cuatro motores
Servo esc1;
Servo esc2;
Servo esc3;
Servo esc4;
char dato;
int pulso = 0;
int option;
void setup()
{
// Asignamos cada motor al pin correspondiente y los valores mínimo y máximo
de pulso en microsegundos
esc1.attach(8, 1000, 2000);
esc2.attach(9, 1000, 2000);
esc3.attach(10, 1000, 2000);
esc4.attach(11, 1000, 2000);
esc1.write(0); // ¡IMPORTANTE! Para armar el motor correspondiente
esc2.write(0);
esc3.write(0);
esc4.write(0);
// Usar la siguiente línea solo para calibrar; comentar en otro caso
esc1.writeMicroseconds(2000); // Escribimos el valor máximo para
calibrar el motor
Serial.begin(115200);
menu();
Serial.print("Introduzca valor de PWM (1000-2000): ");
}
void loop()
{
// Interacción con el usuario para escribir un pulso válido al variador
if (Serial.available()) {
static char input[16];
static uint8_t i;
dato = Serial.read();
if ( dato != '\r' && i < 15 ) // Asumiendo que "Carriage Return" es el
caracter utilizado en el monitor serial para el cambio de línea
input[i++] = dato;
else
{
input[i] = '\0';
i = 0;
pulso = atoi(input);
Serial.println(pulso);
if (pulso < 1000 || pulso > 2000){
Serial.println("Numero no valido. Intente de nuevo (1000-2000).");
Serial.print("Introduzca valor de PWM (1000-2000): ");
}else{
switch(option){
case 1:
esc1.writeMicroseconds(pulso);
break;
case 2:
esc2.writeMicroseconds(pulso);
break;
case 3:
esc3.writeMicroseconds(pulso);
break;
case 4:
esc4.writeMicroseconds(pulso);
break;
default:
Serial.println("");
menu();
break;
}
Serial.print("Introduzca valor de PWM (1000-2000): ");
}
}
}
//--------- FUNCIONES ADICIONALES ----------------
void menu(){
// Sencilla función para escribir un menú al usuario
Serial.println("Seleccione numero de 1 a 4 para probar motor correspondiente:
");
option = 0;
while (option!=1 && option!=2 && option!=3 && option!=4) option =
read_serial();
Serial.print("Ha escogido ");
Serial.println(option);
Serial.println("");
}
int read_serial(){
// Función para leer el puerto serial y convertir texto a número
static char input[16];
static uint8_t i;
int result;
while (Serial.available()) {
dato = Serial.read();
if ( dato != '\r' && i < 15 ) // Asumiendo que "Carriage Return" es el
caracter utilizado en el monitor serial para el cambio de línea
input[i++] = dato;
else {
input[i] = '\0';
result = atoi(input);
}
}
return result;
}
Procedimiento de calibración
El sencillo programa que hemos elaborado nos permite tanto calibrar en
primera instancia cada conjunto motor-variador como probar la velocidad de
rotación (y el sentido). Para el procedimiento de calibración hay que seguir
un secuencia específica.
1. En primera instancia, una vez tengamos listo el programa, verificamos
que uno o los cuatro cables de señal estén conectados a los pines
correspondientes del Arduino (y también los cables correspondientes
a tierra, por supuesto). Pero la almientación de los variadores debe
estar desconectada (es decir, la batería).
2. Tras estas verificaciones, podemos proceder a descargar el programa
al Arduino. Una vez finalizado el proceso, abrimos el monitor serial y
lo dejamos a 115200 baudios. Al hacer esto deberíamos ver el mensaje
de selección de motor en pantalla.
3. Ahora sí, en este estado, procedemos a conectar la batería.
Escucharemos un pitido del motor que esté conectado en el momento.
Recordemos que de acuerdo al programa, en este momento se está
enviando la señal máxima (2000 us) al motor en calibración; sin
embargo, todos los motores deberían estar quietos en este momento.
La razón de esto es que cuando un variador es energizado y está
recibiendo en ese momento la señal máxima, asume que no está en
modo de operación normal sino en modo calibración. Por eso es
necesario hacer los pasos en este orden.
4. En el monitor serial debemos digitar el número del motor que estemos
calibrando. Este número irá del 1 al 4 y corresponderá al pin del 8 al
11 al que esté conectado el ESC respectivo. Ahora el programa nos
pedirá introducir un valor de pulso a enviar. Enviaremos el valor
MÍNIMO (1000). Al hacer esto, deberíamos escuchar un doble pitido
del motor y otro pitido un rato después. Esto significa que el motor ha
reconocido la calibración, la cual ha sido exitosa, y ahora ha entrado
al modo de operación normal.
5. Ahora sí podemos enviar cualquier otro valor que se nos ocurra en el
rango establecido, para observar la velocidad con la que el motor gira
con respecto a cada valor y verificar si el sentido de giro es el
deseado. Si no lo es, simplemente debemos intercambiar los cables
externos entre motor y ESC.
Este proceso debe hacerse para los cuatro variadores, simplemente
variando la línea en el programa donde se escribe la señal máxima (2000
us), asignándola al variador correspondiente. Una vez se haya hecho esto
para los cuatro, recomiendo dejar esa línea comentada y volver a cargar el
programa, que ahora quedará simplemente de prueba.
Mira acá el video correspondiente a los pasos 4 y 5 del tutorial.
CONSTRUCCIÓN
Continuamos con la guía, pasos 6 a 10.
Paso 6: Conexión de componentes
Ya lo hemos venido haciendo de forma individual para cada subsistema
como parte de su integración propia al Arduino, pero ahora es el momento
de considerar el sistema de nuestra aeronave completo con respecto a sus
conexiones y el montaje de todos los componentes sobre el marco.
En la figura 6 se ilustra de manera esquemática la totalidad de las
conexiones de nuestra aeronave, incluyendo los elementos que ya hemos
visto (IMU, receptor de comunicaciones y motores / ESCs) más la batería y
algunos elementos adicionales como un par de resistencias para un divisor
de voltaje y un LED de indicación de estado. A continuación resumimos los
puntos más importantes respecto a este esquema:
La IMU, como se mencionó, se comunica por el protocolo I 2C, lo que
supone usar los pines SCL y SDA del Arduino. Adicionalmente requiere
alimentación (es posible usar la salida de 3.3 V o la de 5 V) y conexión a
tierra.
El receptor de comunicaciones cuenta con varios pines, de los cuales
usaremos cuatro señales (throttle, ailerons, elevator and rudder, usando
el nombre que suelen tener estas marquillas en los receptores)
conectados a los pines 7, 6, 5 y 4 del Arduino respectivamente. Hay una
hilera completa de pines para alimentación (debe ser a 5V) y otra para
tierra, de las cuales solo hace falta usar una de cada una.
Para los motores/variadores comenzaremos a contar desde el de
adelante a la izquierda y nos desplazaremos así en sentido horario
hasta el 4. En ese orden, los conectaremos a los pines 8, 9, 10 y 11 del
Arduino respectivamente. Las tierras ya están interconectadas entre sí
en el momento en el que soldamos los variadores a la tarjeta de
distribución, así que solo hace falta conectar una de ellas al Arduino. La
señal de BEC de los variadores, si la tenemos, no será requerida en este
tutorial.
El conector de la batería ya debería estar soldado a la tarjeta de
distribución, por lo cual los ESC ya están siendo alimentados. Pero,
importante, falta alimentar el Arduino. Según especificaciones
obtenidas en su página, este puede recibir hasta unos 12 voltios (rango
recomendado), por lo cual es posible alimentarlo directamente desde la
batería. Para esto tenemos dos opciones: podemos utilizar un conector
de 2.1 mm compatible con el jack de alimentación que tiene el Arduino
y a través de un para de cables soldar a los mismos pines donde
tenemos el conector de la batería. O bien es posible conectar un cable
desde el pin positivo de la batería al pin llamado Vin de nuestro Arduino.
En este segundo caso debemos utilizar un diodo para aislar la batería
de otras posibles fuentes de alimentación (por ejemplo, el puerto USB
de nuestro computador cuando hagamos pruebas). El diodo no es
necesario en el primer caso puesto que ya está incluido entre el jack de
alimentación y el pin Vin en la tarjeta Arduino.
Sea cual sea la opción elegida en el paso anterior, debemos conectar el
pin Vin a un par de resistencias en serie. Esto con el fin de medir el
nivel de voltaje de la batería. Las entradas análogas reciben un máximo
de 5 V; por ende debemos convertir el valor de la batería (rango
recomendado de operación entre 10 y 12.4 V) en un valor apropiado
para el puerto del Arduino. Esto se hace con un divisor de voltaje
(clic acá para leer lo que es esto), conformado por un par de
resistencias de valores apropiados. No hay una única solución de
valores, el lector puede utilizar las que le convengan conforme a la
ecuación presentada en el enlace. En este caso sugiero unas
resistencias de 4.7 y 10 kilo-ohmios; con estos valores el pin A5 del
Arduino recibirá un máximo de 3.96 V, perfectamente aceptable.
Finalmente, un LED de indicación, aunque no necesario, es sugerido
para tener una referencia visual del estado del dron. En este tutorial lo
conectaremos al pin 2 del Arduino, junto a su resistencia de limitación
de corriente, para la cual una de 470 ohmios o similar podrá servir.
Fig. 6 - Esquema de conexiones completas de dron (clic en la imagen para
agrandar)
Mira acá el video correspondiente a este paso del tutorial.
Paso 7: Diseño y programación del control
Ya conocemos de manera más detallada todos los elementos de nuestra
aeronave. Ya sabemos cómo funciona cada uno y cómo se integran al
Arduino, el cerebro de nuestro dron. Podemos adquirir los datos de los
sensores (la IMU), los comandos a efectuar (del control remoto) y operar los
motores. Ahora viene un paso muy importante: integrar toda esta
información para generar el sistema de control de nuestra aeronave.
Existen muchas y muy diferentes técnicas para diseñar e implementar una
estrategia de control para un sistema dinámico, como es el caso de nuestra
aeronave. En este tutorial usaremos uno de los métodos más populares,
conocido como control PID. La teoría de este tipo de controlador es muy
interesante y no demasiado compleja; existen infinidades de páginas donde
el lector puede consultar al respecto. Esta es una de tantas páginas donde
se explican los principios del controlador PID de una manera sencilla: ver
enlace.
Una vez asimilada la información, podemos plasmar el esquema de control
en lazo cerrado de nuestra aeronave, como se muestra en la figura 7.1.
Como entrada externa tenemos las señales enviadas con nuestro transmisor
remoto. El controlador PID, implementado en el Arduino, se encarga de
tomar estas señales, o más exactamente, la diferencia entre el estado
deseado y el estado real de nuestro dron y calcular la señal de salida
adecuada para ser efectuada por el mismo. Ahora bien, debemos distinguir
dos elementos claves en nuestro sistema: los actuadores, que son quienes
reciben esta señal de control y ACTÚAN, como su nombre lo indica, sobre el
sistema. Y los sensores, en este caso la IMU, quienes miden el estado
actual del sistema y realimentan esta información al sistema de control. Es
por eso que se dice que el sistema es de lazo cerrado, pues la salida del
sistema completo es realimentada hacia la entrada continuamente.
Fig. 7.1 - Esquema de control del dron
Fig. 7.2 - Definición de coordenadas
Antes de proceder con el código es necesario tener claro a nivel conceptual
cómo será nuestro sistema de control y su interacción con los demás
componentes de nuestro sistema. Pero, antes de ello, es necesario, si no se
ha hecho ya, establecer algunas convenciones básicas sobre el movimiento
de nuestro dron. En particular debemos tener claro:
El sistema de coordenadas que usaremos (ejes x-y-z). Con esto
definiremos qué dirección será "adelante", "atrás" y demás para nuestro
aparato, lo cuál es esencial para relacionar con nuestro sistema de
comunicaciones y su integración con el sistema de control, asegurando
que la señal de salida producida sea la esperada.
El sentido de rotación de las aspas. Como vimos en los fundamentos,
los rotores contiguos deben girar en sentidos opuestos, donde
finalmente tendremos dos girando en sentido CW (dirección horaria) y
dos en sentido CCW (dirección antihoraria).
La figura 7.2 nos presenta el diagrama que representa las convenciones que
elegiremos para este proyecto. Valga decir que este sistema no es único, el
lector es libre de elegir el sistema de coordenadas que le parezca más
conveniente, pero debe ser cuidadoso de ser consistente con el mismo al
programar el sistema de control. En este caso, el sistema de coordenadas
utilizado tiene el eje z invertido, es decir, apuntando hacia abajo, como es
convención en el mundo aeronáutico. Esto dependerá también de la IMU que
hayamos elegido y de su orientación en la aeronave, hay que tener cuidado
y realizar las pruebas respectivas (como ya hicimos en el numaral anterior)
para asegurar que las lecturas obtenidas se ajusten a nuestro sistema de
coordenadas.
Ahora bien, después de lo que hemos leído y aprendido sobre el control PID,
¿cómo implementarlo en nuestro Arduino para nuestra aeronave? Después
de todo, nos quedan algunos interrogantes y consideraciones en nuestra
situación particular, a saber:
Hemos aprendido sobre el control PID, pero lo que hemos visto es
aplicable para sistemas SISO (Single Input - Single Output) o de una
entrada y una salida. Pero en nuestro caso tenemos cuatro entradas
(las señales de referencia de potencia, alabeo, cabeceo y guiñada,
enviadas a través del transmisor remoto) y cuatro salidas, que son las
salidas a cada motor. ¿Cómo hacemos entonces?
Tenemos cuatro entradas y cuatro salidas, pero en cuanto a las
medidas obtenidas por nuestro sensor (la IMU) solo tenemos tres de
ellas (ángulo de alabeo, de cabeceo y de guiñada). ¿Cómo integramos
entonces estas tres medidas al sistema de control?
La salida del sistema de control, que como sabemos debe ser la entrada
a los actuadores (los motores), ¿sale directamente del controlador o
requiere algún tipo de ajuste antes de poder ser enviada efectivamente
a cada motor?
Para esto es útil recurrir nuevamente a nuestro buen amigo, el diagrama de
bloques (figura 7.3), que de una forma sencilla y gráfica nos presenta la
conceptualización de nuestro sistema de control, resolviendo las
inquietudes anteriores de esta forma:
Al tener varias cantidades de entradas, salidas y mediciones, esto
parece sugerirnos que realmente no necesitamos uno sino varios
controladores. Esto es correcto. Como se observa en la figura,
realmente debemos implementar TRES controladores en uno, uno para
cada ángulo de actitud del dron (en adelante los llamaremos, a mi
pesar, por su nombre en inglés - roll, pitch y yaw -, pues es una práctica
ampliamente difundida en la industria). En efecto, tendremos tres
controladores SISO.
En el caso de la potencia, que se traduce en la elevación de la
aeronave, realmente no estamos efectuando ningún control y por eso
vemos que esta señal "pasa derecho", sin requerir ningún controlador.
En otras palabras, el valor de potencia que enviamos con nuestro
transmisor es prácticamente el mismo que es usado para generar la
señal de los motores.
Ahora bien, la señal que produce cada controlador, junto con la señal
extra de potencia-elevación, deben ser combinadas entre sí de forma
correcta para ser enviadas a cada variador-motor. Acá es donde vemos
más claramente la importancia de las definiciones establecidas en la
figura 7.2 (y donde debemos tener cuidado de ser coherentes en caso
de haber escogido un sistema diferente). Debemos distinguir entre dos
formas de aplicar estas señales a los motores: de manera integral (igual
para todos los motores) o de manera diferencial (positiva para algunos
motores y negativa para otros). Veamos cómo aplicamos cada una de
las señales que tenemos:
o Comencemos por la más fácil. La señal de elevación-potencia es
la única que se aplica de forma integral a los cuatro motores. Por
eso vemos que en cada bloque adonde llega la línea amarilla, su
aplicación es positiva (representada por el signo '+'). Esto es
lógico, puesto que la potencia suministrada al dron para elevarse
debe ser suministrada por igual a todos los motores.
o La señal de "roll" (rojo escarlata) es aplicada de forma
diferencial, siendo positiva para los motores 1 y 4 y negativa para
los motores 2 y 3. La razón la observamos en la figura 7.2. El
"roll" es la rotación efectuada alrededor del eje x. Utilizando la
convención de la mano derecha (según la cual debemos usar
nuestra mano derecha, apuntando el pulgar en dirección del eje,
donde la rotación del resto de dedos nos dice en qué sentido la
rotación es positiva), tenemos que cuando los rotores 1 y 4
tengan más potencia, la rotación alrededor de este eje será
positiva; cuando los rotores 2 y 3 reciban más potencia, la
rotación será negativa. Esto explica la distribución de los signos
'+' y '-' para esta señal.
o Utilizamos el mismo razonamiento para la señal de "pitch" (azul),
aplicada de forma diferencial y siendo positiva para los motores 3
y 4 y negativa para los motores 1 y 2, ya que el "pitch" es la
rotación efectuada alrededor del eje y.
o La señal de "yaw" (verde) también es aplicada de forma
diferencial, siendo positiva para los motores 2 y 4 y negativa para
los motores 1 y 3, ya que el "yaw" es la rotación efectuada
alrededor del eje z. Teniendo en cuenta que la rotación de una
hélice en un sentido provoca una rotación en el sentido opuesto
para la aeronave podemos comprender, por ejemplo, para el rotor
2 que gira en sentido horario que el resultado final sobre la
aeronave será un movimiento en sentido antihorario, que es el
sentido positivo de giro alrededor del eje z. Con el mismo
razonamiento para los demás rotores podemos explicar la
distribución de los signos '+' y '-' para esta señal.
Fig. 7.3 - Diagrama de bloques detallado del sistema de control
Vamos entonces a analizar las partes del código que corresponden al
sistema de control y simultáneamente aprovecharemos para esclarecer
algunos conceptos sobre la estrategia seleccionada. Pero antes de ello
debemos hacer un par de aclaraciones pertinentes repsecto a la estrategia
de control utilizada.
1. Recordemos las mediciones que se obtienen de la IMU. De los
giroscopios obtenemos la velocidad angular alrededor de los ejes x, y y
z. De los acelerómetros obtenemos, desde luego, la aceleración en cada
dirección. Realmente no obtenemos de forma directa la medida de los
ángulos de "roll", "pitch" y "yaw", sino que estos deben ser calculados
matemáticamente a partir de la información anterior, como vimos en la
sección 5.1. En ese caso, una estrategia de control que resulta
conveniente es no controlar directamente el valor deseado de esos
ángulos, sino la velocidad angular, para utilizar directamente la
medición obtenida de los giroscopios y aprovechar sus características
ventajosas, como el bajo nivel de ruido y la alta precisión. En resumen,
al tirar las palancas de nuestro mando remoto no buscaremos inclinar el
dron en un ángulo específico hacia la dirección adonde tiremos la
palanca, sino que estableceremos más bien la rapidez con la cual el
dron rotará en esa dirección. Ya veremos la implicación de esta
consideración aparentemente sutil en el código.
2. Sin embargo, cuando no estemos manipulando ninguna palanca aparte
de la potencia, ¿en qué dirección cree el lector que se inclinará el dron?
¿Se mantendrá acaso perfectamente nivelado? La respuesta es que no,
el dron mantendrá una inclinación que dependerá en gran medida de la
última dirección en la que se haya tirado alguna palanca de dirección o
incluso de la posición inicial del dron en el suelo. Esto precisamente
porque estamos controlando velocidad angular y no posición, con lo
cual la aeronave podrá, por ejemplo, mantener un ángulo de 10° hacia la
derecha. Mientras no esté rotando, los giroscopios medirán "cero" y el
sistema se estabilizará en esa posición. Esto no es del todo malo, de
hecho en los drones de competencias el sistema de control se
comporta de esta manera debido a la alta velocidad de respuesta. Sin
embargo, para nuestro primer proyecto de dron eso no es lo que
queremos. Queremos una aeronave donde al no manipular ninguna
palanca, la inclinación en cualquier dirección sea cero. En otras
palabras, queremos un dron auto-nivelante. Para lograr esto, debemos
calcular los ángulos de inclinación de "roll" y "pitch", como ya hicimos
en la sección 5.1 y usar estos datos para compensar el control por
velocidad de ambos ángulos. De nuevo, ya veremos la implicación de
esto al desarrollar el código.
Comenzamos entonces con nuestro código del sistema de control. En
primera instancia declaramos las variables correspondientes al control,
cuyo uso se verá más adelante. Por ahora debemos mencionar la variable
SampleTime, la cual hemos inicializado en 4 (valor en milisegundos). Ya
veremos su importancia y el porqué de ese valor.
En el "setup" comenzamos por establecer los valores límite para la señal de
control, los cuales serán -400 y 400. ¿Por qué estos valores? Ya que
esperamos que el valor central de cada ángulo esté en 1500 us, podemos
movernos 500 us a cada lador alrededor de este valor. Por ello los valores
de -400 y 400, donde dejamos un pequeño margen de 100 us a ambos lados.
Inicializamos algunos valores en 0 para el cálculo de los términos derivativo
e integral de cada controlador. Los valores de referencia iniciales serán
1500 para la referencia de los ángulos y 1000 para la señal de elevación. El
1500 se debe a que para los ángulos, dado que nos podemos desplazar
hacia un lado o hacia el otro, dentro de un rango de 1000 a 2000 el valor
central (sin desplazamiento) será en la mitad, es decir, 1500. También
inicializamos en 0 las señales de salida de cada controlador.
A continuación, como se observa, usamos la función SetTunings para
asignar los parámetros Kp (proporcional), Ki (integral) y Kd (derivativo) a
cada controlador. Acá surge una pregunta clave para esta sección: ¿cómo
se determinan estos valores? Existen varias alternativas, dependiendo del
conocimiento técnico del constructor y el grado de refinación que se
busque. En mi caso creé un modelo matemático del dron a partir de las
ecuaciones físicas que gobiernan su comportamiento y lo implementé en
Matlab, tomando también como parámetros las características físicas del
aparato (peso, longitudes, etc) así como algunas características del Arduino
(en especial la tasa de refresco que escogimos de 4 ms, o 250 Hz) para
simular la aeronave y poder ajustar en el programa los valores del
controlador PID hasta encontrar aquellos que brindaran un desempeño
óptimo. Después de eso obtuve unos buenos valores de referencia con los
que pude comenzar a hacer "ensayo y error" en la aeronave real, pero ya
siendo los ajustes finales mínimos. Sin embargo, este procedimiento no
hace parte del alcance de este tutorial, que debe mantenerse lo más
sencillo posible. Así que por ahora recomiendo empezar con los valores que
aparecen en este ejemplo, que fueron precisamente los obtenidos en mi
experiencia, los cuales deben ser refinados posteriormente durante la
puesta a punto de la aeronave de cada usuario.
En el "loop" comenzamos por establecer unos valores de ajuste. Como
dijimos, vamos a utilizar los ángulos calculados de "roll" y de "pitch" para
corregir el control por velocidad angular para los ejes x y y y lograr que el
dron se "autonivele". Por ello asignamos los ángulos respectivos a las
variables "roll_level_adjust" y "pitch_level_adjust" multiplicados por 15. Este
valor es un número que indica la velocidad con la que queremos que se
efectúe la corrección y el cual el lector puede modificar a su gusto, pero
recomiendo empezar con este valor obtenido empíricamente.
Luego tenemos una sección dedicada al control de "roll". Establecemos un
"set point" de cero. Recordemos que estamos controlando velocidad
angular, por lo cual este "set point" nos dice que nuestra señal de velocidad
angular deceada alrededor del eje x es de 0 °/s. Luego entramos a un
condicional, donde básicamente establecemos que no haya ningún control
si la señal de potencia es menor de 1200 us, esto con el fin de que la nave
no comience a estabilizarse sin haberse elevado (y por lo tanto podemos
arrancar de manera segura desde un terreno que no sea perfectamente
plano, como el pasto). Posteriormente establecemos una pequeña "banda
muerta" entre 1490 y 1510 us. Esto se debe a que no podemos asegurar que
cuando la palanca del mando esté centrada, su valor enviado sea
exactamente 1500 us, sino que posiblemente oscilará en un rango cercano
a este valor. A continuación modificamos el "set point" restándole el valor
de ajuste del ángulo de "roll" y dividimos este valor por tres para limitar un
poco la velocidad máxima de giro. Finalmente, recordamos que al
controlador le ingresan dos señales: la referencia y la medida del estado
actual. La referencia es el "set point" que acabamos de modificar; la medida
es la señal actual de velocidad angular en el eje x, llamda "gx_rate", así que
asignamos este valor a la variable "Input_r".
La sección de "pitch" es exactamente igual a la de "roll", simplemente
utilizando las variables correspondientes. Finalmente la sección de "yaw" es
parecida, salvo que en este caso no tenemos necesidad de corregir el "set
point" para auto-nivelación.
Acto seguido invocamos la función Compute(), que veremos más adelante,
en la cual calcularemos la señal de salida de cada controlador PID. Luego
limitamos el máximo valor de potencia a 1800 us, para dar un margen a las
otras señales de control en el ventual caso en que operemos el dron a
máxima potencia. Finalmente calculamos la salida a ser enviada a cada
motor usando las cuatro señales mencionadas en la explicación de la figura
7.3: la señal de potencia y la suma o resta de la señal de salida de cada
controlador. Como medida de seguridad limitamos la señal de cada motor a
los valores ya conocidos, en el rango entre 1000 y 2000 y finalmente
escribimos dichos valores al pin asignado a cada variador.
Al final del "loop" tenemos un par de líneas muy importantes. Habíamos
definido una variable "loop_timer" la cual básicamente lleva la cuenta de lo
que dura la ejecución de un "loop" en microsegundos. Acá restamos el valor
actual en microsegundos (obtenido con la función micros()) de dicho valor, y
nos quedamos dentro de un "while loop" hasta que esa diferencia sea mayor
o igual a 4000, después de lo cual cargamos el nuevo valor de
microsegundos a la variable "loop timer" En otras palabras, en estas líneas
aseguramos que la duración del lazo sea de 4000 microsegundos, o 4
milisegundos. ¿Por qué? Para el cálculo de los parámetros integral y
derivativo del control PID es necesario conocer exactamente el valor del
tiempo transcurrido entre cada ejecución del lazo. Para ello podemos medir
el tiempo transcurrido cada vez que se ejecuta el lazo, o bien asegurar
siempre un tiempo de ejecución fijo. En este caso hemos escogido la
segunda opción, así que debemos asegurar que el tiempo de ejecución del
ciclo "loop" sea constante, y así los parámetros Ki y Kp serán también
constantes. En mis propias pruebas, una vez integrados tanto las lecturas
de la IMU, las comunicaciones con el receptor RF y el envío de señales a los
motores, más los cálculos de los ángulos y las computaciones propias de
cada controlador PID, teniendo en cuenta un parámetro importante como la
velocidad de procesador del Arduino Uno (16 MHz), encontré que la
ejecución de un "loop" tardaba algo más de 3 ms, midiendo siempre un
tiempo variable pero cercano a los 3.4 ms. Por ello decidí redondear este
valor a 4 ms, y garantizar este tiempo fijo para la ejecución del "loop". Este
valor lo utilizaremos en las funciones auxiliares para calcular los
parámetros del control PID.
En cuanto a las funciones adicionales definidas, explicaremos la más
importante, Compute(). Las demás son bastante sencillas y se pueden
comprender con la ayuda de los comentarios (setTunings() y
setOutputLimits(). Para computar las señales de salida de cada controlador,
primero debemos obtener la señal de error, que como sabemos de la teoría
de control, es la diferencia entre el "set point" y la medición actual. Para
calcular el término integral multiplicamos el error por el valor de la constnte
integral (Ki) que cargamos en el "setup". Debemos limitar este valor a un
mínimo o máximo establecido por los valores que también determinamos en
el "setup" (-400 y 400). Para el término derivativo debemos calcular la
diferencia entre la medición actual y la anterior, multiplicando también este
valor por el kd establecido. Finalmente la señal de salida de cada
controlador PID será compuesta por el término proporcional multiplicado
por el error más los términos integral y derivativo ya computados. Para
terminar guardamos la medición actual para ser usada en el próximo
cálculo.
////////////////////////////////////////////////////////////////////
//////////////////////////////////////////
// Dron - Arduino
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Impementación de un UAV tipo cuadricóptero con motores Brushless (sin
escobillas)
// El control se realiza usando la velocidad angular y haciendo correcciones
según los ángulos calculados
// El control remoto está compuesto por transmisor y receptor
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
// Incluimos algunas librerías adicionales que vamos a utilizar
#include <Wire.h> // Librería para protocolo I2C
#include <Servo.h> // Librería para el manejo de los motores
// ALGUNAS DEFINICIONES
//Direccion I2C de la IMU
#define IMU_ADDRESS 0x68
// Variables control PID
unsigned long lastTime;
double Input_r, Output_r, Setpoint_r;
double Input_p, Output_p, Setpoint_p;
double Input_y, Output_y, Setpoint_y;
double Output_h;
double ITerm_r, lastInput_r;
double ITerm_p, lastInput_p;
double ITerm_y, lastInput_y;
double kp_r, ki_r, kd_r;
double kp_p, ki_p, kd_p;
double kp_y, ki_y, kd_y;
int SampleTime = 4; // 4 milisegundos
double outMin_dif, outMax_dif;
float roll_level_adjust, pitch_level_adjust;
// Offset para los acelerómetros (deben ser obtenidos en reposo en posición
horizontal - usar el programa de la IMU)
float aoffsetX = -8, aoffsetY = -199, aoffsetZ = 3870;
// Variables IMU
int acc[3];
int gyro[3];
int temperature;
float rawX, rawY, rawZ;
float X, Y, Z;
float gyroX, gyroY, gyroZ;
float gx_rate, gy_rate, gz_rate;
float last_gx_rate, last_gy_rate, last_gz_rate;
float rollrad, pitchrad;
unsigned long mtime, looptime, loop_timer;
float angleAx, angleAy, angleAz;
float angleGx, angleGy, angleGz;
float goffsetX, goffsetY, goffsetZ;
// Variables del filtro
float angleFx, angleFy;
// Motores
Servo esc1, esc2, esc3, esc4;
char dato;
// Control remoto
volatile int rollref, pitchref, yawref, href;
byte last_channel_1, last_channel_2, last_channel_3, last_channel_4;
int receiver_input[4];
unsigned long timer_1, timer_2, timer_3, timer_4, current_time, last_int;
// Otras
int start;
int led_dis;
void setup()
{
// Deshabilitar watchdog antes del setup
wdt_disable();
// Inicio del puerto serial a 115200 baudios y mensaje de bienvenida
Serial.begin(115200);
Serial.println("Bienvenido, sistema iniciando...");
// Inicio de comunicación I2C
Wire.begin();
// Inicializamos la IMU
init_IMU();
// Asignamos cada motor a su pin correspondiente
esc1.attach(8,1000,2000);
esc2.attach(9,1000,2000);
esc3.attach(10,1000,2000);
esc4.attach(11,1000,2000);
esc1.write(0); // ¡IMPORTANTE! Hay que armar cada motor
esc2.write(0);
esc3.write(0);
esc4.write(0);
// Los pines que se utilicen como salida deben declararse explícitamente - en
este caso, el LED
pinMode(LED_PIN, OUTPUT);
// Un pequeño "delay" e iniciamos la calibración de la IMU
delay(1000);
Serial.println("Calibrando...");
Serial.println("Mantener la IMU quieta y en posición horizontal");
calibrate();
delay(500);
Serial.println("Calibración finalizada.");
// Inicialización de los parámetros de control
double *limsdif = SetOutputLimits(-400, 400);
outMin_dif = limsdif[0];
outMax_dif = limsdif[1];
ITerm_r = 0, lastInput_r = 0;
ITerm_p = 0, lastInput_p = 0;
ITerm_y = 0, lastInput_y = 0;
// Los controles se asumen centrados al comienzo
rollref = 1500;
pitchref = 1500;
yawref = 1500;
href = 0; // Lo iniciamos en cero como valor seguro.
Output_r = 0, Output_p = 0; Output_y = 0;
// Roll Control
double *cons_r = SetTunings(0.8, 0.1, 0.02);
kp_r = cons_r[0];
ki_r = cons_r[1];
kd_r = cons_r[2];
// Pitch Control
// Igualamos a los parámetros de "roll" ya que el dron es prácticamente
simétrico en los ejes x y y
double *cons_p = cons_r;
kp_p = cons_p[0];
ki_p = cons_p[1];
kd_p = cons_p[2];
// Yaw Control
double *cons_y = SetTunings(2, 0.01, 0.01);
kp_y = cons_y[0];
ki_y = cons_y[1];
kd_y = cons_y[2];
// Configuramos las interrupciones para recibir los comandos remotos
PCICR |= (1 << PCIE2); //
PCIE2 activado para habilitar PCMSK2 scan.
PCMSK2 |= (1 << PCINT23); //
PCINT23 (D7) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT22); //
PCINT22 (D6) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT21); //
PCINT21 (D5) activado para disparar una interrupción si hay cambio de estado.
PCMSK2 |= (1 << PCINT20); //
PCINT20 (D4) activado para disparar una interrupción si hay cambio de estado.
// Esperamos hasta que el receptor esté activo y la señal de potencia esté al
mínimo.
while(href < 900 || href > 1150 || yawref < 1400){
href = receiver_input[0];
yawref = receiver_input[3];
start ++; //
Mientras esperamos incrementamos la variable "start" en cada ciclo.
// Enviamos repetidamente una señal mínima a los motores para mantenerlos
armados en posición segura
esc1.writeMicroseconds(1000);
esc2.writeMicroseconds(1000);
esc3.writeMicroseconds(1000);
esc4.writeMicroseconds(1000);
delay(3);
if (start == 125) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
// ...cambiamos el estado del LED
start = 0; //
Reiniciamos "start"
}
}
start = 0; //
Reiniciamos "start"
led_dis = 1; //
LED arranca en estado encendido
Serial.println("Listo para volar");
mtime = millis(); //
Inicializamos la variable mtime con el valor actual en milisegundos (para uso
del giroscopio)
loop_timer = micros(); //
Inicializamos la variable mtime con el valor actual en milisegundos (para uso de
las interrupciones)
}
void loop()
{
wdt_reset(); // Reset watchdog cada loop
// Leemos las entradas del transmisor remoto
href = receiver_input[0];
rollref = receiver_input[1];
pitchref = receiver_input[2];
yawref = receiver_input[3];
// Leemos la IMU
read_IMU();
// Obtenemos ángulos de roll and pitch de lecturas del acelerómetro
rawX = acc[0] - aoffsetX;
rawY = acc[1] - aoffsetY;
rawZ = acc[2] - (4095 - aoffsetZ); // Debemos considerar la gravedad;
en este caso 1g es igual a 4095
// 1/4096 = 0.0002 (4096 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
X = rawX*0.0002;
Y = rawY*0.0002;
Z = rawZ*0.0002;
rollrad = atan(Y/sqrt(X*X+Z*Z)); // Ángulo en radianes
pitchrad = atan(X/sqrt(Y*Y+Z*Z)); // Ángulo en radianes
// 180/pi = 57.2958 (factor para convertir a grados)
angleAx = rollrad*57.2958; // Ángulo de roll en grados
angleAy = pitchrad*57.2958; // Ángulo de pitch en grados
// Código para giroscopio (roll, pitch, yaw)
looptime = (millis() - mtime); // Calculamos el valor
transcurrido en ms entre el ciclo pasado y este
mtime = millis(); // Guardamos el valor actual para
usarlo en el próximo ciclo
gyroX = gyro[0] - goffsetX;
gyroY = gyro[1] - goffsetY;
gyroZ = gyro[2] - goffsetZ;
// 1/65.5 = 0.0153 (65.5 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
gx_rate = gyroX*0.0153;
gy_rate = gyroY*0.0153;
gz_rate = gyroZ*0.0153;
// Filtrado inicial de las mediciones de velocidad angular usando una
proporción de la medida anterior y la actual
gx_rate = (0.7*last_gx_rate) + (0.3*gx_rate);
gy_rate = (0.7*last_gy_rate) + (0.3*gy_rate);
gz_rate = (0.7*last_gz_rate) + (0.3*gz_rate);
// Integramos para obtener los ángulos
angleGx = angleGx + (gx_rate * looptime)*0.001; // Convertir a segundos
(1/1000)
angleGy = angleGy - (gy_rate * looptime)*0.001; // Medición de pitch rate
está invertida por sistema de coordenadas elegido
angleGz = angleGz - (gz_rate * looptime)*0.001; // Medición de yaw rate
está invertida por sistema de coordenadas elegido
// Limitamos los ángulos al rango entre -180 y 180 grados
if (angleGx < -180) angleGx += 360;
if (angleGx > 180) angleGx -= 360;
if (angleGy < -180) angleGy += 360;
if (angleGy > 180) angleGy -= 360;
if (angleGz < 0) angleGz += 360;
if (angleGz > 360) angleGz -= 360;
// Guardar valores actuales para el próximo ciclo
last_gx_rate = gx_rate;
last_gy_rate = gy_rate;
last_gz_rate = gz_rate;
// Corrección de "yaw" para los ángulos obtenidos del giroscopio
// pi/180 = 0.0174 (para convertir a radianes, luego *0.001 para convertir a
segundos
angleFx -= angleFy * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de pitch a roll
angleFy += angleFx * sin((gz_rate * looptime)*0.0000174); // Si
hubo "yaw" tranferir ángulo de roll a pitch
// Aplicar el Filtro Complementario a los ángulos originales
angleFx = 0.995*(angleFx + (gx_rate * looptime*0.001)) + 0.005*angleAx;
angleFy = 0.995*(angleFy - (gy_rate * looptime*0.001)) + 0.005*angleAy;
// Limitamos los ángulos al rango entre -180 y 180 grados
if (angleFx < -180) angleFx += 360;
if (angleFx > 180) angleFx -= 360;
if (angleFy < -180) angleFy += 360;
if (angleFy > 180) angleFy -= 360;
// Corrección de velocidad angular para autonivelación
roll_level_adjust = angleFx * 15; //
Calcular corrección de roll
pitch_level_adjust = angleFy * 15; //
Calcular corrección de pitch
// ------------------------------ CONTROL PID
--------------------------------------
// Roll Control
// El set point en grados por segundo es determinado de la señal recibida del
mando remoto.
// Dividimos por 3 para limitar el máximo "roll rate" a unos 163 grados por
segundo ( (500-10)/3 = 163d/s ).
Setpoint_r = 0;
if (href > 1200){ // No
hay control si la palanca de potencia está abajo
// Establecemos una banda muerta de 20us para un mejor rendimiento
if (rollref > 1510) Setpoint_r = rollref - 1510;
else if (rollref < 1490) Setpoint_r = rollref - 1490;
Setpoint_r -= roll_level_adjust; //
Restar la corrección calculada preciamente para autonivelar
Setpoint_r *= 0.3333; //
Dividir el setpoint por 3 para obtener ángulos en grados.
}
Input_r = gx_rate; //
Como la variable a controlar es la velocidad angular, es este el valor que se
pasa como entrada al control PID
// Pitch Control
// El set point en grados por segundo es determinado de la señal recibida del
mando remoto.
// Dividimos por 3 para limitar el máximo "pitch rate" a unos 163 grados por
segundo ( (500-10)/3 = 163d/s ).
Setpoint_p = 0;
if (href > 1200){ //
No hay control si la palanca de potencia está abajo
// Establecemos una banda muerta de 20us para un mejor rendimiento
if (pitchref > 1510) Setpoint_p = pitchref - 1510;
else if (pitchref < 1490) Setpoint_p = pitchref - 1490;
Setpoint_p -= pitch_level_adjust; //
Restar la corrección calculada preciamente para autonivelar
Setpoint_p *= 0.3333; //
Dividir el setpoint por 3 para obtener ángulos en grados.
}
Input_p = -gy_rate; //
Como la variable a controlar es la velocidad angular, es este el valor que se
pasa como entrada al control PID
// Yaw Control
// El set point en grados por segundo es determinado de la señal recibida del
mando remoto.
// Dividimos por 3 para limitar el máximo "yaw rate" a unos 163 grados por
segundo ( (500-10)/3 = 163d/s ).
Setpoint_y = 0;
// Establecemos una banda muerta de 20us para un mejor rendimiento
if (href > 1200){ //
No hay control si la palanca de potencia está abajo
if (yawref > 1510) Setpoint_y = (yawref - 1510)*0.3333;
else if (yawref < 1490) Setpoint_y = (yawref - 1490)*0.3333;
}
Input_y = gz_rate; //
Como la variable a controlar es la velocidad angular, es este el valor que se
pasa como entrada al control PID
// Todos los cálculos de control PID
Compute();
// Para señal de potencia se envía el valor recibido directamente del receptor
Output_h = href;
if (Output_h > 1800) Output_h = 1800; //
Dejamos un margen para poder realizar control a máxima potencia
// Calculamos la salida a cada motor combinando adecuadamente la señal de
salida de cada controlador
int Output1 = Output_h + Output_r + Output_p - Output_y;
int Output2 = Output_h - Output_r + Output_p + Output_y;
int Output3 = Output_h - Output_r - Output_p - Output_y;
int Output4 = Output_h + Output_r - Output_p + Output_y;
// Limitamos los valores de ancho de pulso entre 1000 y 2000 us
if (Output1 > 2000) Output1 = 2000;
else if (Output1 < 1000) Output1 = 1000;
if (Output2 > 2000) Output2 = 2000;
else if (Output2 < 1000) Output2 = 1000;
if (Output3 > 2000) Output3 = 2000;
else if (Output3 < 1000) Output3 = 1000;
if (Output4 > 2000) Output4 = 2000;
else if (Output4 < 1000) Output4 = 1000;
// Si la salida es más baja de 1100 microsegundos, mantenemos los motores
corriendo a baja potencia
if (Output1 < 1100) Output1 = 1100;
if (Output2 < 1100) Output2 = 1100;
if (Output3 < 1100) Output3 = 1100;
if (Output4 < 1100) Output4 = 1100;
// Enviamos la respectiva señal a cada motor
esc1.writeMicroseconds(Output1);
esc2.writeMicroseconds(Output2);
esc3.writeMicroseconds(Output3);
esc4.writeMicroseconds(Output4);
// El programa debe correr a 250Hz. Eso significa que debemos asegurar un
ciclo cada 4ms.
while (micros() - loop_timer < 4000); //
Esperamos a que transcurran 4000us
loop_timer = micros(); //
Actualizamos el valor del timer para el siguiente ciclo
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// RUTINA DE INTERRUPCIÓN
// Esta rutina es invocada cada vez que alguno de los pines 7, 6, 5 o 4 cambia
de estado, para leer las señales del receptor.
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
ISR(PCINT2_vect){
current_time = micros();
//Channel 1=========================================
if(PIND & B10000000){ //
¿El pin 7 está ALTO?
if(last_channel_1 == 0){ //
Si cambió de 0 a 1...
last_channel_1 = 1; //
Guardar estado actual.
timer_1 = current_time; //
Guardar tiempo actual en timer_1.
}
}
else if(last_channel_1 == 1){ //
Si el pin 7 está en BAJO y pasó de 1 a 0.
last_channel_1 = 0; //
Guardar estado actual.
receiver_input[0] = current_time - timer_1; //
El valor de este canal es current_time - timer_1.
}
//Channel 2=========================================
if(PIND & B01000000 ){ //
¿El pin 6 está ALTO?
if(last_channel_2 == 0){ //
Si cambió de 0 a 1...
last_channel_2 = 1; //
Guardar estado actual.
timer_2 = current_time; //
Guardar tiempo actual en timer_2.
}
}
else if(last_channel_2 == 1){ //
Si el pin 6 está en BAJO y pasó de 1 a 0.
last_channel_2 = 0; //
Guardar estado actual.
receiver_input[1] = current_time - timer_2; //
El valor de este canal es current_time - timer_2.
}
//Channel 3=========================================
if(PIND & B00100000 ){ //
¿El pin 5 está ALTO?
if(last_channel_3 == 0){ //
Si cambió de 0 a 1...
last_channel_3 = 1; //
Guardar estado actual.
timer_3 = current_time; //
Guardar tiempo actual en timer_3.
}
}
else if(last_channel_3 == 1){ //
Si el pin 5 está en BAJO y pasó de 1 a 0.
last_channel_3 = 0; //
Guardar estado actual.
receiver_input[2] = current_time - timer_3; //
El valor de este canal es current_time - timer_3.
}
//Channel 4=========================================
if(PIND & B00010000 ){ //
¿El pin 4 está ALTO?
if(last_channel_4 == 0){ //
Si cambió de 0 a 1...
last_channel_4 = 1; //
Guardar estado actual.
timer_4 = current_time; //
Guardar tiempo actual en timer_4.
}
}
else if(last_channel_4 == 1){ //
Si el pin 4 está en BAJO y pasó de 1 a 0.
last_channel_4 = 0; //
Guardar estado actual.
receiver_input[3] = current_time - timer_4; //
El valor de este canal es current_time - timer_4.
}
last_int = current_time; //
Guardamos el tiempo de la última interrupción de cualquier pin
}
// ------------Funciones complementarias---------------
// Inicializar la IMU
void init_IMU() {
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x6B); //
Escribir al registro PWR_MGMT_1 (6B hex)
Wire.write(0x00); //
Escribir 00000000 para activar el giroscopio
Wire.endTransmission(); //
Finalizar la transmisión
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1B); //
Escribir al registro GYRO_CONFIG (1B hex)
Wire.write(0x08); //
Escribir 00001000 (Rango 500dps)
Wire.endTransmission(); //
Finalizar la transmisión
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1C); //
Escribir al registro ACCEL_CONFIG (1A hex)
Wire.write(0x10); //
Escribir 00010000 (Rango +/- 8g)
Wire.endTransmission(); //
Finalizar la transmisión
// Pequeña revisión para verificar los valores enviados
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1B); //
Leer registro 0x1B
Wire.endTransmission(); //
Finalizar la transmisión
Wire.requestFrom(IMU_ADDRESS, 1); //
Solicitar 1 byte
while(Wire.available() < 1); //
Esperar la recepción de la información
if(Wire.read() != 0x08){ //
Verificar que el valor es 0x08
while(1) delay(10); //
Quedarse en este "loop"
}
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x1A); //
Escribir al registro CONFIG (1A hex)
Wire.write(0x03); //
Escribir 00000011 (Low Pass Filter to ~43Hz)
Wire.endTransmission(); //
Finalizar la transmisión
}
// Leer la IMU
void read_IMU(){
Wire.beginTransmission(IMU_ADDRESS); //
Comenzar comunicación con la dirección de la IMU.
Wire.write(0x3B); //
Leer desde registro 3B
Wire.endTransmission(); //
Finalizar la transmisión
Wire.requestFrom(IMU_ADDRESS,14); //
Solicitar 14 bytes
while(Wire.available() < 14); //
Esperar recepción de la información
acc[0] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje x.
acc[1] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje y.
acc[2] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de acelerómetro en eje z.
temperature = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte en la variable temperature.
gyro[0] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje x.
gyro[1] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje y.
gyro[2] = Wire.read()<<8|Wire.read(); //
Concatenar low y high byte de giroscopio en eje z.
}
// Rutina de calibración
void calibrate() {
// Leemos cien datos de la IMU y obtenemos los respectivos promedios
for (int i = 0; i < 100; i++) {
read_IMU();
if (i == 0) {
goffsetX = gyro[0];
goffsetY = gyro[1];
goffsetZ = gyro[2];
}
if (i > 0) {
goffsetX = (gyro[0] + goffsetX);
goffsetY = (gyro[1] + goffsetY);
goffsetZ = (gyro[2] + goffsetZ);
}
}
goffsetX = goffsetX*0.01;
goffsetY = goffsetY*0.01;
goffsetZ = goffsetZ*0.01;
// Los valores obtenidos son el "offset" inicial de los giroscopios
Serial.print("Los offset del GYRO son: ");
Serial.print(goffsetX);
Serial.print(", ");
Serial.print(goffsetY);
Serial.print(", ");
Serial.println(goffsetZ);
// El "offset" inicial de los acelerómetros debe ser introducido arriba
manualmente, dependiendo de su calibración EN REPOSO
Serial.print("Los offset del ACC son: ");
Serial.print(aoffsetX);
Serial.print(", ");
Serial.print(aoffsetY);
Serial.print(", ");
Serial.println(aoffsetZ);
// Volvemos a leer la IMU para obtener datos promedio del acelerómetro
float acc_x = 0, acc_y = 0, acc_z = 0;
for (int i = 0; i < 10; i++) {
read_IMU();
acc_x += acc[0];
acc_y += acc[1];
acc_z += acc[2];
}
// Promedio de 10 lecturas
acc_x *= 0.1;
acc_y *= 0.1;
acc_z *= 0.1;
rawX = acc_x - aoffsetX;
rawY = acc_y - aoffsetY;
rawZ = acc_z - (4095 - aoffsetZ); // Debemos considerar la gravedad;
en este caso 1g es igual a 4095
// 1/4096 = 0.0002 (4096 es la sensibilidad según datasheet para el rango que
escogimos, usamos el inverso para multiplicar en vez de dividir)
X = rawX*0.0002;
Y = rawY*0.0002;
Z = rawZ*0.0002;
rollrad = atan(Y/sqrt(X*X+Z*Z)); // Ángulo en radianes
pitchrad = atan(X/sqrt(Y*Y+Z*Z)); // Ángulo en radianes
// 180/pi = 57.2958 (factor para convertir a grados)
angleAx = rollrad*57.2958; // Ángulo de roll en grados
angleAy = pitchrad*57.2958; // Ángulo de pitch en grados
// Inicializamos los filtros con estos ángulos
angleGx = angleAx;
angleGy = angleAy;
angleFx = angleAx;
angleFy = angleAy;
}
//--------Funciones del control PID------
void Compute() {
// Calculamos todos los errores
double error_r = Setpoint_r - Input_r;
double error_p = Setpoint_p - Input_p;
double error_y = Setpoint_y - Input_y;
ITerm_r += (ki_r * error_r);
if (ITerm_r > outMax_dif) ITerm_r = outMax_dif;
else if (ITerm_r < outMin_dif) ITerm_r = outMin_dif;
ITerm_p += (ki_p * error_p);
if (ITerm_p > outMax_dif) ITerm_p = outMax_dif;
else if (ITerm_p < outMin_dif) ITerm_p = outMin_dif;
ITerm_y += (ki_y * error_y);
if (ITerm_y > outMax_dif) ITerm_y = outMax_dif;
else if (ITerm_y < outMin_dif) ITerm_y = outMin_dif;
double dInput_r = (Input_r - lastInput_r);
double dInput_p = (Input_p - lastInput_p);
double dInput_y = (Input_y - lastInput_y);
// Calculamos la función de salida del PID.
Output_r = (kp_r * error_r) + ITerm_r - (kd_r * dInput_r);
if (Output_r > outMax_dif) Output_r = outMax_dif;
else if (Output_r < outMin_dif) Output_r = outMin_dif;
Output_p = (kp_p * error_p) + ITerm_p - (kd_p * dInput_p);
if (Output_p > outMax_dif) Output_p = outMax_dif;
else if (Output_p < outMin_dif) Output_p = outMin_dif;
Output_y = (kp_y * error_y) + ITerm_y - (kd_y * dInput_y);
if (Output_y > outMax_dif) Output_y = outMax_dif;
else if (Output_y < outMin_dif) Output_y = outMin_dif;
// Guardamos el valor de algunas variables para el próximo recálculo.
lastInput_r = Input_r;
lastInput_p = Input_p;
lastInput_y = Input_y;
}
double *SetTunings (double Kp, double Ki, double Kd) {
static double tunes[3];
int i;
if (Kp<0 || Ki<0|| Kd<0) {
tunes[0] = 0;
tunes[1] = 0;
tunes[2] = 0;
return tunes;
}
double SampleTimeInSec = ((double)SampleTime)/1000;
tunes[0] = Kp;
tunes[1] = Ki * SampleTimeInSec;
tunes[2] = Kd / SampleTimeInSec;
return tunes;
}
double *SetOutputLimits(double Min, double Max) {
static double lims[2];
if (Min > Max) {
lims[0] = Max;
lims[1] = Min;
} else {
lims[0] = Min;
lims[1] = Max;
}
return lims;
}
Paso 8: Consideraciones adicionales en el programa
Ya tenemos prácticamente listo nuestro programa en Arduino. Ya sabemos
integrar las señales de la IMU, del módulo de comunicaciones, de los
ESC/motores y ya hemos implementado nuestro sistema de control. Como
último paso es conveniente refinar un poco el código, agregando algunas
mejoras simples pero útiles, como las siguientes:
1. Una adición básica pero muy útil es una señal de indicación. Para ello,
como ya mencionamos incluiremos un LED con su respectiva
resistencia a uno de los pines del Arduino (en este caso, el 2).
Usaremos esta señal para indicar cuando el dron esté en modo espera
(luz encendida) o en modo operativo (luz apagada). Igualmente el LED
nos avisará de algún problema de comunicaciones o de batería baja.
2. Para medir el nivel de la batería es necesario usar una entrada
analógica del Arduino. El microcontrolador del Arduino incluye un
periférico llamado ADC (Conversor Analógico-Digital) por medio del cual
puede convertir este voltaje analógico en uno de sus pines dedicados
para tal efecto en un valor digital. Hay que tener en cuenta que el
voltaje de entrada está limitado entre 0 y 5 voltios. Por tanto, como ya
mencionamos ligeramente, es necesario diseñar e implementar
externamente un "divisor de voltaje", que es simplemente un arreglo de
resistencias que convierte proporcionalmente el valor de entrada en un
valor de voltaje apto para el Arduino. El valor de entrada es el voltaje de
la batería, que en el caso de una pila de Litio-ion de 3 celdas tendrá un
valor máximo de 12.4 V. El voltaje mínimo recomendable para operar la
batería es de unos 10 V, así que debemos operar en este rango. En el
código debemos configurar uno de los pines del arduino como "entrada
analógica" y leer continuamente su valor para asegurar que esté dentro
del rango permitido.
3. Otro elemento útil es tener métodos de arranque y parada seguros. No
queremos que los motores se enciendan inmediatamente conectamos la
batería, así como es necesario tener una parada "de emergencia" en
caso de que algo salga mal. Hay miles de opciones para implementar
esta funcionalidad; en este ejercicio hemos escogido hacerlo a través
de una variable ("start"), que nos indica en qué estado está actualmente
la aeronave. Definimos tres posibles estados: 0 - parado, 1 - arrancando,
2 - en operación. Establecemos un método a través del mando remoto
para entrar en cada estado: por defecto estaremos en 0, para pasar a 1
debemos hacer una combinación con la palanca izquierda de tirarla
hacia la esquina inferior izquierda (esto se traduce en potencia mínima -
1000 - y "yaw" máximo hacia la izquierda - 1000). Cuando soltemos la
palanca y el "yaw" vuelva a la posición de centrado, el dron estará en
estado operativo (2). Para volver a apagar, tiraremos la palanca hacia el
extremo inferior derecho (esto se traduce en potencia mínima - 1000 - y
"yaw" máximo hacia la derecha - 2000).
4. Para detectar un posible error o pérdida de comunicaciones hemos
implementado un "timer" que actualiza su valor cada vez que el Arduino
detecta un pulso entre 1000 y 2000 us en alguno de los pines
conectados al receptor. Si se pierde la comunicación, el receptor no
emitirá estos pulsos y por tanto el "timer" no se actualizará.
Revisaremos el estado de este "timer" en cada loop y si por alguna
razón no se ha recibido señal del receptor en los últimos 2 segundos, la
nave pasará a estado 0 inmediatamente.
5. Es aconsejable también hacer uso del "watchdog" de nuestro Arduino.
Esta herramienta consiste básicamente en un "timer" interno del
microcontrolador que se encarga de reiniciar el programa después de
algún tiempo límite en el que no se cumpla una condición. Por ello
puede ser inmensamente útil para evitar "bloqueos" en el programa
durante su ejecución. En este enlace puedes ver una sencilla
explicación del tema. La implementación del "watchdog" en nuestro
programa solo toma tres líneas simples de código para inicializarlo
primero y luego reiniciarlo al comienzo de cada ciclo, además de la
línea necesaria para incluir la librería que permite su uso.
No explicaremos en detalle el código de estas mejoras, el cual es bastante
simple y puede comprenderse correctamente a través de los comentarios
insertados en el mismo.
Paso 9: Descarga del programa, puesta a punto y pruebas
Ahora sí, nuestro programa está listo. En este enlace se puede descargar
el código completo, que incluye de manera integral todo lo que ya hemos
visto. Recomiendo leerlo, en especial los comentarios, y familiarizarse con
él y sus partes, ya que en las pruebas puede ser necesario modificar algún
parámetro y convienen saber identificar su ubicación rápidadmente. Una vez
listos, podemos proceder a descargarlo en nuestra placa Arduino.
Asegurando que tenemos la batería en un nivel aceptable de operación
(conviene tener un multímetro para este propósito), podemos ensamblar
todos los componentes faltantes sobre el marco del dron, exceptuando en lo
posible los rotores. Haremos una primera prueba de encendido y apagado
sin ellos para asegurar que el dron opere en las condiciones esperadas. El
transmisor debe encenderse primero en lo posible, y apagarse de último
también. Una vez estemos listos, podemos energizar el dron conectando la
batería a su respectivo conector. Deberíamos escuchar los pitidos de los
motores al armarse y luego deberíamos ver el LED encendido. Significa que
estamos listos y podemos proceder a manipular el dorn con el mando
remoto, recordando el procedimiento de arranque. Los motores deberían
rotar a una velocidad mínima que podemos ir aumentando con la palanca de
potencia. Podemos utilizar las demás palancas y ver como la potencia de
los motores se aplica en forma diferencial. Finalmente podemos apagar los
motores con el procedimiento que ya conocemos y desconectar la batería.
Si todo marchó bien, ahora sí es un buen momento para acoplar los rotores
a los motores, teniendo en cuenta el sentido de dirección. Es recomendable
hacer este paso al final, ya que hacer las pruebas previas de los motores
con las hélices ya puestas es peligroso para la integridad de la aeronave y
de las personas alrededor en caso de que algo no haya quedado bien (error
en el programa, problemas de conexión con algún componente, etc.). Ahora
sí estamos listos para volar la aeronave, por lo cual debemos buscar una
ubicación segura para hacerlo.
Para volar la aeronave repetiremos los pasas anteriores. Esta vez al subir la
potencia la nave debería elevarse manteniendo una actitud nivelada,
después de lo cual podemos probar los demás controles y ver la reacción
del dron ante los mismos. Si estamos satisfechos, ¡hemos terminado!
Tenemos nuestro propio dron operativo, hecho por nosotros mismos. Si el
control vibra mucho o es definitivamente inestable, debemos revisar el
programa de control y ajustar los parámetros de los controladores PID hasta
que el control sea eficiente. Los parámetros del controlador de "roll" y de
"pitch" deberían ser exactamente iguales, pues la aeronave es simétrica
respecto a los ejes x y y (de hecho al montar los componentes esta simetría
se altera ligeramente, pero no de una manera significativa, por lo que
podemos seguir asumiendo dicha simetría tranquilamente).
Una vez que todo está listo, ¡a volar se dijo!
Mira acá el video correspondiente a los pasos 7, 8 y 9 del tutorial.
Paso 10: Solución de problemas
Algún problema pudo haber surgido durante la construcción que solo vendrá
a manifestarse, como bien dicta la ley de Murphy, al final del proceso. Para
ello es conveniente revisar meticulosamente todo el proceso e identificar el
problema:
¿Están todas las conexiones bien? Se debe verificar la alimentación de
todos los componentes y la continuidad en las señales. Un solo cable
defectuoso en un componente esencial puede estropear todo el
proceso. Reitero, un multímetro viene bien para este proceso.
Si no es problema de conexiones, ¿cómo saber dónde está? En el paso 5
hemos visto cómo se integra cada componente al Arduino. Sería
recomendable aislar cada componente y repetir estas pruebas
individualmente para cada elemento, para verificar que está operando
como debe. En este caso el monitor serial de la IDE de Arduino nos es
de gran utilidad. Por ejemplo, al verificar la IMU podemos inclinar el
dron en todas las direcciones y observar si se obtiene un ángulo en la
dirección adecuada que se ajusta a la realidad. Al verificar el módulo de
comunicaciones se debe comprobar si se está recibiendo un valor entre
1000 y 2000 en cada canal según la palanca que estemos manipulando.
Igual para los motores (¡sin rotores durante las pruebas!) se puede ver
si su velocidad de rotación es proporcional al valor ingresado y si el
sentido de rotación es el esperado. Para el sistema de control en
general es un poco más complicado, pues todo debe estar montado, por
lo que lo importante es hacerlo en un ambiente seguro y variar los
parámetros de control comenzando por valores pequeños e
incrementándolos lentamente.
¿Algún otro problema? Conviene revisar los videos y enlaces auxiliares
provistos durante este tutorial, o en su defecto escribir en el foro,
donde se tratará de dar solución.
Mira acá el video correspondiente a este paso del tutorial.
DRONES PROFESIONALES
Para los lectores que han disfrutado de este tutorial y sus explicaciones
pero por alguna razón de tiempo o dedicación simplemente quieren
comenzar con un dron listo para ser volado, ponemos acá algunas
sugerencias que podrían ser de su interés.
Vale la pena mencionar que ante la enorme variedad de aparatos que se
consiguen en el mercado, con muy diferentes prestaciones y diferentes
costos, estas sugerencias, a menos que se indique lo contrario, son
sencillas, DE BAJO COSTO pero de buena calidad, y de funciones básicas.
En resumen, se orientan principalmente a los debutantes en el vuelo de
drones, aunque son accesibles para cualquier persona en general.
Syma x5C
Este Syma es una excelente opción al buscar un dron barato, tiene una
buena relación calidad-precio y es fácil de pilotar para los que quieren
iniciarse en el mundo de los drones. Se puede usar en interiores con
suficiente espacio o en exteriores en buenas condiciones ambientales.
Cuenta con una pequeña cámara incorporada que graba fotos y videos en
una tarjeta SD de 2GB.
Las funciones de vuelo son de fácil manejo y gracias a ello permite incluso
hacer piruetas con facilidad. En la parte inferior tiene luces LED para una
mejor visibilidad durante el vuelo. El tiempo de vuelo que permite la batería
(1 celda) es de unos 8 a 10 minutos, con un tiempo de carga de una hora
aproximadamente.
Consíguelo en estos enlaces para:
España: Syma x5 X5C-1 2.4 G HD Quadcopter RTF RC Helicóptero con
cámara de 2.0 MP
Estados Unidos: Syma X5C 4 Channel 2.4GHz RC Explorers Quad Copter
w/ Camera
Fig. 1 -
Syma x5C
Fig. 2 - Syma X5SW-1
Syma – X5SW-1
Siguiendo con la marca Syma tenemos este modelo algo más avanzado, que
cuenta con WIFI integrado. Se puede acoplar el teléfono móvil para ver
mientras se maneja. Cuenta con cámara HD y ofrece una buena resistencia
a los impactos, además de su flexibilidad y estabilidad de vuelo.
Consíguelo en estos enlaces para:
España: Syma X5SW/X5SW-1 versión actualizada de X5C Explorers RTF
Drone RC Airplane Flight UFO – 2,4 GHz 6 Ejes 4 Canales 3D FPV
Quadcopter
Estados Unidos: Syma X5SW-1 FPV HD Camera Drone with Real Time
Transmission in Exclusive Blue design with extra battery X5SW
Gool RC Scorpion
Es un dron bastante sencillo y compacto, no tiene cámara pero sí un un
precio ideal, perfecto para aprender a volar. Tiene buena maniobrabilidad
para volar en lugares cerrados y en el exterior si no hay mucho viento.
Incluye hélices de repuesto, batería y su respectivo cargador.
Una cualidad interesante es que ofrece un modo "retorno", con el cual el
dron regresa al sitio donde inició el vuelo. con solo presionar un botón.
Consíguelo en estos enlaces para:
España: GoolRC Scorpion T36 2.4G 4 canales 6-Axis Gyro 3D-Flip
antiaplastamiento UFO RC Quadcopter RTF Drone grandes regalos
Juguetes
Estados Unidos: GoolRC T33 WiFi FPV 720P HD Camera Quadcopter
Foldable G-Sensor Mini RC Selfie Pocket Drone Height Hold One 2
Batteries
Fig. 3 - Gool
RC Scorpion
Fig. 4 - GoolRC-JJRC
H20
GoolRC-JJRC H20
Un dron bastante interesante por su configuración tipo hexacóptero, con un
precio económico y con cámara incluida. Precisamente su configuración de
seis rotores es el punto que más resalta de este aparato, lo cual le brinda
una inmejorable estabilidad a pesar de su tamaño reducido.
También cuenta con LEDS de indicación, como otros modelos, y el siempre
útil modo de retorno a casa.
Consíguelo en estos enlaces para:
España: GoolRC-JJRC H20 Hexacopter 2.4G 4 Canales 6 Ejes RC Drone
Quadcopter con Modo sin Cabeza y una Clave Retorno Automático
Estados Unidos: GoolRC T33 WiFi FPV 720P HD Camera Quadcopter
Foldable G-Sensor Mini RC Selfie Pocket Drone Height Hold One 2
Batteries
Cheerson CX-10
Este modelo es muy popular, especialmente por su pequeño tamaño y sus
buenas cualidades. Es apropiado para interiores, aunque no incluye cámara,
por lo que es solo para practicar maniobras de vuelo.
Consíguelo en estos enlaces para:
España: Cheerson® CX-10 Mini Drone Nano Cuadricópteros RTF - 4
Canales 6 Ejes Gyro 360 Grados 2.4G RC Minicóptero con Luz LED (Azul)
Estados Unidos: Cheerson CX-10 Mini 29mm Diameter 4CH 2.4GHz 6
Axis Gyro RC Quadcopter UFO RTF Green
Fig. 5 -
Cheerson CX-10
Fig. 6 - UDI U818A HD+
UDI U818A HD+
Otro interesante dron con un buen diseño, cuenta con cámara de alta
definición y función de retorno a casa. Es controlable hasta una distancia
aproximada de unos 30 metros y cuenta con alarma de batería baja.
Consíguelo en estos enlaces para:
España: Daye Drone con cámara UDI U818A-HD 2.4GHz 4 CH 6 Axis RC
Quadcopter Drone 720P Cámara de Video HD, función de Modo de
Regreso a casa sin Cabeza
Estados Unidos: UDI U818A HD 2.4GHz 4CH 6 Axis Gyro Headless Mode
RC Quadcopter Drone w/ HD 2MP Camera, Extra Battery and Return
Home Function Black
U28W FPV
Es otro dron interesante, operable a través del teléfono móvil. Este modelo
incluye algunas funcionalidades más avanzadas, como retención de altitud,
despegue y aterrizaje con un solo botón y programación de una ruta a
seguir. Estas características son usuales en modelos más complejos (y más
caros), por lo que este aparato es una gran opción a un bajo costo.
Consíguelo en estos enlaces para:
España: riou VISUO XS812 GPS 5G WiFi FPV 1080P/720P HD cámara
Plegable RC Quadcopter Drone on Altitud Hold WiFi Cargador USB
Protector de hélice Hélice de Repuesto 5MP/2MP
Estados Unidos: Drones with Camera for Adults or Kids – U28W VR WiFi
FPV Drone with Camera Live Video, Remote Control HD Mini Camera
Drone Indoor Outdoor Quadcopter
Fig. 7 - U28W
FPV
Fig. 8 - Mokasi Mini Drone
Mokasi Mini Drone
Existen muchas opciones de mini-drones, o aeronaves de muy pequeño
tamaño, que algunos llaman "de bolsillo". Este modelo es una de tantas
opciones, con un control estilo consola de videojuegos. Cuenta con luces,
tiene un rango de unos 20 a 30 metros y una autonomía de vuelo de hasta 5
minutos. Su peso no supera los 150 gramos.
Consíguelo en estos enlaces para:
España: Mokasi® 6 Propellers Mini Pocket Drone, 2.4Ghz 4CH 6-Axis
Gyro RC Micro Quadcopter with 3D Flip, Headless Mode,Nano Copters
RTF Mode 2 Blue
Estados Unidos: Hubsan X4 H507A Pro Drone with 720P HD Camera
Headless Mode Quadcopter with GPS Modus(Version
Transmitter:HT009)
¿Qué es un dron y para qué sirve?
Características y funciones
Los drones se han convertido en parte importante para la realización de
diversas tareas en distintos ámbitos de actuación. Es por ello que cada vez
es más común ver este tipo de “vehículos voladores” entre nosotros. ¿Pero
realmente sabes qué es un dron?
Es importante conocer las características de este tipo de aeronaves no
tripuladas y comprender para qué sirven los drones, de modo que se pueda
sacar provecho de todas las funciones que éstos poseen.
Si quieres saber qué es un dron y para qué sirve, no puedes dejar de leer
este artículo en el que te explicamos a detalle todo lo relacionado a los
drones: funcionamiento, tipos y usos. De esta manera podrás aprender de
toda la información de drones que tenemos para ofrecerte en UMILES.
Índice de contenidos
¿Qué es un dron?
¿Qué es un RPA?
¿Cómo funciona un dron?
¿Para qué sirve un dron?
o 1. Drones para Filmaciones cinematográficas
o 2. ¿Para qué sirve el dron en agricultura?
o 3. ¿Para qué se usa un dron de Seguridad?
o 4. ¿Qué hacen los drones de Entretenimiento?
o 5. Control de incendios y catástrofes
o 6. Transporte de carga
o 7. Drones de uso recreativo
Partes de un dron
Características de los drones según su uso
o Drones personales
o Características de un dron profesional
o Características de los drones de pasajeros
o ¿Cómo son los drones de carga?
o 5 características de un dron de carga
¿Qué es un dron?
Antes de saber qué son los drones y para qué sirven, es importante conocer
cómo se conocen comúnmente este tipo de aeronaves. La definición de
drones puede ser muy amplia, ya que se suelen utilizar diversos términos
que engloban estos dispositivos.
Un dron es un vehículo aéreo no tripulado, es decir, que es un tipo de
aeronave que es capaz de desplazarse por el aire sin que haya un piloto a
bordo. Pueden ser controlados de manera remota, o por medio de
programación específica mediante software y GPS para que operen de
forma autónoma.
Esta es solo una definición de dron, aunque también son conocidos con el
nombre de UAV o RPA. Por esto, es necesario hacer una diferenciación
entre las características que distinguen a estos tipos de drones según sus
siglas.
¿Qué es un RPA?
Como hemos mencionado anteriormente, existen diferentes modalidades de
operatividad de los drones. Los más comunes son los RPA (Remotely
Piloted Aircraft), que son drones operados a distancia, y se definen
literalmente como aeronaves tripuladas por control remoto.
Por lo tanto, quedan excluidos de este tipo de variedad todos aquellos
drones que puedan ser configurados y que tengan autonomía para operar
sin el control directo de un piloto a distancia. Recuerda que tienes un
artículo para saber más acerca del significado RPA.
¿Cómo funciona un dron?
Los drones funcionan mediante un conjunto de motores eléctricos que
impulsan el dispositivo a través de un sistema multi-hélice que le
proporciona gran estabilidad en el momento de despegar, volar y aterrizar.
Suelen contar con baterías de gran autonomía, por lo que son capaces de
mantenerse en el aire por bastante tiempo, antes de requerir un cambio o
recarga de las baterías. De modo que son de gran utilidad para diversos
usos.
En el caso de los RPAs, son operados desde una estación remota en tierra
a través de un enlace de comunicaciones, que envía señales al dron para
que realice las maniobras que el piloto desea que ejecute.
Por otra parte, aquellos que no son controlados de manera remota, se
enlazan con un software que usa un GPS para programar vuelos
controlados y éstos operan de forma autónoma. En esta variedad se
encuentran los drones usados para la agricultura, que normalmente se
programan para que realicen diversas tareas en los cultivos (ver curso de
agricultura de precisión con drones).
Algunos de ellos cuentan con múltiples sensores que les permiten detectar
obstáculos en la ruta, capturar imágenes, hacer filmaciones con drones o
accesorios adicionales, como por ejemplo luces que permiten volar dron de
noche, de modo que su funcionamiento específico varía según sean las
características del dron.
¿Para qué sirve un dron?
Si eres de las personas que se pregunta ¿para qué se utiliza un dron? O
¿para qué sirven los drones?, te sorprenderá saber que son múltiples las
aplicaciones que se les han dado a este tipo de vehículos aéreos en la
actualidad. De hecho, son tantas las funciones de un dron, que se siguen
encontrando más usos cada día para mejorar la manera en la que se
realizan diversas actividades.
A continuación detallamos las funciones de los drones en general y
los principales usos de los drones profesionales, así como de aquellos que
se usan con fines recreacionales.
1. Drones para Filmaciones cinematográficas
Uno de los principales usos para los que sirve un dron es en el campo
cinematográfico, para lograr capturar escenas desde el aire, con visión
hacia todos los ángulos, sin ninguna interferencia y con muy poco consumo
de recursos.
Los drones para el cine facilitan el proceso de filmación aérea, ya que se
evita la movilización de helicópteros o cualquier tipo de grúa para capturar
imágenes en altura. Ahora, solo con la adaptación de un potente sistema de
cámaras y lentes se pueden obtener imágenes de calidad profesional en
poco tiempo. En UMILES GROUP somos especialistas en la filmación aérea
con drones para TV, cine y publicidad con nuestra división grabación con
drones.
2. ¿Para qué sirve el dron en agricultura?
En la agricultura se han venido optimizando distintos procesos,
automatizándolos por medio del uso de la tecnología. Por lo tanto, es común
ver que se utilicen drones para fumigar o para el riego de cultivos, los cuales
agilizan el proceso y permiten optimizar los recursos. Por tanto, este es otro
de los usos para los que sirve el dron como elemento principal de trabajo.
3. ¿Para qué se usa un dron de Seguridad?
Los drones también son especialmente útiles para el control y monitoreo de
espacios aéreos. Su portabilidad y autonomía les permiten que puedan ser
utilizados para la exploración de zonas poco accesibles desde la
perspectiva del ser humano.
4. ¿Qué hacen los drones de Entretenimiento?
Una de las aplicaciones que más llama la atención de los drones en la
actualidad, es su uso para entretenimiento masivo a través de shows de
luces. Este tipo de espectáculos con drones cada vez está más de moda y
lo puedes contratar a través de nuestra división Drone Light Show que
ofrecemos en UMILES. Sin duda, es una excelente alternativa para
celebraciones o promociones de eventos especiales.
Se pueden usar como un sustituto de los shows de fuegos artificiales, que
suelen ser muy contaminantes. Por lo que son una excelente alternativa de
entretenimiento, que ofrece una experiencia única e inigualable.
5. Control de incendios y catástrofes
Algunos drones profesionales están equipados con potentes sistemas que
les permiten transportar cargas pesadas para ayudar a combatir incendios y
catástrofes forestales. Estos ayudan a que se pueda acceder rápidamente a
la zona afectada, sin poner en riesgo la vida del piloto.
6. Transporte de carga
Según sean las características de un dron, se pueden aplicar usos
especiales que potencian los amplios beneficios de estos equipos.
Uno de los usos más recientes pero que viene ganando fuerza son
los drones de logística y transporte, que se utilizan para hacer entregas de
paquetes y despachos de mercancías. Aunque esta actividad aun no está
regulada en España, en otros países se utilizan como una alternativa de los
negocios de venta con servicio de delivery para hacer entregas rápidas y
eficientes.
7. Drone de uso recreativo
Finalmente, uno de los usos más populares de los drones es el
recreacional. Esto se refiere a quienes desean volar un dron solo como un
pasatiempo y no realizan ninguna actividad específica durante el vuelo.
Partes de un dron
Los drones están compuestos por varias partes fundamentales que
contribuyen a su funcionamiento. Desde los motores y las hélices que
generan la fuerza de propulsión, hasta los sensores y sistemas de control
que permiten la estabilidad y la navegación precisa.
Si deseas obtener más información detallada sobre las diferentes partes de
un dron y cómo cada una contribuye a su vuelo exitoso, te invitamos a leer
nuestro artículo de partes de un dron. Allí encontrarás respuestas a todas
tus preguntas relacionadas a este tema.
Características de los drones
según su uso
Hasta este punto debes tener claro qué es un drone y para qué sirve, pero
posiblemente aun no te queden claras las características de estas
aeronaves. Hay muchas formas de distinguir los tipos de drones, pero en
sentido general podemos clasificar los drones según sus características de
uso en:
Drones personales
Drones profesionales
De carga
Drones para pasajeros
Drones personales
Los drones de uso personal suelen ser los más sencillos, ya que no tienen
requerimientos específicos. Pueden ser usados únicamente con la finalidad
de vivir la experiencia de vuelo, por lo que no tienen elementos adicionales.
Muchos modelos suelen tener una cámara para hacer fotografías y
filmaciones aéreas sencillas que le permitan al usuario observar lo que le
rodea desde un punto de vista diferente.
Características de un dron profesional
Los drones profesionales suelen ser más grandes o tener mayor cantidad
de piezas para realizar una actividad específica. Estos drones sirven para
hacer múltiples tipos de actividades, y cada vez son más las tareas para las
que sirve un dron profesional.
Algunos de los elementos que caracterizan los drones profesionales son las
cámaras de alta de definición, los estabilizadores, sensores de proximidad,
entre muchos otros.
Características de los drones de pasajeros
Las características de un drone de pasajeros son diferentes a la mayoría de
UAS, ya que se trata de aeronaves diseñadas para resguardar en su interior
al pasajero con su equipaje, con capacidad para elevarse y aterrizar de
forma vertical.
¿Cómo son los drones de carga?
La principal función del dron de carga es transportar elementos de un lado a
otro, por lo que su principal característica es un cabrestante que se coloca
en el cuerpo del dron para elevar cargas de distinto peso.
Ahora que sabes qué es y para qué sirve un dron, es momento de que
tomes la decisión de probar tus habilidades con el uso de este tipo de
aeronaves no tripuladas. Solo debes ponerte en contacto con nuestro
equipo de UMILES Group, para que conozcas todos los servicios que
ponemos a tu disposición.
Y si quieres convertirte en un profesional cualificado y certificado por AESA
para trabajar en uno de los sectores con más demanda laboral del
momento, te recomendamos nuestro curso de piloto de drones profesional,
uno de los mejores cursos de piloto de drones de Madrid.
5 características de un dron de carga
Las características de los drones de carga pueden variar según el modelo y
la marca, pero aquí hay cinco características comunes que suelen tener:
Capacidad de carga: este tipo de drones están diseñados para
transportar cargas pesadas. Por lo tanto, una característica
clave es su capacidad de carga, que puede variar desde unos
pocos hasta cientos de kilogramos, dependiendo de su tamaño.
Autonomía de vuelo: Para cumplir con su propósito de
transporte de carga, deben tener baterías para drones de alta
capacidad o incluso sistemas de propulsión híbridos.
Sistemas de navegación avanzados: estos drones necesitan
sistemas de navegación sofisticados para volar de forma
autónoma y segura.
Estabilidad y resistencia: Debido a las cargas pesadas que
transportan, estos drones deben ser estables y resistentes.
Comunicación y conectividad: Los drones de carga suelen
requerir una comunicación confiable y conectividad para su
operación. Esto puede implicar la capacidad de conectarse a
redes móviles, redes satelitales o sistemas de control remoto.
Baterías para drones: Todo lo que debes
saber sobre ellas
En la actualidad, los componentes tecnológicos de los drones son muy
ligeros, siendo la batería el elemento más pesado. Las baterías para
drones son las que proporcionan la energía necesaria para que éstos
puedan volar, por lo que es importante aprender a seleccionar y cuidar
estos componentes para asegurar el máximo desempeño del dron durante
el vuelo.
Cuando la batería del dron no cumple con los requisitos del modelo, como la
duración y estabilidad del vuelo, debe reemplazarse para evitar posibles
daños al equipo. Es por ello que elegir una batería para dron debe hacerse
responsablemente, para no confundir tecnologías y características de
conexión, y así garantizar el funcionamiento del dron.
Si quieres formarte y saber más acerca de las baterías de los drones, te
recomendamos que le eches un vistazo a nuestro curso de reparación y
mantenimiento de drones.
Índice de contenidos
¿Qué tipo de batería usa un dron?
¿Cuanto tiempo tardan en cargarse las baterías para drones?
¿Cuándo es el momento de reemplazar la batería de un dron?
¿Cómo elegir la batería correcta?
Errores en la selección de baterías para drones
¿Cuántos watts consume un dron y cuánto se gasta en la recarga?
¿Qué se debe hacer con las baterías después de cada vuelo?
¿Qué tipo de batería usa un
dron?
Existen varios tipos de baterías para drones, pero la principal tecnología que
se usa para estas fuentes de alimentación es la versión de polímero de litio
(LiPo). Estas baterías son ligeras, compactas y contienen una gran cantidad
de energía a pesar de su pequeño tamaño.
Esto las convierte en las opciones ideales para los drones, ya que otro tipo
de batería que cuente con el mismo volumen de almacenamiento pesaría
varias veces más, y su instalación en un dron provocaría que el dispositivo
no despegara.
¿Cuánto tiempo tardan en
cargarse las baterías para
drones?
Responder esta pregunta de forma generalizada no es posible, ya que esto
dependerá de la cantidad de Amperios Hora (Ah) que la batería tenga y del
cargador que se utilice. Además, puede existir otra pequeña fluctuación en
el tiempo de carga de la batería, según el tipo de voltaje utilizado (110V o
220V), siendo un poco más lento el proceso de carga en una red de 110V.
Sin embargo, podemos sacar un promedio utilizando los modelos más
comunes en el mercado, estimando que el tiempo para que la batería del
dron esté totalmente cargada de 0 a 100% es de 100 minutos
aproximadamente.
¿Cuándo es el momento de
reemplazar la batería de un
dron?
Durante el vuelo, es necesario conocer cuánto dura la batería de un dron
para saber en qué momento debe ser sustituida o recargada. El momento
ideal de cambiar la batería de tu dron durante el vuelo, es cuando los
niveles de carga sean inferiores al 30% de la carga total. De esta manera se
podrá cuidar la batería del dron y extender su vida útil.
Si quieres saber cuándo es el momento ideal para reemplazar las baterías
de tu dron por unas nuevas, debes controlar el tiempo que dura la batería
en los vuelos normales. Si notas que el tiempo de permanencia continua en
el aire ha disminuido al menos un tercio de los parámetros indicados de
fábrica, entonces deberás reemplazar las baterías por unas nuevas.
Ten en cuenta que las baterías no son los únicos componentes que se
pueden reemplazar en un dron, de modo que si deseas conocer a detalle
todo lo relacionado al mantenimiento de estos dispositivos, debes ingresar a
nuestro curso especializado de montaje, reparación y mantenimiento de
drones.
¿Cómo elegir la batería
correcta?
Elegir baterías para drones es simple, siempre que tengas en cuenta los
siguientes parámetros importantes:
Lo ideal es poder reemplazar la batería con el mismo modelo
que incluye el fabricante. Por lo tanto, siempre que exista la
posibilidad de hacerlo debes tomar esta opción.
La capacidad, potencia y las características deben ser las
mismas que se indican para tu modelo de dron. Cualquier
variación puede generar incompatibilidad.
Compra modelos de marcas conocidas en el mercado, ya que
de esa forma tendrás el respaldo de una empresa constituida.
Es importante comprar baterías para drones de larga duración,
ya que existirán modelos que ofrecen las mismas
características, pero no soportan el consumo del modelo.
Es importante tomar en consideración el peso máximo que
permite el equipo, ya que no debe exceder el umbral
especificado por el fabricante para cada uno de los tipos de
drones.
Errores en la selección de
baterías para drones
Si no tomaste en consideración las recomendaciones que te hemos dado
para seleccionar correctamente la batería de tu dron, es posible que hayas
comprado un modelo que no coincida con los requerimientos del UAV. Es
por ello que a continuación te contamos 3 formas sencillas de identificar si
has cometido un error al seleccionar las baterías del dron:
1. La conexión de tu batería no coincide con la que tiene tu dron,
por lo tanto, no puedes realizar la instalación.
2. Al despegar el dron, no logra estabilizarse por una mala
distribución del peso.
3. El consumo de la batería no es el indicado por el fabricante en
el manual de uso.
¿Cuántos watts consume un
dron y cuánto se gasta en la
recarga?
A muchas personas les interesa saber cuánto gasto se genera por el
consumo energético del dron. Por ello a continuación te mostramos una
estimación en base a los modelos más básicos de baterías de drones que
hay en el mercado, para calcular el coste estimado de cargar o aumentar la
batería de un dron en España con los precios actuales de la energía de
finales de 2022.
Un modelo estándar consume en promedio 4.5 W para cargase totalmente
de 0 a 100%. Si tomamos en cuenta que el kWh en España se puede
calcular en su pico máximo del día a 0.34 euros, entonces el consumo de
4.5 w tiene un coste de 0.00153 euros.
¿Qué se debe hacer con las
baterías después de cada
vuelo?
Todo dependerá de la frecuencia con la cual se utilice el dron. Pero como
regla general, se recomienda mantener la batería del dron con una carga
entre los 40-65% de su capacidad para aumentar su vida útil. Esto aplica
especialmente para quienes almacenarán por largos periodos de tiempo el
UAV o para quienes necesiten viajar con el dron en el avión.
Además, es importante que las condiciones donde se almacena el dron
sean adecuadas, ya que los componentes no deben mojarse, no se tienen
que exponer al sol y no deben estar cerca de fuentes de calor.
Si aun no sabes cómo volar un dron y quieres especializarte en este tipo de
operaciones, te invitamos a que descubras los mejores cursos de drones de
Madrid que te ofrecemos e UMILES University, donde aprenderás junto a
profesionales expertos todo lo necesario para manipular y operar con
drones de forma segura, de acuerdo a la normativa vigente en España.
http://www.buenanueva.net/Teologia/temario.htm