En este ejemplo haremos que el eje de un motor paso a paso siga al potenciómetro.
Para controlar el motor, nos ayudamos del circuito integrado L293D.
#include <Stepper.h>
// change this to the number of steps per revolution on your motor
#define STEPS 200
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 8, 9, 10, 11);
// the previous reading from the analog input
int previous = 0;
void setup()
{
// set the speed of the motor to 30 RPMs
stepper.setSpeed(30);
}
void loop()
{
// get the sensor value
int val = analogRead(0);
// move a number of steps equal to the change in the
// sensor reading
stepper.step(val - previous);
// remember the previous value of the sensor
previous = val;
}
En el siguiente ejemplo vamos a controlar dos motores paso a paso a la vez, cada uno con diferente velocidad y aceleración.
Para ello vamos a utilizar un shield para motores.
Si se van a utilizar fuentes de alimentación independientes para Arduino y para los motores, hay que quitar el jumper.
En mi caso he utilizado 5V del conector USB para alimentar Arduino y una batería de 6V para los motores.
Los motores empleados son 24BYJ48.
Aquí hay información detallada del shield empleado en este tutorial. Si vais a utilizar éste circuito, recomiendo leer detenidamente el datasheet del mismo así como las instrucciones de puesta a punto y manejo del mismo.
// MultiStepper
// -*- mode: C++ -*-
//
// Control both Stepper motors at the same time with different speeds
// and accelerations.
// Requires the AFMotor library (https://github.com/adafruit/Adafruit-Motor-Shield-library)
// And AccelStepper with AFMotor support (https://github.com/adafruit/AccelStepper)
// Public domain!
#include <AccelStepper.h>
#include <AFMotor.h>
// two stepper motors one on each port
AF_Stepper motor1(64, 1);
AF_Stepper motor2(64, 2);
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {
motor1.onestep(FORWARD, SINGLE);
}
void backwardstep1() {
motor1.onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() {
motor2.onestep(FORWARD, SINGLE);
}
void backwardstep2() {
motor2.onestep(BACKWARD, SINGLE);
}
// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
void setup()
{
stepper1.setMaxSpeed(400.0);
stepper1.setAcceleration(100.0);
stepper1.moveTo(1024);
stepper2.setMaxSpeed(400.0);
stepper2.setAcceleration(100.0);
stepper2.moveTo(1024);
}
void loop()
{
// Change direction at the limits
if (stepper1.distanceToGo() == 0)
stepper1.moveTo(-stepper1.currentPosition());
stepper1.run();
stepper2.run();
}
Con el mismo circuito anterior, vamos a modificar el código para hacer que los motores cambien el sentido de giro a la vez.
Una aplicación de este ejemplo la tenemos en el proyecto 14, con este código podemos hacer avanzar y retroceder al robot.
Las constantes pos1 y pos2 = 4096 representan el número de pasos que gira el eje del motor, o la distancia que recorrería el robot.
#include <AccelStepper.h>
#include <AFMotor.h>
// two stepper motors one on each port
AF_Stepper motor1(64, 1);
AF_Stepper motor2(64, 2);
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {
motor1.onestep(FORWARD, SINGLE);
}
void backwardstep1() {
motor1.onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() {
motor2.onestep(FORWARD, SINGLE);
}
void backwardstep2() {
motor2.onestep(BACKWARD, SINGLE);
}
// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
int pos1 = -4096;
int pos2 = 4096;
void setup()
{
stepper1.setMaxSpeed(400);
stepper1.setAcceleration(200);
stepper2.setMaxSpeed(400);
stepper2.setAcceleration(200);
}
void loop()
{
if (stepper1.distanceToGo() == 0)
{
pos1 = -pos1;
stepper1.moveTo(pos1);
}
if (stepper2.distanceToGo() == 0)
{
pos2 = -pos2;
stepper2.moveTo(pos2);
}
stepper1.run();
stepper2.run();
}
Con el mismo circuito, vamos a modificar el código para hacer que los motores cambien el sentido de giro por separado, de esa forma hacemos que el robot gire 90º, por ejemplo para evitar un obstáculo.
Las constantes turn1 y turn2 = 512 representan el número de pasos para efectuar un giro de 90º. Modificando este valor podemos hacer que el robot gire el ángulo deseado. Vemos como los motores paso a paso ofrecen una gran precisión de movimientos.
#include <AccelStepper.h>
#include <AFMotor.h>
// two stepper motors one on each port
AF_Stepper motor1(64, 1);
AF_Stepper motor2(64, 2);
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {
motor1.onestep(FORWARD, DOUBLE);
}
void backwardstep1() {
motor1.onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() {
motor2.onestep(FORWARD, DOUBLE);
}
void backwardstep2() {
motor2.onestep(BACKWARD, DOUBLE);
}
// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
int pos1 = 8000; // 4 turns
int pos2 = -8000; // 4 turns
int turn1 = 512; // 1/2 turn
int turn2 = 512; // 1/2 turn
boolean turn = false;
void setup()
{
stepper1.setMaxSpeed(600);
stepper1.setAcceleration(300);
stepper2.setMaxSpeed(600);
stepper2.setAcceleration(300);
}
void loop()
{
if ((stepper1.distanceToGo() == 0) && turn==false)
{
turn=!turn;
stepper1.move(pos1);
stepper2.move(pos2);
}
if ((stepper1.distanceToGo() == 0) && turn==true)
{
turn=!turn;
stepper1.move(1050);
stepper2.move(1050);
}
stepper1.run();
stepper2.run();
}
Adafruit: Motor Shield