On two occasions I have been asked (by members of Parliament!), «Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?» I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
Charles Babbage (1791-1871), diseñador de la máquina analítica, precursora del ordenador.
Inventors and Inventions, Volume 1. Marshall Cavendish, 2007
Voy a contar cómo manejar un motor paso a paso (stepper) con Arduino a través de un driver A4988. En esta otra entrada ya expliqué cómo hacerlo con un controlador DRV8825, que es una versión mejorada del A4988 (el DRV8825 admite microstepping has 1/32, frente al 1/16 del A4988, 45V frente a 35V, y 2.5A frente a 2A).
Pololu driver A4988
Características principales del driver A4988:
Para motores bipolares
Permite microstepping de hasta 1/16
2A
Interfaz casi idéntica al DRV8825
35 V máximo
Control de corriente máxima con un potenciómetro
Nota importantísima: los datos anteriores, en especial el del límite de 2A es para los A4988 en los módulos Pololu (algo más caros). Hay una variante muy común que son los StepStick (más baratos, y seguramente es este el que tienes si lo has comprado de China). y la principal diferencia es que su límite es de 1A. Así que mucho ojito.
Stepstick driver A4988
El motor que voy a usar es un motor NEMA 17 GZGW09, comprado aquí por 13.50 €, pero valdría cualquier motor bipolar de 4 cables.
Driven X-axis and Y-axis movement, sprinkler wire wheel to scroll
Great for DIY project
Dimensions: 5.8 cm x 4.2 cm x 4.2 cm
Weight: 220 g
Para alimentar el motor empleo una fuente de alimentación de un ordenador (ver esta entrada).
Siguiendo las instrucciones de Pololu, voy a emplear el siguiente esquema de conexión, con paso completo (sin microstepping):
Empleo un Arduino Nano, pero valdría cualquier otro. Uso el pin 8 para la dirección y el 9 para el step. El esquema Fritzing sería así:
La conexión de los cables del motor al StepStick A4988 la hago así:
1A: rojo (morado)
1B: gris (gris)
2A: amarillo (blanco)
2B: verde (negro)
Para no dañar el motor tenemos que regular inicialmente el potenciómetro a la mínima potencia, girando el potenciómetro en sentido antihorario hasta el final, y más adelante ajustarlo hasta la capacidad del motor. En este vídeo se explica cómo regular adecuadamente la intensidad.
Lo primero es determinar el chip que realmente tenemos, pues cambia mucho si es un Pololu o un StepStick.
En la hoja de especificaciones se dice:
El Pololu tiene un valor de para la resistencia de censado SMD de 0.05 Ω (si se fabricó a partir de enero de 2017, entonces 0.068 Ω), mientras que en el StepStick es de 0.2 Ω. Lo mejor es mirarlo en la propia placa.
Así pues, en mi caso, tengo un StepStick (Rs= 0.2 Ω), y la intensidad máxima para mi motor de 0.84 A.
Pero ojo, el valor de la intensidad que hemos empleado antes es la máxima. En función de qué configuración de microstepping vayamos a usar, se podrá emplear otro valor.
Así, si empleamos pasos completos sin micro pasos, vemos que la tensión va variando en cada micropaso (también se puede consultar una tabla en las especificaciones):
Si emplease pasos completos y no micro pasos, entonces la tensión máxima que se entrega al motor es de un 70.71%.
Y entonces, si voy a emplear pasos completos tendré que ajustar el voltaje a:
Para medir este voltaje, lo hacemos con el multímetro sobre el potenciómetro y sobre tierra, y ajustamos el potenciómetro hasta la VREF calculada antes (0.95 V).
Ya tengo el driver ajustado a mi motor para pasos completos, así que ya puedo conectarlo y empezar a utilizarlo.
Cargando el siguiente código a Arduino, el motor da una vuelta completa en una dirección, y luego cambia de dirección y da otra vuelta:
const int dirPin = 8;
const int stepPin = 9;
const int steps = 200;
int microPausa = 1000;
void setup() {
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
}
void loop() {
digitalWrite(dirPin, HIGH); // Establezco una dirección
for (int x = 0; x < steps ; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(microPausa);
digitalWrite(stepPin, LOW);
delayMicroseconds(microPausa);
}
delay(1000);
digitalWrite(dirPin, LOW); // Cambio la dirección
for (int x = 0; x < steps ; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(microPausa);
digitalWrite(stepPin, LOW);
delayMicroseconds(microPausa);
}
delay(1000);
}
Y un vídeo mostrando el motor en movimiento con el código anterior:
Voy a contar cómo manejar un motor paso a paso (stepper) con Arduino a través de un controlador DRV8825. En esta otra entrada explico cómo hacerlo con una Raspberry Pi, de forma muy similar, y en esta hablo de varios motores y drivers.
Características principales del driver DRV8825:
Para motores bipolares
Permite microstepping de hasta 1/32
1.5 por fase o 2.2A si se dispone de ventilación forzada de aire o disipadores
Interfaz casi idéntica al A4988
45 V máximo
Control de corriente máxima con un potenciómetro
El motor que voy a usar es un motor NEMA 17 JK42HS40-1704 13A, comprado aquí por 12.50 €, pero valdría cualquier motor bipolar de 4 cables.
Características del motor:
Número de parte: JK42HS40-1704 13A
Tamaño de marco: NEMA17
Ángulo del paso: 1,8 grados
Voltaje: 3.4V
Corriente: 1,7 A/fase
Resistencia: 2,0 ohmios/fase
Inductancia: 3,0 mH/phase
Llevar a cabo el esfuerzo de torsión: 4000g-cm 58.30 OZ-IN
Inercia del rotor: 54 g-cm2
Esfuerzo de torsión de la muesca: 0,22 kilogramo-cm
Número de ventajas de alambre: 4
Peso: 0,24 kilogramos
Longitud: 40m m
Eje del motor: 5mm
Longitud del árbol delantero: 20 mm
Certificación: CE, ROHS, ISO9001
Para alimentar el motor empleo una fuente de alimentación de un ordenador (ver esta entrada).
Siguiendo las instrucciones de la página de Pololu, voy a emplear el siguiente modo de conexión, con paso completo (sin microstepping):
Empleo un Arduino Nano, pero valdría cualquier otro. Uso el pin 8 para la dirección y el 9 para el step. El esquema Fritzing de mi montaje es así:
Manejar un motor paso a paso con DRV8825 y Arduino
La conexión de los cables del motor al DRV8825 la hago así:
B2: azul
B1: rojo
A1: negro
A2: verde
Para no dañar el motor tenemos que regular inicialmente el potenciómetro a la mínima potencia, girando el potenciómetro en sentido antihorario hasta el final, y más adelante ajustarlo hasta la capacidad del motor. En este vídeo se explica cómo regular adecuadamente la intensidad, que cuento a continuación.
Empiezo con el motor desconectado. Lo primero, calculo el voltaje por cada fase. Para eso me fijo en las características de mi motor. Ahí me dicen que el motor es de 1.7 A / fase. Tendré que limitar el DRV8825 a este valor. Por encima de 1.5 A (y hasta 2.2A) el controlador DRV8825 debe tener ventilación forzada de aire o un disipador, así que le pego un disipador (me venía al comprarlo con el DRV8825), pues pretendo fijarlo en la capacidad máxima del motor.
Ahora tengo que ajustar la corriente del DRV8825 con el potenciómetro. Primero tengo que averiguar a cuánto he de limitar esa corriente. Para ello empleo la fórmula que viene en la hoja de especificaciones del driver:
Current Limit = VREF × 2
(Ojo, que por muchas páginas se ven otras fórmulas; hay que emplear la fórmula específica de nuestro driver).
Entonces:
1.7 = VREF x 2
VREF = 0.85 V
Pero ojo, este voltaje va asociado a la corriente máxima que recibirá el motor, y depende de la configuración de micropasos. Hay que consultar en la Tabla 2 de la hoja de especificaciones del DRV8825. En mi caso, con paso completo (full step), la corriente es un 71%, así que deberé multiplicar por este factor el resultado anterior:
VREF = 0.71 · 0.85 = 0.60 V
Así que el voltaje límite que debo ajustar es 0.60 V por fase.
Ahora tengo que ver dónde medir con el multímetro en el DRV8825:
Aunque es más fácil medir directamente desde el potenciómetro:
Desconecto el motor, pero alimento con 12V el DRV8825 y alimento también el Arduino a través del puerto USB. Con todo así, mido el voltaje y ajusto el potenciómetro hasta alcanzar mis VREF calculado antes (0.60 V).
Ya tengo el driver ajustado a mi motor, así que ya puedo conectarlo y empezar a utilizarlo.
Cargando el siguiente código a Arduino, el motor da una vuelta completa en una dirección, y luego cambia de dirección y da otra vuelta:
const int dirPin = 8;
const int stepPin = 9;
const int steps = 200;
int microPausa = 1000;
void setup() {
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
}
void loop() {
digitalWrite(dirPin, HIGH); // Establezco una dirección
for (int x = 0; x < steps ; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(microPausa);
digitalWrite(stepPin, LOW);
delayMicroseconds(microPausa);
}
delay(1000);
digitalWrite(dirPin, LOW); // Cambio la dirección
for (int x = 0; x < steps ; x++) {
digitalWrite(stepPin, HIGH);
delayMicroseconds(microPausa);
digitalWrite(stepPin, LOW);
delayMicroseconds(microPausa);
}
delay(1000);
}
Y un vídeo mostrando el motor en movimiento con el código anterior: