Hoy voy a explicar el mismo procedimiento que seguimos con el control de un servomotor, pero esta vez utilizaremos un motor paso a paso. La diferencia entre un servomotor y un motor paso a paso, aunque su principio de funcionamiento sea el mismo, es la forma de sumininistrar la información necesaria para su giro. Un servomotor requiere de una señal PWM para girar en un rango, que suele estar limitado entre 0 y 180 grados.

Y digo que suele estar comprendido entre ese rango porque viene limitado por un tope mecánico y por un potenciómetro interno para su control, que algún día manipularemos para obtener un servomotor multivuelta. Por lo que ahora solo consideraremos que los servomotores solo pueden girar una vuelta… o menos. El número de cables necesarios para controlarlos son 3, el de alimentación, tierra y el de la señal PWM.

Los motores paso a paso pueden ser de varios tipos. Pero para empezar podemos decir que son multivuelta, por lo que no podemos controlarlo con una señal PWM que nos ofrece una referencia absoluta para el giro, sino que informamos cuántos grados queremos que gire de forma relativa.

Es decir, a un servo le informamos que gire a un ángulo de 60º (respecto a la referencia de 0º). Y para girar en la dirección contraría le diremos que gire a la posición absoluta -60º. A un motor paso a paso le diremos que gire 60º respecto a la posición desde la que estaba y es acumulativa. No tiene definida una posición absoluta, por lo que si necesitamos de un control preciso deberemos añadirlo nosotros mediante algún tipo de sensor (usualmente un encoder).

Para controlar un motor paso a paso, necesitaremos de dos señales digitales, una que indique la dirección de giro. Si está en alto se moverá en una dirección y si está en bajo en la dirección contraria. La otra señal es un tren de impulsos que definirá por pasos el ángulo que queremos girar.

A todo esto… un paso se define como la precisión que tiene el motor en su giro para una vuelta. Por ejemplo un motor de 200 pasos es el número de pasos en que se divide una vuelta de 360º. Por lo que un paso corresponden con un giro de 1,8º. Y esa es la resolución del motor que obtendremos.  Las cantidades más comunes de grados por paso son: 0,72º, 1,8º, 3,6º, 7,5º, 15º, incluso de 90º, por lo que cuanto más pequeño sea, más precisión obtendremos.

Los cables de alimentación de un motor paso a paso vienen por pares, que alimentan las bobinas internas suelen ser de 2 para motores unipolares o 4 para bipolares. Las distintas combinaciones en la activación de estos cables ofrecen los giros distintos. Arduino posee una librería para motores paso a paso llamada Stepper. Estas funciones son aplicables cuando conectamos directamente el motor al arduino, pero nosotros usaremos un controlador. Este controlador nos facilitará mucho trabajo si queremos limitar la corriente y no dañar ningún elemento adicional o nuestra placa Arduino, ya que algunos motores paso a paso requieren 12 V de alimentación que Arduino no soporta. Con un controlador también podemos aumentar la resolución y mejorar el control.

En el ejemplo que proponemos utilizamos un motor NEMA 14 bipolar y un controlador A4988. Para conectar necesitaremos de una placa entrenador donde situaremos el controlador y le conectaremos una fuente de alimentación, el motor paso a paso y la placa Arduino que será la encargada de transmitir la información de giro. Los pines del controlador vienen definidos en la siguiente imagen.

Controller A4988

En esta imagen podemos ver que la alimentación suministrada al motor irá a VMOT que en nuestro caso serán 12 V y la alimentación VDD de 5 V. El cuadrado definido como microcontroller que se conecta a los pines STEP y DIR es nuestra placa Arduino y el motor paso a paso son las dos bobinas definidas en los pines 1A, 1B, 2A y 2B.

Los pines en gris definidos como MS1, MS2, MS3 sirven para aumentar la resolución del motor, pero por ahora no los utilizaremos.

Una vez conectado todo introducimos el siguiente código que he copiado desde esta página.


#define STEP 11
#define DIR 12

void setup(){
   pinMode(DIR,OUTPUT);/*Indicamos que los pines son de salida */
   pinMode(STEP,OUTPUT);
   digitalWrite(DIR,HIGH);/*Fijamos una direción */

   for(int i=0; i<200; i++){/*Mandamos pulsos al motor en concreto 2000 */
      digitalWrite(STEP,HIGH);
      delay(1);
      digitalWrite(STEP,LOW);
      delay(1);
   }

   delay(500);/*Esperamos medio segundo*/
   digitalWrite(DIR,LOW);/*Cambiamos la dirección de giro */

   for(int i=0; i<200; i++){/*Hacemos 200 pasos en sentido contrario */
      digitalWrite(STEP,HIGH);
      delay(1);
      digitalWrite(STEP,LOW);
      delay(1);
   }

}

void loop(){ /*No hacemos nada para ejecutar el programa de nuevo pulsamos el boton*/
}

Ahora añadiremos la acción de un potenciómetro para definir el ángulo que queremos girar, indicando la diferencia detectada desde el pin analógico y mediante un for actualizamos en el loop el valor de giro.

/*Control motor paso a paso con potenciometro*/

#define STEP 11
#define DIR 12

int pf,pi,DP;
int potPin = 2; /* seleccionamos pin para el potenciometro*/
float val=0;
float value;

void setup(){
   pinMode(DIR,OUTPUT);/*Indicamos que los pines son de salida */
   pinMode(STEP,OUTPUT);
   Serial.begin(9600);
   Serial.println("Potentiometer");
   pi=PotRange(0,360,value);
   pf=pi;
   DP=pf-pia
}

void loop(){

   val = analogRead(potPin); /* leemos el valor del potenciometro*/
   value=val/1023;
   delay(5);
   pf=PotRange(0,200,value);
   Serial.println(pf); /*print to serial monitor
to see number results*/
   DP=pf-pi;

   if (DP!=0){
       Serial.println("Valor diferencial");

      if(DP>0){
         digitalWrite(DIR,HIGH);/*Fijamos una direción */
      }else{
         digitalWrite(DIR,LOW);/*Cambiamos la dirección de giro*/
         DP=-DP;
      }
   for(int i=0; i<DP; i++){/*Mandamos pulsos al motor en concreto 2000*/
      digitalWrite(STEP,HIGH);
      delay(1);
      digitalWrite(STEP,LOW);
      delay(1);
   }
   /*Serial.print("Valor pi: ");
   Serial.print(pi);
   Serial.print(" Valor pf: ");
   Serial.println(pf);
   Serial.println(DP);*/
   pi=pf;

   }
   delay(100);
}

int PotRange(int init, int final,float value){
   int result;
   float aux;
   aux=final-(final-init)*value;
   result = (int) aux;
   return result;
}

Después de todo este rollo, se puede hacer uso de una función definida dentro de las librerias que vienen por defecto llamada map.

Esta librería realiza una interpolación entre dos rangos de datos y cuyo valor introducido es nuestro mismo valor leido por el potenciómetro.

 

/*Control motor paso a paso con potenciometro*/

#define STEP 11
#define DIR 12

int pf,pi,DP;
int potPin = 2; /* seleccionamos pin para el potenciometro*/
float val=0;
float value;

void setup(){
   pinMode(DIR,OUTPUT);/*Indicamos que los pines son de salida */
   pinMode(STEP,OUTPUT);
   Serial.begin(9600);
   Serial.println("Potentiometer");
   pi=0;
   pf=pi;
   DP=pf-pi;
}

void loop(){

   val = analogRead(potPin); /* leemos el valor del potenciometro*/
   delay(5);
   pf=map(val, 0 , 1023, 0, 200);
   Serial.println(pf); /*print to serial monitor
to see number results*/
   DP=pf-pi;

   if (DP!=0){
       Serial.println("Valor diferencial");

      if(DP>0){
         digitalWrite(DIR,HIGH);/*Fijamos una direción */
      }else{
         digitalWrite(DIR,LOW);/*Cambiamos la dirección de giro*/
         DP=-DP;
      }
   for(int i=0; i<DP; i++){/*Mandamos pulsos al motor en concreto 2000*/
      digitalWrite(STEP,HIGH);
      delay(1);
      digitalWrite(STEP,LOW);
      delay(1);
   }
   /*Serial.print("Valor pi: ");
   Serial.print(pi);
   Serial.print(" Valor pf: ");
   Serial.println(pf);
   Serial.println(DP);*/
   pi=pf;

   }
   delay(100);
}