Curso Arduino y robótica: Motores Paso a Paso – Stepper Driver

Hace un tiempo ya explicamos en un tutorial anterior, cómo podríamos controlar motores paso a paso con un driver L298N y en otro tutorial como controlar motores DC con el mismo Driver L298N. Con la experiencia de haber probado ambos modelos de conexión, hemos llegado a la siguiente conclusión.

El driver L298N solo lo vamos a utilizar con motores de corriente continua, ya que son baratos y para obtener precisión en el control hacen falta sensores externos como realizamos en un tutorial anterior.

Los motores paso a paso sí que nos ofrecen la suficiente precisión y control de movimiento para la posición, velocidad y aceleración sin necesidad de añadir sensores adicionales. Pero si queremos explotar completamente las prestaciones de este tipo de motores, vamos a dejar de lado el driver L298N y vamos a realizar otros drivers mucho más específico para controlar.

Asi que si antes habíamos definido la norma de no usar nunca delays, ahora establecemos una nueva regla:

NO USAR EL DRIVER L298N PARA CONTROLAR MOTORES PASO A PASO EN NUESTROS PROYECTOS

Existen opciones mejores que vamos a presentar a continuación.

EasyDriver o StepStick

En un tutorial anterior, los programas de nuestros motores paso a paso debían de controlar un número diferente de salidas dependiendo del tipo de motor que tengamos. Para el motor paso a paso más común bipolar necesitabamos controlar 4 salidas con una secuencia definida.

En este caso, vamos a reducir las salidas a controlar para preocuparnos solamente de dos señales. STEP para definir el número de pasos y DIR para establecer la dirección de movimiento. El resto de las señales de salida hacia el motor las gestionará nuestro driver simplificando así nuestra programación.

 

Existen otros modelos diferentes para conectar, pero estos son los más comunes que se usan sobre todo en impresoras 3D y robótica DIY.

¿Que necesitamos?

Para este tutorial hara falta disponer de:

  • Placa Arduino
  • Motor NEMA
  • Driver de control motor paso a paso. (Stepper EasyDriver or Stepstick)
  • Fuente de alimentación de 12 V como mínimo

EasyDriver

Empezaremos explicando el modelo EasyDriver, que facilita el modelo de conexiones y podremos visualizar cómo se han de conectar los cables.

Como se puede observar, solamente nos preocuparemos en definir la dirección de giro con el pin DIR y la activación del pin STEP.

Además tenemos 2 pines de control adicionales que sirven para definir precisión en el número de pasos que es capaz de mover nuestro motor. Si realizamos la activación de estos pines podemos aumentar la precisión de 200, 400, 800, 1600 pasos por vuelta. Este factor nos proporcionará mayor precisión ya que podremos alcanzar intervalos de grados más cortos.

 

Vamos a conectar los pines de control  STEP, DIR en los pines 2 y 3 , los pines MS1 y MS2 en el 4 y el 5, y el pin ENABLE en el pin 6.

*El ENABLE tiene que estar en bajo para no bloquear el motor y que realice su movimiento. Si el motor no se mueve es posible que sea por causa de no haber conectado este pin a tierra o establecer su señal a 0V.

 



int STEP;
boolean DIR;
boolean EN;
boolean MS1;
boolean MS2;
int timeDelay;
char serialData;
int nsteps;
boolean direction;
int mode;

void setup() {
  Serial.begin(9600);
  pinMode(EN, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(STEP, OUTPUT);

  STEP = (int)(0);
  DIR = (boolean)(true);
  EN = (boolean)(false);
  MS1 = (boolean)(false);
  MS2 = (boolean)(false);
  timeDelay = (int)(1000);
  serialData = (char)(('0'));
  nsteps = (int)(0);
  direction = (boolean)(true);
  mode = (int)(0);
  digitalWrite(EN, LOW);
  digitalWrite(MS1, LOW);
  digitalWrite(MS2, LOW);

}

void loop() {
  if (Serial.available()) {
    if (serialData == ('P')) {
      nsteps = ((Serial.readString()).toInt());
      for (int count = 0; count < nsteps; count++) {
        digitalWrite(STEP, LOW);
        digitalWrite(STEP, HIGH);
        delayMicroseconds(timeDelay);
      }
      Serial.println((String("Position: ") + String(nsteps)));
    }
    if (serialData == ('D')) {
      direction = !direction;
      Serial.println((String("Direction: ") + String(direction)));
    }
    if (serialData == ('M')) {
      mode = ((Serial.readString()).toInt());
      digitalWrite(MS1, (mode % 2 == 0));
      digitalWrite(MS2, (mode / 2));
      Serial.println((String("Mode: ") + String(mode)));
    }
    if (serialData == ('T')) {
      timeDelay = ((Serial.readString()).toInt());
      Serial.println((String("Time Delay microsec: ") + String(timeDelay)));
    }
  }

}

Hemos definido el número de pasos a 200, como hemos explicado anteriormente y con la variable delayTime, definimos cuánto tarda entre paso y paso para definir más o menos velocidad por cada vuelta.

 

Stepper Driver

Los drivers StepStick se basan en el mismo modelo anterior, pero son más compactos. En esencia, se controlan mediante los mismos pines STEP y DIR y otros pines para desarrollar micropasos.

En este caso, tendremos un total de 3 pines MS1, MS2 y MS3. Anteriormente podíamos trabajar a 1600 pasos con un motor de 200 pasos activando los dos primeros pines. Ahora, podremos trabajar como máximo a 3200 pasos siguiendo el siguiente esquema de configuración de micropasos.

Aunque existen muchos tipos, nos centraremos en los modelos Pololu A4988 y aprenderemos a controlarlos mediante el siguiente conexionado.

En este diagrama, la caja definida como MicroController será nuestra placa Arduino y los pines de control son los dos pines definidos como STEP y DIR.

Necesitaremos una fuente de alimentación de 12V y con más de 1A, que se puede obtener de una fuente vieja de ordenador.

En el driver hay un potenciometro que tendremos que calibrar para dejar circular suficiente corriente al motor. Por una parte, es necesario un mínimo de intensidad para que el motor se mueva y realice fuerza en caso de mover un elemento externo. Por otra parte, si aumentamos demasiado el valor del potenciómetro, la sobreintensidad se acumulará y se liberará en forma de calor. Notaremos que nuestro driver o el motor están saturándose si escuchamos un pequeño pitido.

 

El problema del anterior programa es que no es suficiente para atender a varios motores al mismo tiempo y nos encontraremos con problemas de bloqueo y que hay que solucionar cuando queramos desarrollar movimientos dependientes uno de otro como el de una máquina láser, impresora 3D o CNC

Para ello, es necesario aplicar una estrategía antibloqueo para el movimiento. De todas formas, podemos implementar librerías que nos ahorran tiempo en el desarrollo de este tipo de programas más complejos.

 

Librería StepperDriver

La librería StepperDriver nos permite centralizar la programación para cualquier driver al que conectemos de entre los siguientes.

  • A4988
  • DRV8825
  • DRV8834
  • DRV8880

Para programar un motor paso a paso con un driver A4988, necesitaremos el siguiente programa

#include "BasicStepperDriver.h"

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
#define RPM 100
#define MICROSTEPS 2

int STEP = 2;
int DIR = 3;

BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP);

char serialData;
void setup() {
  Serial.begin(9600);
  stepper.begin(RPM, MICROSTEPS);
  stepper.enable();
}

void loop() {
  if (Serial.available()){
    serialData = Serial.read();
    if ( serialData == 'P'){
      int degrees = Serial.readString().toInt();
      stepper.rotate(degrees);
      Serial.println("Position in degrees: "+ String(degrees) );
    }
    if ( serialData == 'M'){
      int nsteps = Serial.readString().toInt();
      stepper.move(nsteps);
      Serial.println("Position in steps: "+ String(nsteps) );
    }

  }
  
}

Este programa sirve perfectamente para la configuración anterior del EasyDriver. En caso de utilizar un driver como el A4988, se nos proporcionan algunos métodos que ofrecen mayor versatilidad como el movimiento con aceleración o de velocidad constante.

#include "A4988.h"
#define MOTOR_STEPS 200
#define RPM 150
#define MICROSTEPS 1
#define ENABLE 4

int STEP = 2;
int DIR = 3;

#define MS1 10
#define MS2 11
#define MS3 12
A4988 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, MS1, MS2, MS3);

char serialData;
void setup() {
  Serial.begin(9600);
  stepper.begin(RPM, MICROSTEPS);
  stepper.enable();
  stepper.setSpeedProfile( stepper.LINEAR_SPEED );
}

void loop() {
  if (Serial.available()){
    serialData = Serial.read();
    if ( serialData == 'P'){
      int degrees = Serial.readString().toInt();
      stepper.rotate(degrees);
      Serial.println("Position in degrees: "+ String(degrees) );
    }
    if ( serialData == 'M'){
      int nsteps = Serial.readString().toInt();
      stepper.move(nsteps);
      Serial.println("Position in steps: "+ String(nsteps) );
    }

    if ( serialData == 'S'){
      stepper.stop();
      Serial.println("Stop ");
    }

    if ( serialData == 'L'){
      stepper.setSpeedProfile( stepper.LINEAR_SPEED );
      Serial.println("LINEAR SPEED " );
    }

    if ( serialData == 'C'){
      stepper.setSpeedProfile( stepper.CONSTANT_SPEED );
      Serial.println("CONSTANT SPEED" );
    }

  }
  
}

De todas formas, estos programas aún no nos sirven, ya que bloquean todo el sistema hasta que realizan todo el movimiento. Para ello, hemos de realizar un método antibloqueo en el que se desarrolle el movimiento, calculándolo en cada iteración del bucle con capacidad de atender a otras instrucciones en paralelo.


Una vez completado este tutorial, puedes acceder al siguiente nivel.

 

Los ejercicios de código, proyectos y recursos que desarrollaremos durante el curso se pueden consultar a través de nuestro Github.

Documentacion ZaragozaMakerSpace Github

Deja un comentario

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

cinco × 1 =

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.