Binary Coffee

Controlar un motor Brushless con Arduino

arduino electronic
Últimamente me he dedicado a jugar un poco con Arduino y reforzar mis conocimientos (bajos) de electrónica. Aunque más allá de encender y apagar leds no salí en buen tiempo, hace poco me encontré un lector de DVD (si, aún los hay por ahí escondidos) y lo desarmé para reutilizar sus componentes (nada espontáneo, ya había visto en miles de videos en youtube de gente haciendo cosas con ellos). Es así que me hice de los tres motores con que contaba el aparato. ![motores](https://api.binary-coffee.dev/uploads/motors_image_39c75a0978.png) Pues como puede apreciar en la imagen, estos aparatos traen 3 tipos de motores diferentes: 1. DC motor: para abrir y cerrar la torre de DVD 2. Brushless motor: el encargado de hacer girar a muchas revoluciones nuestro DVD/CD 3. Step motor: el que mueve con precisión el cabezal lector sobre el disco No pretendo explicar las diferencias entre cada uno de estos motores (es posible que luego haga un artículo sobre el tema) porque quiero centrarme en los motores *Brushless*. Los motores *Brushless* son motores que podemos controlar su velocidad de giro y su diseño está basado en imanes. Por este motivo son muy duraderos, dado que con los imanes se elimina el rozamiento (característico en otros tipos motores). Por otra parte y gracias a que no tienen este contacto, son motores con los que se pueden alcanzar altas revoluciones por segundo, convirtiéndolos en los más utilizados para drones. Pero existe un problema con estos motores: y es que no resulta tan sencillo: como conectarlos a una fuente de voltaje y que comiencen a girar. Para hacer girar un motor Brushless es necesario un controlador, y es aquí donde entra Arduino. Pretendo explicarles cómo hacer funcionar un motor Brushless con Arduino. # ¿Cómo funcionan los motores Brushless? Para explicar cómo funcionan estos motores, se hace necesario mostrar la siguiente imágen: ![Brushless motor diagram](https://api.binary-coffee.dev/uploads/brushless_animation_c3dff39def.gif) Lo que se muestra en la imágen, es la configuración de los enrollados del motor. Básicamente cada enrollado al transitar corriente por él, creará un campo electromagnético que atraerá a los imanes, y si continuamente vamos cambiando el sentido y configuración de la corriente que atraviesa dichos enrollados, lograremos hacer girar nuestro motor. La velocidad de girado está dada, por la frecuencia con que hagamos este cambio de configuraciones. A continuación una imágen del motor con el que estoy trabajando en este artículo, aunque estos pueden variar en aspecto y configuración del enrollado, pero la idea es la misma. ![motor coil](https://api.binary-coffee.dev/uploads/coil_example_9df5ccdb2a.png) # Preparando el hardware necesario Para hacer funcionar el motor necesitamos un hardware que permita transitar la corriente tanto en una dirección como en otra, para de esa manera definir el enrollado que será energizado en cada momento. Para este fin, utilizo algo conocido como un *puente H*: ![H bridge](https://api.binary-coffee.dev/uploads/bridge_H_15c93e5003.gif) Como se puede ver en la imagen, con 4 interruptores podemos hacer un puente H y determinar en qué sentido transita la corriente dentro del enrollado, invirtiendo de esta manera la polaridad del campo electromagnético. En este caso en particular como se aprecia en la imágen solo tenemos 2 entradas y 2 salidas, pero en el caso de los motores Brushless necesitamos agregar 2 nuevos interruptores para hacerlo funcionar. ## Montar el hardware Cómo los interruptores los queremos controlar por arduino, pues la mejor manera de hacer esto, es por medio de transistores. A continuación el plano del circuito que vamos a utilizar: ![circuit setup](https://api.binary-coffee.dev/uploads/circuit_image_c306c85b07.png) y puesto en práctica en mi protoboard: ![circuit in the protoboard](https://api.binary-coffee.dev/uploads/circuit_example_hardware_2ddb6ec236.png) Como se puede ver, en cada salida del puente H hemos puesto las tres entradas del motor Brushless, solo queda controlarlo con arduino. # Programando en Arduino Como se pudo notar en los pasos anteriores, necesitamos 6 puertos en total. 3 disposiciones positivas y 3 disposiciones negativas. Cada uno de estos puertos, indica entre cual de los enrollados transita la corriente y la polaridad del campo electromagnético que se forma según la dirección en que transita dicha corriente. De esta manera definimos la siguiente tabla que determina en cada momento la configuración que debe estar encendida y la representaremos con valores binarios, determinando cada uno de los 6 puertos con un bit binario y la suma de esos bit, determinará la configuración para de esta manera formar un arreglo de configuraciones que en cada ciclo harán girar el motor. ![configuration table](https://api.binary-coffee.dev/uploads/configuration_table_733db8a017.png) Una vez explicado cómo definiremos las configuraciones, ya podemos programar nuestro motor. ``` // Run brushless motor v1.0 #define len(x) (*(&x + 1) - x) // d1, d2, d5, d6, d7, d8 int PINS[6] = {5, 4, 14, 12, 13, 15}; int TWO_POW[6] = {1, 2, 4, 8, 16, 32}; int CONFIGURATION[6] = {6, 18, 24, 9, 33, 36};// the binary representation int direction = -1; int currentConfiguration = 0; void setup() { int numberOfPins = len(PINS); for (int i=0;i<numberOfPins;i++){ pinMode(PINS[i], OUTPUT); } } void loop() { updatePins(); nextStep(); delayMicroseconds(10000); } void nextStep() { int stepsLength = len(CONFIGURATION); currentConfiguration = (currentConfiguration + direction + stepsLength) % stepsLength; } void updatePins() { int currentStep = CONFIGURATION[currentConfiguration]; int numberOfPins = len(PINS); for(int i=0;i<numberOfPins;i++){ digitalWrite(PINS[i], getOutput(currentStep & TWO_POW[i])); } } int getOutput(int b) { return b ? HIGH : LOW; } ``` En el código anterior, por medio de la función *delayMicroseconds*, definimos el intervalo que esperaremos antes de cambiar a la siguiente configuración de los pines de salida. De esta manera vamos generando las modulaciones necesarias para hacer girar el motor. Pero el código anterior cuenta con una desventaja, y es que no podemos definir una velocidad mayor que 5000 microsegundos ($1 microsecond = 1 second * 10^{-6}$) para que el motor rompa la inercia (esto varía según el motor), y a partir de ahí podemos aumentar la velocidad disminuyendo los intervalos de las configuraciones. Para lograr aumentar la velocidad del motor, lo hice a partir de un decremento lineal del intervalo máximo para romper la inercia y decreciendo hasta el mínimo intervalo soportado por el motor (800 microsegundos) en donde alcanzará su velocidad de giro máxima. ``` // Run brushless motor v2.0 #define len(x) (*(&x + 1) - x) // d1, d2, d5, d6, d7, d8 int PINS[6] = {5, 4, 14, 12, 13, 15}; int TWO_POW[6] = {1, 2, 4, 8, 16, 32}; int CONFIGURATION[6] = {6, 18, 24, 9, 33, 36}; int direction = -1; int currentConfiguration = 0; double minDelay = 800; double maxDelay = 10000; double currentDelay = maxDelay; double accelerationInterval = 5000000; double slope; double initialTime; void setup() { int numberOfPins = len(PINS); for (int i=0;i<numberOfPins;i++){ pinMode(PINS[i], OUTPUT); } slope = (minDelay - maxDelay) / accelerationInterval; initialTime = micros(); } void loop() { updatePins(); nextStep(); calculateInterval(); delayMicroseconds(currentDelay); } void calculateInterval() { long delta = micros() - initialTime; if (delta <= accelerationInterval) { currentDelay = max(minDelay, delta * slope + maxDelay); } } void nextStep() { int stepsLength = len(CONFIGURATION); currentConfiguration = (currentConfiguration + direction + stepsLength) % stepsLength; } void updatePins() { int currentStep = CONFIGURATION[currentConfiguration]; int numberOfPins = len(PINS); for(int i=0;i<numberOfPins;i++){ digitalWrite(PINS[i], getOutput(currentStep & TWO_POW[i])); } } int getOutput(int b) { return b ? HIGH : LOW; } ``` > NOTA: En el ejemplo del código anterior, utilizo un Arduino modelo NodeMCU y los puertos de salida que utizo son los descritos al principio del código: *d1, d2, d5, d6, d7, d8*. Esto puede cambiar según la versión de Arduino que tengan. En mi cuenta de twitter pueden ver un video del motor en acción: <blockquote class="twitter-tweet"><p lang="es" dir="ltr">Hoy tocó hacer girar un motor brushless con Arduino. ⚙️<br><br>Q cosa más chula 🤩 <a href="https://t.co/kNoEGnoPQi">pic.twitter.com/kNoEGnoPQi</a></p>&mdash; Guillermo 🇨🇺 (@ggjnez92) <a href="https://twitter.com/ggjnez92/status/1303402674319220736?ref_src=twsrc%5Etfw">September 8, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> # Conclusiones Espero que a partir del presente tutorial puedas replicar y hacer funcionar tu motor *Brushless* con Arduino sin necesidad de controladores de velocidad o hardware semejante. Solo con 6 transistores y 6 resistencias (Y un poco de trabajo :P) ya puedes hacerlo girar. > Happy coding!!!
Opiniones
class Relacionado {
}