Motor DC – Driver L298N
Nuestro arduino /genuino, no tiene la potencia necesaria para mover un motor, o encender una bombilla de 12 V y no digamos controlar un motor trifásico.
Anteriormente hemos trabajado con motores paso a paso y ahora vamos a trabajar con motores DC que son más fáciles de poner en funcionamiento. Vamos a trabajar con un driver específico , el L298N que se puede usar con motores, tanto de corriente continua, como motores de pasos.
Motores DC
Empezando por lo básico, la definición de un motor eléctrico es un dispositivo capaz de convertir la corriente eléctrica en movimiento. Esta definición es general y nos servirá para ver ciertas características comunes, como es la potencia requerida para el control del mismo.
Arduino puede trabajar con un máximo de 100 mA ( que es insuficiente para mover motores de alta velocidad ), y los motores más básicos de juguetes ya son capaces de usar 1 amperio, u otros tipos de motores hasta 2 y 4 amperios.
Para el control sencillo de motores de escobillas y motores paso a paso vamos a usar un controlador basado en un integrado L298N bastante común y sencillo de trabajar
El driver L298N que consiste en un puente H, capaz de controlar 2 motores de corriente continua como se puede ver en la siguiente imagen.
El controlador L298N permite trabajar con voltajes desde los 5 v a los 35v y con intensidades de de hasta 2 A, pero nunca superando los 25 W.
Por un lado recibe la alimentación que dará potencia a los motores (ya sea una pila, batería) por otro lado también recibe la alimentación de 5v para el control de la electrónica.
Si recordamos los tutoriales anteriores de control de servomotores y control de motores paso a paso las señales que se utilizaban, eran una señal PWM en un solo pin de salida digital para servomotores; mientras que los motores paso a paso requerían de 4 salidas digitales que se activan y desactivan en un orden específico.
Para el caso de los motores de corriente continua, necesitaremos 2 pines de salida digitales con capacidad de transportar una señal PWM.
Si realizamos el montaje de la figura anterior, veremos que hemos conectado los pines a los pines 5 y 6 para un motor de corriente continua y 9 y 10 para un segundo motor DC con capacidad de suministrar señal PWM.
En este contexto, podemos realizar el siguiente ejercicio, básico de funcionamiento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | void setup() { pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); digitalWrite(5, HIGH); digitalWrite(6, LOW); digitalWrite(9, LOW); digitalWrite(10, HIGH); } void loop() { } |
Si nos fijamos bien, este ejercicio, hará que nuestros motores giren en sentido contrario, uno respecto de otro.
Además lo harán a la velocidad máxima que les permite el controlador, ya que uno de los pines esta continuamente en activo, mientras que el segundo pin esta en voltaje bajo.
IMPORTANTE: La potencia que se le suministra al motor es proporcional a la diferencia de voltaje. Es decir, que si los dos pines están en alto, el motor no se moverá, debido a que la diferencia de voltajes es cero, aunque aparentemente parezca que le suministramos potencia.
Para extender un poco el control, vamos a realizar un modelo de control por serie.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | char serialData; void setup() { Serial.begin(9600); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(9, OUTPUT); pinMode(10, OUTPUT); serialData = ( char )(( '0' )); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); } void loop() { if (Serial.available()) { serialData = (Serial.read()); if (serialData == ( 'A' )) { digitalWrite(5, HIGH); digitalWrite(6, LOW); } if (serialData == ( 'D' )) { digitalWrite(5, LOW); digitalWrite(6, HIGH); } if (serialData == ( 'S' )) { digitalWrite(5, LOW); digitalWrite(6, LOW); } if (serialData == ( 'W' )) { digitalWrite(5, HIGH); digitalWrite(6, HIGH); } } } |
Con este programa, si accedemos al monitor serie, podemos comprobar que las teclas «W» (2 pines en alto ) y «S» (2 pines en bajo ) no moverán los motores, mientras que las teclas «A» y «D» moverán el motor a máxima velocidad en una y otra dirección.
Recibe las entradas de información desde el arduino que indica la velocidad y sentido de giro, dependiendo de la señal enviada.
Control de velocidad
Una de las cuestiones que queremos abordar, es cómo podremos definir la velocidad para que nuestro coche no salga disparado en el momento que lo conectemos. Puesto que podemos usar una señal PWM, con esta misma conexión de pines, vamos a definir la potencia suministrada a los motores con este modelo de señal que utilizábamos anteriormente en servomotores.
Y nos dará la señal aumentada con la potencia necesaria para mover los motores. Hay que tener en cuenta que la señal PWM en su salida digital, el máximo valor es igual a 255.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | char serialData; int pin1; int pin2; int value; void setup() { Serial.begin(9600); pinMode(pin1, OUTPUT); pinMode(pin2, OUTPUT); serialData = ( char )(( '0' )); pin1 = ( int )(5); pin2 = ( int )(6); } void loop() { if (Serial.available()) { serialData = (Serial.read()); if (serialData == ( 'A' )) { value = ( int )(((Serial.readString()).toInt())); analogWrite(pin1, value); analogWrite(pin2, 0); Serial.print( "Forward: " ); Serial.println(value); } if (serialData == ( 'D' )) { value = ( int )(((Serial.readString()).toInt())); analogWrite(pin1, 0); analogWrite(pin2, value); Serial.print( "Backward: " ); Serial.println(value); } if (serialData == ( 'S' )) { digitalWrite(pin1, LOW); digitalWrite(pin2, LOW); } if (serialData == ( 'W' )) { digitalWrite(pin1, HIGH); digitalWrite(pin2, HIGH); } } } |
De esta manera podremo escribir una letra de movimiento seguida de un número con máximo de 255 para mover el motor a distintos puntos de velocidad. A50, A100, A150, A200, D50, D100, D150, D200… y la tecla S y W para pararlo.
Desarrollo de funciones para movimiento de dos motores DC
El modelo de robot más común para usar este tipo de motores es el de un coche que requiera de dos ruedas y de esta manera definir los movimientos de del coche en base a la sincronización de estos dos motores hacia delante, atrás, izquierda y derecha.
Es por ello, que vamos a conectar ambos motores sobre un chasis con ruedas para poder hacerlo funcionar. Estas funciones para mover el coche se basan en el modelo anterior de activación de pines y se desarrollan tal y como se ve en la figura dentro de la sección car control.
Una vez definidas las funciones, desarrollamos el control serie para cada movimiento dentro del bucle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | char serialData; int value; int vel; int M11=5; int M12=6; int M21=9; int M22=10; void move( int S11, int S12, int S21, int S22){ analogWrite(M11,S11); analogWrite(M12,S12); analogWrite(M21,S21); analogWrite(M22,S22); } // Describe this function... void stop() { move(0, 0, 0, 0); } // Describe this function... void forward( int vel) { move(0, vel, vel, 0); } // Describe this function... void backward( int vel) { move(vel, 0, 0, vel); } // Describe this function... void left( int vel) { move(vel, 0, vel, 0); } // Describe this function... void right( int vel) { move(0, vel, 0, vel); } void setup() { Serial.begin(9600); pinMode(M11,OUTPUT); pinMode(M12,OUTPUT); pinMode(M21,OUTPUT); pinMode(M22,OUTPUT); serialData = ( char )(( '0' )); } void loop() { if (Serial.available()) { serialData = (Serial.read()); if (serialData == ( 'W' )) { value = ( int )(((Serial.readString()).toInt())); forward(value); Serial.print( "Forward: " ); } if (serialData == ( 'S' )) { value = ( int )(((Serial.readString()).toInt())); backward(value); Serial.print( "Backward: " ); } if (serialData == ( 'A' )) { value = ( int )(((Serial.readString()).toInt())); left(value); Serial.print( "Left: " ); } if (serialData == ( 'D' )) { value = ( int )(((Serial.readString()).toInt())); right(value); Serial.print( "Right: " ); } if (serialData == ( 'Q' )) { stop(); Serial.print( "Stop" ); } Serial.println(value); } } |
Control de calibración
Una de las desventajas asociadas a este tipo de motores, como consecuencia de su bajo coste, es el control de velocidades para un valor definido.
Tenemos que asumir que los motores DC no son todos iguales y que de la misma manera que los servomotores, para un mismo valor en una dirección y en otra se van a comportar de manera diferente.
En el caso de que nuestro modelo de robot no necesite de precisión en el control de posición y velocidad, este caso no nos debería preocupar, pero la mayor consecuencia de este caso es el de querer mover dos ruedas con dos motores distintos en el que uno se mueve más rápido que el otro.
Resultado – El coche empieza a girar de forma relativa, aún a pesar de que le hemos dicho que vaya hacia delante.
Para revisar este caso, podemos usar el monitor serie y definir valores para revisar, en qué momento pasa de estar parado a comenzar el movimiento con dos ruedas montadas sobre un chasis.
Este caso, lo solucionaremos más adelante en el siguiente tutorial de control de posición y velocidad con un Encoder Wheel.
Los ejercicios de código, proyectos y recursos que desarrollaremos durante el curso se pueden consultar a través de nuestro Github.