Control de velocidad y giro de motores

Controlar un motor es fácil, le pasas corriente y listo, ya corre. Si quieres controlar la velocidad, es decir, que acelere, ya es un pelín más complejo, necesitas PWM, pero… si además quieres elegir en qué dirección tiene que girar, ya es la ostia necesitas lo que se denomina un puente H.

Este tutorial viene a ser una continuación del Howto ArduTanque DIY, el tanque ya está montado, falta hacer que se mueva. En este tutorial no me voy a detener en los posibles usos que se le puedan dar a un motor (desde mover ruedas u orugas a un ventilador, ducted-fan, etc), los límites los pones tu, yo sólo te voy a explicar cómo mover un motor (o varios).

Podría entrar a explicar toda la teoría de como influyen las corrientes eléctricas en el bobinado de un motor… pero ni tengo mucha idea, ni entra en el objetivo de este tutorial, así que vamos a ver directamente al tema, como controlar un motor.

Con un motor, si no necesitamos variar la velocidad ni el sentido, lo tenemos muy fácil, asignamos un pin de salida del arduino y le damos valor HIGH cada vez que lo queramos en marcha, al igual que haríamos para encender un LED.

Esquema del motor

La respuesta del motor será la misma que si lo conectáramos al pin +5V de arduino, es decir, todo o nada, va o no va.

Si utilizamos las salidas PWM del arduino, podemos variar la velocidad del motor, de forma que se multiplican las opciones para manejarlo (también se multiplica la complejidad computacional, pero hay que echarle valor, el resultado merece la pena).

Esquema del motor con PWM

Todo eso está muy bien, tiene muchas utilidades, es sencillo y es hasta chulo. . . pero yo quiero controlar un motor que se mueva adelante y atrás, para mi robot dominador del mundo.

Aquí es donde entra la electrónica como un elefante en una cacharrería, necesitamos algo más que un motor y un arduino. Concretamente, necesitamos montar lo que se denomina un puente H.

El puente H obtiene este nombre a partir de que la configuración del mismo se asemejaría a una H mayúscula. Tenemos los dos extremos superiores que son los selectores de dirección, que crean un circuito cada uno para que el motor gire en un sentido u otro. Estos circuitos se cruzan a través del motor, que está, por decirlo de alguna forma, en el palito horizontal de la H. No voy a detenerme en el funcionamiento del puente H, hay montones de esquemas que lo hacen, así que no voy a reinventar la rueda.

Para simplificar los circuitos, se utiliza un I.C. (circuito integrado), en este caso, un L293D. Este nos permite 2 puentes H independientes. El puente de diodos, en el caso del L293D no es necesario, está implementado internamente, pero en mi caso, el IC esta sobre un zócalo, por si en una de esas lo cambio por el L293B, que sí lo necesita. Nunca está de más un poco de protección extra.

 

Bueno, ahora ya tenemos el giro pero, ¿como conseguimos acelerar?

Para ello, necesitamos usar un pin del arduino con PWM para la entrada ENABLE del IC, que nos permite activar la salida hacia el motor y esto es lo que permite acelerar. Haremos un analogWrite con valor base 800 + 1/6 del valor que lea el C.A/D, sobre el pin del motor que nos interese. Este valor base nos da la frecuencia a la que debe transmitir el valor HIGH por el pin seleccionado.

El esquemático y el código para el ejemplo es el siguiente:

Muy importante, poner GNDs en común para no freir el arduino, las diferencias de los voltajes a los que trabajan el microcontrolador y los motores, pueden ser peligrosas para el arduino (y en general, para cualquier micro).

//Programa para controlar 2 motores con control de velocidad y giro con un L293
int switchPin = 7;    // switch para cambiar el sentido de giro de los motores
int motor1Pin1 = 3;   // Motor 1 adelante
int motor1Pin2 = 4;   // Motor 1 atras
int speedPin1 = 9;    // Motor 1 aceleracion (PWM) Pin enable del L293
int potPin = 0;       // Potenciometro para controlar velocidad motor 1

int ledPin = 13;      // LED 

//int switchPin2 = 8;   // No implementado
int motor2Pin1 = 5;   // Motor 2 adelante
int motor2Pin2 = 6;   // Motor 2 atras
int speedPin2 = 10;   // Motor 2 aceleracion (PWM) Pin Enable del L293
int potPin2 = 1;      // Potenciometro para controlar velocidad motor 2
int speedpin = 0;     // tasa de velocidad a la que Arduino envia los datos

void setup() {
  
Serial.begin (9600);

//configuracion de pines
pinMode(switchPin, INPUT);
//pinMode(switchPin2, INPUT); //no usado

// Control Motor 1
pinMode(motor1Pin1, OUTPUT); 
pinMode(motor1Pin2, OUTPUT); 
pinMode(speedPin1, OUTPUT);

//Control Motor 2
pinMode(motor2Pin1, OUTPUT); 
pinMode(motor2Pin2, OUTPUT); 
pinMode(speedPin2, OUTPUT);

pinMode(ledPin, OUTPUT);

// Establece speedPinX en modo High para poder controlar la velocidad
digitalWrite(speedPin1, HIGH);
digitalWrite(speedPin2, HIGH);

// comprobacion de reseteo, si el led parpadea solo 3 veces, todo esta bien
// si vuelve a parpadear, significa que ha hecho un reset, revisar conexiones
// por si hubiera un corto
blink(ledPin, 3, 100);
}

void loop() {

  //Si el switch no esta pulsado, gira en una direccion, si no en la contraria
  if (digitalRead(switchPin) >0) {
    
    digitalWrite(motor1Pin1, LOW);      // Establece el sentido de giro del motor 1
    digitalWrite(motor1Pin2, HIGH);     // 
    
    speedpin = analogRead(potPin);      // Lectura del valor del potenciometro
    speedpin = 800 + (speedpin/6);      // Para establecer la velocidad de giro
    analogWrite (speedPin1, speedpin);  //
    Serial.print("motor 1 = ");         //
    Serial.println(speedpin);           //
    delay (50);                         //
    
    
    digitalWrite(motor2Pin1, LOW);      // Establece el sentido de giro del motor 2
    digitalWrite(motor2Pin2, HIGH);     // 
    
    speedpin = analogRead(potPin2);     // Lectura del valor del potenciometro
    speedpin = 800 + (speedpin/6);      // Para establecer la velocidad de giro
    analogWrite (speedPin2, speedpin);  //
    Serial.print("motor 2 = ");         //
    Serial.println(speedpin);           //
    delay(50);                          //
  }  
  else {
    digitalWrite(motor1Pin1, HIGH);     // Establece el sentido de giro del motor 1
    digitalWrite(motor1Pin2, LOW);      // 
    
    speedpin = analogRead(potPin);      // Lectura del valor del potenciometro
    speedpin = 800 + (speedpin/6);      // Para establecer la velocidad de giro
    analogWrite (speedPin1, speedpin);  //
    Serial.print("motor 1 = ");         //
    Serial.println(speedpin);           //
    delay (50);                         //
    
    
    digitalWrite(motor2Pin1, HIGH);     // Establece el sentido de giro del motor 2
    digitalWrite(motor2Pin2, LOW);      // 
    
    speedpin = analogRead(potPin2);     // Lectura del valor del potenciometro
    speedpin = 800 + (speedpin/6);      // Para establecer la velocidad de giro
    analogWrite (speedPin2, speedpin);  //
    Serial.print("motor 2 = ");         //
    Serial.println(speedpin);           //
    delay(50);                          //
  }
}

/*
Parpadeo del led, Significa que ha ejecutado la funcion setup()
si todo va bien, solo parpadea tres veces, si hay algun error que resetee el arduino,
volvera a verse el parpadeo del led
*/
void blink(int whatPin, int howManyTimes, int milliSecs) {
  int i = 0;
  for ( i = 0; i < howManyTimes; i++) {
    digitalWrite(whatPin, HIGH);
    delay(milliSecs/2);
    digitalWrite(whatPin, LOW);
    delay(milliSecs/2);
  }
}

