PROLOGO.
Este artículo, se puede considerar como una aplicación que puede ser puesta en práctica, de la teoría que se describe, en la que se emplean dos motores de corriente continua cuya aplicación puede responder a la necesidad de un proyecto, utilizando su propia placa PCB o si se prefiere a un pequeño robot, en la que adquirir cierta experiencia en esta materia.
También se puede aplicar, sobre la placa de utilidad que, se encuentra en este mismo sitio, con el nombre escudo Arduino, principalmente debido a que está basado en la creación de una tarjeta con los conectores dispuestos de tal manera que ésta tarjeta, se pueda conectar directamente en el soporte del propio Arduino, digamos a lomos del mismo.
EL CIRCUITO L293.
El circuito integrado en el que nos basaremos es el L293b, en sus hojas de datos, podemos ver que, está compuesto por cuatro amplificadores con salida triestado, capaz de proporcionar una corriente de salida de hasta 1A por canal a tensiones de alimentación desde 4’5V a 36V y con una entrada habilitable (chip Enable) que permite un control de salida de dos amplificadores. Todas sus entradas son compatibles TTL. En el L293b, se deben utilizar diodos de alta velocidad externos, en la salida, para la supresión de transitorios inductivos. En la figura que sigue, se puede apreciar la tabla de la verdad, con la cual debe familiarizarse para tener un conocimiento más amplio de como se comporta este circuito.
Según las especificaciones el L293b es un integrado monolítico de alta tensión, controlador de 4 canales, de alta corriente. Cada canal es controlado por señales de entrada compatibles TTL y cada pareja de canales dispone de una señal de habilitación que desconecta las salidas de los mismos. Básicamente esto significa que utilizando este chip, puede utilizar motores de corriente continua y fuentes de alimentación de hasta 36 voltios, esos son motores muy grandes y el chip puede suministrar una corriente máxima de 1A por canal. El chip L293b es también lo que se conoce como un tipo de puente H (H-Bridge).
Según el diagrama, este chip pone a nuestra disposición dos brazos idénticos e independientes. Cada uno, consta de dos amplificadores comandados por una línea de control (EN), con la cual habilitamos el par de amplificadores que nos interese en cada momento. Esta disposición, permite distintos montajes para un motor o más motores, como veremos. Es necesario resaltar la existencia en el mercado de dos versiones L293B y L293D, dos diferencias entre ambas, en la versión B, no lleva diodos ‘clamp’ internos (se puede utilizar un pequeño puente en los terminales del motor), sin embargo, admite hasta 1Amperio de consumo, en el caso de la versión D, sólo entrega 600mA, llevando los diodos internos. El usuario debe tomar la decisión de cual utilizar.
El esquema que utilizaremos, está basado en la aplicación del circuito integrado L293b, que como se aprecia en las hojas del fabricante, es un driver de 4 canales, con él y unos pocos componentes más, podemos controlar fácilmente el giro de un motor o dos motores de corriente continua, con distintos circuitos de montaje. Además, también se puede controlar un motor bipolar paso a paso.
No debemos olvidar:
- Refrigerar en lo posible este circuito integrado, ya que puede adquirir bastante temperatura, compruebe este dato, si va a aplicar de forma continuada este chip.
- Utilice un pequeño puente tipo W01F, para evitar disgustos con las tensiones inducidas del motor.
EL ESQUEMA ELÉCTRICO.
El circuito eléctrico en el que nos basaremos es el recomendado por el fabricante del IC y que es mostrado en la siguiente figura. Podemos distinguir dos pares de amplificadores con salidas triestado, con un control habilitador (EN) común para ambos, cuyas propiedades descubriremos más adelante. Por el momento nos ocuparemos de la parte sencilla.
INICIO SENCILLO.
La figura anterior es bastante explicita. Muestra dos montajes distintos como ya he mencionado. Vamos a empezar por el control de un motor de juguete M1. En este ejercicio, he supuesto que no es necesario utilizar el chip L293, ya que, en muchos casos, no tendremos que desembolsar el costo del circuito integrado, con un pequeño transistor podemos salir al paso.
Las salidas de Arduino, sus pines son ideales para controlar directamente los pequeños elementos eléctricos, como los LED. Sin embargo, cuando se trata de dispositivos de consumos más grandes (como un motor de juguete o el de una máquina de lavar), es necesario un controlador externo. Un transistor es increíblemente útil. Se obtiene una gran cantidad de corriente con una, mucho menor. Un transistor tipo NPN, conectaremos la carga (M1) al colector del transistor y el emisor al negativo o masa. Así, cuando la señal alta del pin de nuestro Arduino alcance la base, fluirá una pequeña corriente por R1 (1K) de la base al emisor y la corriente a través del transistor fluirá y el motor girará.
Hay miles de transistores del tipo NPN, que se adaptan perfectamente a todas las situaciones. Como voy a utilizar la tensión de 6V de un cargador que tengo a mano, he elegido el BC337 un transistor común de uso general. Los factores más relevantes en nuestro caso es que la tensión máxima (45 V) y su corriente media (600 mA) son lo suficientemente alta para nuestro motor de juguete. En cuanto al diodo 1N4001 está actuando como un diodo de seguridad.
Veamos una aplicación sencilla, en la que utilizaremos un código de los muchos que existen en la red. Esto es un programa rápido para probar el circuito:
Código control motor CC
Código sencillo para mover un motor con intervalos de parada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// // motorcc.pde // const int transistorPin = 9; // connected to the base of the transistor void setup() { // set the transistor pin as output: pinMode(transistorPin, OUTPUT); } void loop() { digitalWrite(transistorPin, HIGH); delay(1000); digitalWrite(transistorPin, LOW); delay(1000); } |
En este ejemplo, vemos que pertenece a un circuito sencillo, con el cual hacemos girar un motor de corriente continua, con intervalos de parada. Debido a lo sencillo del mismo, observamos que no se tiene ningún control sobre el motor. Tendría más aplicaciones si pudiéramos, poner en marcha con un interruptor, modificar la dirección de giro y poder variar la velocidad de giro.
Control de un motor CC.
Motor de CC con un potenciómetro para cambiar su velocidad.
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 |
// // motordc.pde // int pot = 2; // asigna pin analógico 2 para el pot int motorPin = 9; // motor en el pin 9 PWM void setup() // ejecutar una vez, cuando empieza { Serial.begin(9600); // establecer la librería serie a 9600 bps pinMode(pot, INPUT); pinMode(motorPin, OUTPUT); } int getPot() { int v; v = analogRead(pot); v /= 4; v = max(v, 50); v = min(v, 255); return v; } int motorForward() { analogWrite(motorPin, getPot()); delay(10); digitalWrite(motorPin, LOW); } void loop() { // ejecutar una y otra vez motorForward(); } |
Para controlar esto desde el exterior, se puede utilizar un pot en un puerto analógico para variar el número de grados e incrementar su barrido. Puede hacer la práctica, copie el código o bájelo de aquí y cárguelo en el IDE, para ver su efectividad.
Qué ocurre. El motor gira desde un mínimo de velocidad hasta el máximo según giremos el pot, sin embargo, se observa que el motor pierde fuerza de torsión (par motor, torque en inglés), esto puede ser debido en parte, al transistor que utilicemos, pero es más propio que sea debido al código del programa que no se adecua a lo que esperábamos. Debemos pensar en otro método para lograr nuestro propósito.
Este es un código bastante bueno, para el control de un motor de corriente continua que, se comporta muy parecido al código anterior.
Control motor con pot.
Movimiento del motor con potenciómetro mejorado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// // Funccion: CC_motor_control_pot // // Utilizar un potenciometro para controlar motor CC // int sensor_pin = 2; // debe ser una entrada analógica int motor_pin = 9; // debe ser una salida digital PWM. void setup() { Serial.begin(9600); pinMode(motor_pin, OUTPUT) } void loop() { int pot_val, motor_speed; pot_val = analogRead( sensor_pin ); motor_speed = pot_val*255.0/1024.0; // Incluir decimal /* Sutil: No utilice valores enteros como 255 y 1024 aquí. Compiladores agresivo pre-cálculo la división entera del 255/1024 como cero. */ analogWrite( motor_pin, motor_speed); // hacer cosas útiles } |
Indagando sobre el tema, he llegado a encontrar una función reutilizable para actualizar la velocidad del motor, veamos unas cuestiones a tener en cuenta. El ajuste de la velocidad del motor se establece dentro del lazo loop(), en realidad la parte más relevante se encuentra en el llamado map (), donde los valores leídos del potenciómetro se escalan a la salida.
Así pues, necesitamos …
UNA FUNCIÓN PARA TRADUCIR LAS ESCALAS LINEALES.
El escalado lineal de los valores de x para valores de y:
y = f(x)
donde f es un mapeado lineal.
Es decir, dados: x, xmin, xmax, ymin e ymax. Calcular y
UNA FUNCIÓN PARA TRADUCIR LAS ESCALAS LINEALES.
Entradas que necesitamos: pin de potenciómetro sensor, pin de salida del motor.
Que tareas vamos a abordar:
- Leer tensión del potenciómetro.
- Convertir voltaje con escalas de 10 bits a 8 bits PWM y
- Cambiar la velocidad del motor.
Introduzca el código de la parte inferior en su boceto. Observe que, el código no está dentro de ningún bloque de otro programa [como setup() o void()], es parte de una función. ¿Cómo comprobar que esta función está funcionando?
int int_scale(int x, int xmin, int xmax, int ymin, int ymax) {
int y; y = ymin + float(ymax – ymin)*float( x – xmin )/float(xmax – xmin);
return(y);
}
Este código, es esencialmente una reimplementación integrada de la función map, por los creadores del Arduino. Ver http://arduino.cc/en/Reference/Map
Nota.-
int – Devuelve un entero.
int_scale – Es el nombre de la función.
int x – Es la primera entrada llamada x.
float – Se usa float para una mejor precisión.
return(y) -Devuelve el valor almacenado en y.
Funciones que llaman a otras funciones:
(int x, int xmin, int xmax, int ymin, int ymax);
motor_speed = int_scale(int x = pot_val, int xmin = 0, int xmax = 1024, int ymin = 0, int ymax = 255);
Donde: return(y) = motor_speed
A continuación, a modo de ejemplo, veremos un código que usa la función int_scale.
Control motor con potenciómetro.
Nuevo ejemplo.
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 |
// // Funccion: CC_motor_control_pot // // Utilizar un potenciometro para controlar motor CC int sensor_pin = 2; // debe ser una entrada analógica int motor_pin = 9; // debe ser una salida digital PWMt void setup() { Serial.begin(9600); pinMode(motor_pin, OUTPUT) } void loop() { int pot_val, motor_speed; pot_val = analogRead( sensor_pin ); motor_speed = int_scale( pot_val, 0, 1024, 0, 255; analogWrite( motor_pin, motor_speed); } int int_scale(int x, int xmin, int xmax, int ymin, int ymax) { int y; y = ymin + float(ymax - ymin)*float( x - xmin )/float(xmax - xmin); return(y); } |
Si comprueba este código, observará que el incremento de velocidad propuesta por el potenciómetro, se percibe como una continuidad lineal. Esta es la mejora esperada.
CONTROL EL CIRCUITO INTEGRADO L293.
Hemos probado a utilizar un transistor a la salida de un pin de Arduino y no hemos quedado satisfechos con los resultados. Cabe la posibilidad de utilizar dos transistores en sendos pines, cada cual conduciría un borne del motor, como diría, el motor entre dos pines, pero no quiero perder más tiempo. Es el momento de utilizar el L293, en una de las aplicaciones que vienen en las hojas de especificaciones.
Además con el L293, no tiene que preocuparse por la regulación de una tensión mayor, ya que permite dos fuentes de energía – una fuente directa, hasta 36 V para los motores y otra de 5V, para controlar el CI que, puede ser conectada a la fuente de alimentación ya que el suministro de alimentación del motor proviene es independiente. En el circuito de abajo, se supone una alimentación superior para el motor. A continuación se puede ver la disposición de las conexiones para el chip y el motor. La tabla de verdad muestra la lógica de la salida.
El puente H, es normalmente un circuito eléctrico que permite aplicar un voltaje a través de una carga en cualquier dirección a una salida, por ejemplo, motor. Esto significa que esencialmente puede invertir la dirección de la corriente y por lo tanto invertir la dirección del motor. Lo único que a de recordar es que, la conexión a tierra debe ser compartida, común para ambas fuentes.
En este circuito que sigue, no se trata más que de un control bidireccional, por lo tanto, no se hace necesario el puente H, lo que resulta más sencillo en todos los sentidos. Si nos fijamos en la tabla de verdad que aparece arriba, quedan claras las opciones que nos presenta, he de resaltar que la entrada EN (patilla 1), puede ser definitoria.
Veamos cómo es esto, en cualquier momento. Si se aplica un 1 lógico sobre A1, en la entrada A2, tenemos que aplicar un 0 lógico, esto hará girar el motor en un sentido predeterminado. Para cambiar el sentido de giro, y respetando las reglas de la mecánica, primero pondremos A1 y A2 en un mismo estado lógico y acto seguido invertiremos el estado inicial, es decir, A1 en 0 lógico y A2 en 1 lógico.
Con independencia del estado lógico de las entradas A1 y A2, si es necesario detener el motor, simplemente enviamos un estado lógico bajo (0) a la patilla EN y el motor se para de inmediato. En estas condiciones no es posible mover el motor, no hasta que, a dicha entrada EN, le enviemos un 1 lógico, en ese momento, podemos decidir el sentido de giro o la parada del mismo con los valores lógicos que apliquemos a las patillas A1 y A2. Aunque, lo esencial de esta entrada EN, es que si aplicamos una salida PWM a ella, simplemente podremos regular la velocidad del motor, esta es su funcionalidad. Ver el esquema eléctrico.
Por seguridad, recomiendo que, conecte una fuente externa de alimentación de corriente continua a la entrada de alimentación externa de Arduino, así, puede alimentar el motor y el Arduino. Además, puede dejar conectado el cable USB, para una fácil y rápida reprogramación, si fuera necesaria. De esta forma, cualquiera que sea el motor que utilice, se asegura que la fuente de alimentación es compatible, naturalmente, no utilice un motor de 5V con una alimentación de 12V.
EL CÓDIGO.
La teoría es bastante sencilla. Se trata de poner, un estado lógico 1 en la entrada A1, al mismo tiempo que en la A2 ponemos un 0 lógico. El código para este caso es sencillo, veamos un ejemplo:
Control de motor con potenciómetro.
Controlar el giro de un motor de CC mediante un L293.
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 |
/* * motorpwmpot.pde * * Hace girar un motor de CC mediante un L293 conectado a los pines * 7 y 8 controlando la velocidad por PWM sobre el pin Enable del L293 * en base a la lectura del potenciometro conectado al pin 2 analógico * * Basado en un código de: Miguel Grassi * www.miguelgrassi.com.ar * * Modificado por: V. García el 07.02.2011 * */ int ledPin = 13; // LED conectado al pin digital 13 int pinA1 = 7; // entrada Motor A 1 int pinB1 = 8; // entrada Motor B 1 int pinEN1 = 9; // entrada EN 1 int pinPot = 2; // Lectura analógica del Potenciometro int valorPot= 0; int valorVeloc = 0; void setup() { // Inicializa los pines de salida pinMode(ledPin, OUTPUT); pinMode( pinA1, OUTPUT); pinMode( pinB1, OUTPUT); pinMode(pinEN1, OUTPUT); pinMode(pinPot, INPUT); digitalWrite(pinEN1, HIGH); // linea es la clave, RPA Serial.begin(9600); // El LED parpadea 3 veces. Esto debería ocurrir sólo una vez. // Si usted ve el parpadeo del LED tres veces, significa que // se restablecio (reset) el propio módulo. Probablemente porque // el motor provocó una bajada de voltaje o un corto. blink(ledPin, 3, 100); } void loop() { digitalWrite( pinA1, HIGH); // Valores ALTO en A y BAJO en B simulaneamente digitalWrite( pinB1, LOW); // hacen girar el motor 1 hacia ADELANTE valorPot = analogRead(pinPot); // Lee el valor del potenciometro valorVeloc = map(valorPot, 0, 1023, 55, 255); //Convierte un valor entre 0 y 1023 al rango 0-255 // valorVeloc = valorPot / 4 ; // segunda opción analogWrite(pinEN1, valorVeloc);// y establece la velocidad del motor con ese valor } /* blinks an LED */ void blink(int whatPin, int cuantoTiempo, int milliSecs) { for (int i = 0; i < cuantoTiempo; i++) { digitalWrite(whatPin, HIGH); delay(milliSecs/2); digitalWrite(whatPin, LOW); delay(milliSecs/2); } } |
El código está bastante bien descrito y no considero necesario entrar en mayores detalles. Copie el código o si lo prefiere, bájelo de aquí y cárguelo en el IDE, para comprobar su efectividad.
He realizado este ejemplo, utilizando un escudo para Arduino, realizado con placa de tiras preformada, como se puede apreciar en la imagen de abajo, el esquema utilizado corresponde a la imagen anterior. Sigue una demo del resultado obtenido.
Vídeo.
EL L293.
El circuito integrado L293B, es un driver de 4 canales, capaz de proporcionar una corriente de salida de hasta 1A por canal. Cada canal, se puede controlar por señales de entrada compatibles TTL y cada par de canales dispone de una señal de habilitación que desconecta las salidas de los mismos.
Ahora, vamos a ocuparnos del código necesario para controlar un motor de corriente continua con Arduino. He decidido probar una idea para que los que tengan interés en hacer su primer mini robot, empiecen con una experiencia que les anime y levante la moral.
La idea es que con un motor de juguete, movamos el eje delantero de una pequeña caja, cualquier recinto pequeño nos puede servir, en esta, tiene que alojar las cuatro pilas de 1’5V con su porta pilas, el propio Arduino, el motor, el soporte del eje y una rueda de giro libre en todas direcciones. Algo parecido a la imagen.
Las fotos, aunque corresponden a otro ejercicio (cosa que no es relevante), dan una idea de lo que se describe. La práctica demostrará cómo mover un objeto (bot-tarrina), con un sólo motor y un interruptor del tipo ‘bumper’. Cuando conectemos la tensión, el Arduino mandará una señal al motor para que gire, por un tiempo, lo que hará avanzar el pequeño robot. Cuando éste, encuentre un obstáculo, lo detectará con el interruptor que tropezará con el objeto estático, esto producirá una señal/orden en el programa, de modo que el motor cambiará su dirección de giro por un tiempo determinado, tras el cual volverá a girar en la dirección de inicio. Las direcciones son mecánicamente, bastante aleatorias.
Sólo se trata de un ejemplo, de como manejar un pequeño robot con un mínimo de componentes. En posteriores artículos hablaremos con más profundidad de las posibilidades del L293 en los motores paso a paso. El siguiente es el código que se encarga de realizar estos cambio de desplazamiento. El código como se hace notar, lo he adaptado a mis necesidades, con un pequeño cambio.
Control motor con Puente-H.
Código mejorado para el control de un motor de corriente continua, con control de velocidad por potenciómetro.
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 |
/* Control de un motor DC con puente H * motorL293h.pde * * http://itp.nyu.edu/physcomp/Labs/DCMotorControl * Modificado por V. Garcia el 08.02.2011 * Puede adaptarse a un bot con un motor en las ruedas de traccion * y una rueda de giro libre que pivote cambiando la direccion */ int switchPin = 2; // entrada del switch int motor1Pin = 7; // pin 1 del L293 int motor2Pin = 8; // pin 2 del L293 int speedPin = 9; // pin enable del L293 int ledPin = 13; //LED void setup() { // pone el switch como una entrada pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // pone todos los otros pines usados como salidas pinMode(motor1Pin, OUTPUT); pinMode(motor2Pin, OUTPUT); pinMode(speedPin, OUTPUT); pinMode(ledPin, OUTPUT); // activa la RPA del pin speedPin para activar el motor digitalWrite(speedPin, HIGH); // El LED parpadea 3 veces. Esto debería ocurrir sólo una vez. // Si usted ve el parpadeo del LED tres veces, significa que // se restablecio (reset) el propio módulo. Probablemente porque // el motor provocó una bajada de voltaje o un corto. blink(ledPin, 3, 100); } void loop() { // si el switch es high, motor gira en una direccion if (digitalRead(switchPin) == HIGH) { digitalWrite(motor1Pin, LOW); // pone motor1 del H-bridge low digitalWrite(motor2Pin, HIGH); // pone motor2 del H-bridge high } // si el switch es low, motor gira en la otra direccion: else { digitalWrite(motor1Pin, HIGH); // set leg 1 of the H-bridge high digitalWrite(motor2Pin, LOW); // set leg 2 of the H-bridge low blink(switchPin, 2000, 2); // si pulsas switch cambia giro un tiempo } } /* blinks an LED */ void blink(int whatPin, int cuantoTiempo, int milliSecs) { int i = 0; for ( i = 0; i < cuantoTiempo; i++) { digitalWrite(whatPin, HIGH); delay(milliSecs/2); digitalWrite(whatPin, LOW); delay(milliSecs/2); } } |
Una vez más, si lo desea, puede copiar y pegar este código, dele un nombre y cárguelo en su IDE Arduino.
En los ejercicios que se han desarrollado en este documento, aunque hemos utilizado el circuito integrado L293, tan sólo se ha empleado un amplificador de los cuatro para manejar el motor, o dos amplificadores, uno para cada devanado del motor. La parte más relevante de este circuito integrado, está en utilizar los cuatro amplificadores de forma que se conoce como Puente-H.
Después de lo tratado hasta el momento, en este documento, estamos preparados para comprender y emprender el montaje del L293 en puente-H, para el control de un motor. Es cierto que el control de motores, también se puede conseguir con un circuito integrado como es el ULN2003 que integra una matriz de siete transistores darlington, capaces de entregar hasta 500mA cada uno y la versión ULN2803, con una matriz de ocho transistores darlington. Este último, se utiliza en los casos que se tienen que controlar más de un motor y sobre todo, con motores unipolares.
Los motores que hemos manejado hasta el momento son motores de corriente continua (DC), en próximos artículos desarrollaremos controles para motores paso a paso bipolares y unipolares. El control de un motor unipolar, es más sencillo que el del motor bipolar, debido a la manera de energizar los devanados.
hola saludos no he trabajado con arduino comprare uno y ya te comentare que resultados tengo…..yo trabajo con microcontroladores de micro chip ….no creo que tenga mucha diferencias ……
Te puede ser muy interesante, hay diferencias entre ambos, aunque la idea viene siendo la misma. Arduino dispone de un lenguaje basado en C++ y el PIC es algo más próximo al máquina.
Espero te guste y te impliques.
Saludos.
Hola Alfonso, espero te sirva.
Gracias.
M parece muy interesante lo probare gracias