Para este ejemplo, controlo la velocidad de los dos motores del tanque de forma independiente con los potenciómetros, aunque la dirección en este caso sólo se controla mediante un botón, por simplicidad. Más adelante, con sensores de distancias, brújulas, sensores IR para hacer un siguelíneas, no hará falta este botón, ni los potenciómetros, por lo que es poco relevante su implementación.

Aquí un video del funcionamiento del ardutanque, ya se mueve!!! la conquista del mundo está cerca, MWHAHAHAHAHAAA!!!

El código de control del puente H está basado en el de esta página:

http://www.ecs.umass.edu/ece/m5/tutorials/H-Bridge_tutorial.html

Espero que os haya gustado.

Licencia Creative Commons
Control de velocidad y giro de motores por PepeChorva.com, a excepción del contenido de terceros y de que se indique lo contrario, se encuentra bajo una Licencia Creative Commons Attribution-ShareAlike 3.0 Unported Licencia.

17 pensamientos en “Control de velocidad y giro de motores

  1. Muy chulo, pero tengo una duda.
    Según he leído los pwm van de 0..255, y solo en algunos chips puede configurarse para que funcione de 0..1023.
    es esto así ¿
    De serlo se podría poner
    speedpin= speedpin/4
    Un saludo

    • Una pregunta: ¿Conectaste los pines de pwm de tu arduino a los enables de tu puente h respectivamente? ¿te funcionó? yo hice lo mismo pero con un picmicro, usando un sn754410, un puente h parecido el tuyo, sin embargo no me hacía las variaciones en la velocidad de giro de mis motores conectando mis salidas de pwm a los pines de enable de mi puente h, pero si me hacia el cambio de direcciones que mandaba con mi micro, de otra forma conectando mis salidas de pwm al las entradas input del puente h si me hacia las variaciones de velocidades perfectamente, el problema es que ocupando los inputs de mi puente h para el pwm no tengo para poder controlar las direcciones, en si quisiera de favor saber si tu puente h si te hace perfectamente los cambios de velocidad utilizando los enables para buscarlo y comenzar a hacer pruebas con el.

    • Bueno, la verdad que eso de dividir entre 4 es algo “burdo”, para que se vea más elegante podrías utilizar la función “MAP” para que te veas más como un programador versátil

  2. Buena pregunta, la verdad es que me has pillado :oops:
    PWM va de 0 a 255, si, o 0x00 a 0xFF en hexadecimal. Pero, si pones directamente el valor del potenciómetro en la salida PWM, solo conseguirás que el motor emita un zumbido, pero no se moverá (o al menos, eso me pasaba a mi)., Aumentando este valor, sí consigues movimiento pero, sinceramente, no entiendo el por qué.

    Tomo tu duda como un reto e intentaré averiguarlo.

  3. Bueno el proximo sabado podremos hablarlo pues voy a asistir a la reunion y aprender todo lo que pueda de los que llevais tiempo en esto.
    Un saludo.

  4. como hago para invertir elgiro de un stepper , este es mi programa para q con cada pulsacion avance un paso, pero no logro invertirlo bien, a veces da , a veces se salta, no entiendo porque
    int b1=45;
    int b2=44;
    int b3=43;
    int b4=42;
    int PinA=28;
    int PinB=29;

    byte i,j,A,B;
    int ADE[]={1,2,4,8};
    int ATRAS[]={2,1,8,4};

    void setup()
    {pinMode(b1,OUTPUT); //se define el pin b1 como salida
    pinMode(b2,OUTPUT);
    pinMode(b3,OUTPUT);
    pinMode(b4,OUTPUT);
    pinMode(PinA,INPUT);//se define el pin PinE como Entrada
    pinMode(PinB,INPUT);
    digitalWrite(PinA,HIGH); //Escribimos 1 en el pin de entrada para habilitar la resistencia en pull up interno
    digitalWrite(PinB,HIGH);

    i=0;
    j=0;
    }
    void loop()
    { byte x;
    byte y;

    A=digitalRead(PinA);//Funcion que lee el estado del pin PinE y se almacena en la variable e
    B=digitalRead(PinB);

    if (A!=HIGH) // si e es distinto de 1
    {
    x=ADE[i];
    digitalWrite(b1,ADE[i]&0x01);
    digitalWrite(b2,ADE[i]&0x02);
    digitalWrite(b3,ADE[i]&0x04);
    digitalWrite(b4,ADE[i]&0x08);

    /*digitalWrite(b1,x%2);
    x=x/2;
    digitalWrite(b2,x%2);
    x=x/2;
    digitalWrite(b3,x%2);
    x=x/2;
    digitalWrite(b4,x%2);
    */
    delay(500); // reatardo para que la bobina del motor se energize
    i++;

    if (i==4) // si se pasa del tope entonces vuelve al inicio.
    { i=0;}
    }

    if (B!=HIGH) // si e es distinto de 1
    {
    y=ATRAS[i];
    digitalWrite(b4,ATRAS[i]&0x04);
    digitalWrite(b3,ATRAS[i]&0x08);
    digitalWrite(b2,ATRAS[i]&0x01);
    digitalWrite(b1,ATRAS[i]&0x02);

    /*digitalWrite(b1,x%2);
    x=x/2;
    digitalWrite(b2,x%2);
    x=x/2;
    digitalWrite(b3,x%2);
    x=x/2;
    digitalWrite(b4,x%2);
    */
    delay(500); // reatardo para que la bobina del motor se energize
    i++;

    if (i==4) // si se pasa del tope entonces vuelve al inicio.
    { i=0;}
    }

    }

  5. Bueno, para controlar un motor stepper (paso a paso) es recomendable usar la librería stepper incluida en el IDE de Arduino.
    Quizás deberías controlar el estado del botón, porque con 500ms igual te ocurre que te hace 2 pasos seguidos.
    Se me ocurre una idea para un (o dos) post nuevos, gracias*.

    int b1=45;
    int b2=44;
    int b3=43;
    int b4=42;
    int PinA=28;
    int PinB=29;

    byte i,j,A,B;
    int ADE[]={
    1,2,4,8};
    int ATRAS[]={
    2,1,8,4};

    /**/
    int pinALastSTATE = pinBLastSTATE = LOW;

    void setup()
    {
    pinMode(b1,OUTPUT); //se define el pin b1 como salida
    pinMode(b2,OUTPUT);
    pinMode(b3,OUTPUT);
    pinMode(b4,OUTPUT);
    pinMode(PinA,INPUT);//se define el pin PinE como Entrada
    pinMode(PinB,INPUT);
    digitalWrite(PinA,HIGH); //Escribimos 1 en el pin de entrada para habilitar la resistencia en pull up interno
    digitalWrite(PinB,HIGH);

    i=0;
    j=0;
    }
    void loop()
    {
    byte x;
    byte y;

    int A=digitalRead(PinA);//Funcion que lee el estado del pin PinE y se almacena en la variable e
    int B=digitalRead(PinB);

    if(A != pinALastSTATE)
    {
    pinALastSTATE = A;
    if (readingA!=HIGH) // si e es distinto de 1
    {
    x=ADE[i];
    digitalWrite(b1,ADE[i]&0×01);
    digitalWrite(b2,ADE[i]&0×02);
    digitalWrite(b3,ADE[i]&0×04);
    digitalWrite(b4,ADE[i]&0×08);

    /*digitalWrite(b1,x%2);
    x=x/2;
    digitalWrite(b2,x%2);
    x=x/2;
    digitalWrite(b3,x%2);
    x=x/2;
    digitalWrite(b4,x%2);
    */
    delay(500); // reatardo para que la bobina del motor se energize
    i++;

    if (i==4) // si se pasa del tope entonces vuelve al inicio.
    {
    i=0;
    }
    }
    }
    if(B != pinBLastSTATE)
    {
    pinBLastSTATE = B;

    if (B!=HIGH) // si e es distinto de 1
    {
    y=ATRAS[i];
    digitalWrite(b4,ATRAS[i]&0×04);
    digitalWrite(b3,ATRAS[i]&0×08);
    digitalWrite(b2,ATRAS[i]&0×01);
    digitalWrite(b1,ATRAS[i]&0×02);

    /*digitalWrite(b1,x%2);
    x=x/2;
    digitalWrite(b2,x%2);
    x=x/2;
    digitalWrite(b3,x%2);
    x=x/2;
    digitalWrite(b4,x%2);
    */
    delay(500); // reatardo para que la bobina del motor se energize
    i++;

    if (i==4) // si se pasa del tope entonces vuelve al inicio.
    {
    i=0;
    }
    }
    }

    pinALastSTATE = A;
    pinBLastSTATE = B;

    }

    *tiene narices que el autor del blog sea quien dé las gracias a la gente para escribir cosas en él xD

  6. Que pena excelente blog, eh extraido muy buena informacion, mi duda es por que alimentas con 9V el L293D no seria mejor alimentarlo con la arduino, el no necesita tener 9V para funcionar, solo es mi unica duda.

  7. Hola Victor, el L293 lo alimento con 9V porque así alimento los motores desde el puente H, con 5V quizá no funcionarían o, seguro, rodarían a una velocidad mucho menor.
    De esta forma, además, puedes tener una pila de 9V alimentando al arduino y otra (o una batería LiPo) para los motores, separando los consumos de cada componente.

    Me alegro que te sea útil la información ;)

  8. Que buen proyecto, te felicito (y agradezco je), solo una duda, no se podria utlizar alguna configuracion para controlar en vez de usar el potenciometro para la velocidad de los motores, lo que pasa es que tengo que hacer algo parecido pero desde visual studio, y que desde una interfaz sea capaz de controlar tanto el giro como la velocidad de un motor cd, con tu proyecto me he estado dando una idea de como hacerlo, pero, ¿ No tendrias una sugerencia para alguien que empieza con arduino? Gracias y saludos

    • Gracias, me has salvado, igual no lo voy a controlar por movil, pero me voy a guiarpara ajustar el codigo. De igual manera voy a hacerlo con un motor dc, no creo que me pongan algun pero.

      Lo que habia estado pensando era utilizar la configuracion de puente h que tienes, solo con un motor, controlando el potenciometro por medio deun motor a pasos, no se que tan viable sea pero espero que funcione.

      De nueva cuenta te agradezco mucho, ysi tengo alguna duda espero contar con tu asesoramiento como lo haz hecho.

      Post data, podrias darme alguna direccion mail tuya, es que en la pc no me deja comentar en wordpress, y hacerlo desde la tablet, uff es algo laborioso mas cuando quiero mandarte el codigo que he pensado para controlar el motor

  9. Pues muchas, gracias, en cuanto pueda lo checo bien a detalle
    *solo una recomendacion o una mejor resolucion para el video o no se ._. alguna llanta que se pueda notar mas por que casi no se percibe el movimiento en el video.
    MUCHAS GRACIAS ;)

  10. Hola Kaiser, tomo nota de lo de la resolución o de destacar la rueda para el movimiento, lo grabé con un movil cuya cámara era bastante malilla.

    Gracias por la sugerencia!

  11. Holas buen blog.

    Tengo una duda estoy trabajando en un proyecto de classe donde quero conectar el andruino con un modulo PAM GPS para controlar un coche. Sabes de alguna forma en la cual pueda controlar la velocidad de los motores dependiendo de la diferencia entre las cordenandas ? Osea que si hay muchas diferencia que accelere y si hay poka que frene

Deja un comentario

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

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Powered by sweet Captcha