Alguien que haya trabajado con la librería AccelStepper.h?

Hola, buenos días.

Espero que todos estén bien de salud en estos días de confinamiento;(.

Estoy trabajando en un proyecto en el que necesito coordinar distintos steppers. Estoy utilizando la librería AccelStepper.h que me facilita mucho la programación.

Estoy intentando gestionar las llamadas a la función 'stepper.moveTo(x)' de distintos steppers para que tengan un desfase controlado mediante delays, pero no el sketch no responde como yo quiero.

En lugar de activarme el stepper2 a los 3 segundos, el programa espera 3 segundos y luego me activa las funciones stepper1.moveTo(200) y stepper2.moveTo(200) simultaneamente.

if (serialData == ('3')) {
      Serial.println("HAS ENVIAT ORDRE 3");
      stepper1.moveTo(200);
      delay(3000);
      stepper2.moveTo(200);
    }

Este es el código completo con el que estoy trabajando:

  // Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library 
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support 
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"


char serialData;
Adafruit_MotorShield AFMSbot(0x64); // Rightmost jumper closed
Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
Adafruit_StepperMotor *myStepper3 = AFMStop.getStepper(200, 2);

// Connect one stepper with 200 steps per revolution (1.8 degree)
// to the bottom shield
Adafruit_StepperMotor *myStepper2 = AFMSbot.getStepper(200, 2);

// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1() {  
  myStepper1->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() {  
  myStepper2->onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  myStepper2->onestep(BACKWARD, DOUBLE);
}
// wrappers for the third motor!
void forwardstep3() {  
  myStepper3->onestep(FORWARD, DOUBLE);
}
void backwardstep3() {  
  myStepper3->onestep(BACKWARD, DOUBLE);
}

// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);

void setup()
{  
  Serial.begin(9600);
    
  AFMSbot.begin(); // Start the bottom shield
  AFMStop.begin(); // Start the top shield

  serialData = (char)(('0'));
   
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(100.0);
  stepper1.moveTo(0);
    
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(100.0);
  stepper2.moveTo(0);

  stepper3.setMaxSpeed(200.0);
  stepper3.setAcceleration(100.0);
  stepper3.moveTo(0);
}

void loop()
{
  if (Serial.available()) {
    serialData = (Serial.read());
    if (serialData == ('0')) {
      Serial.println("HAS ENVIAT ORDRE 0");
      stepper1.moveTo(0);
      stepper2.moveTo(0);
    }
    if (serialData == ('1')) {
      Serial.println("HAS ENVIAT ORDRE 1");
      stepper1.moveTo(50);
      stepper2.moveTo(50);
    }
    if (serialData == ('2')) {
      Serial.println("HAS ENVIAT ORDRE 2");
      stepper1.moveTo(50);
      stepper2.moveTo(-50);
    }  
    if (serialData == ('3')) {
      Serial.println("HAS ENVIAT ORDRE 3");
      stepper1.moveTo(200);
      delay(3000);
      stepper2.moveTo(200);
    }    
  }



      if((contador==5)&&(serialData == ('1'))){
        stepper1.moveTo(0);
        stepper2.moveTo(0);
      }
    
    
    // Change direction at the limits
    if (stepper1.distanceToGo() == 0){
       stepper1.moveTo(-stepper1.currentPosition());
   

    if (stepper2.distanceToGo() == 0)
	stepper2.moveTo(-stepper2.currentPosition());

    if (stepper3.distanceToGo() == 0)
	stepper3.moveTo(-stepper3.currentPosition());




    stepper1.run();
    stepper2.run();
    stepper3.run();
    
}

Espero que me podáis ayudar y/o proponer alguna solución.

Gracias por delante y paciencia para tod@s.

Hola @bacum, bienvenido al foro Arduino.
En la sección proyectos tienes estos dos hilos que debiste haber leído antes de postear

Como tu consulta es para otra sección lo muevo a Software.

Todo lo que hagas con delay() a la corta o a la larga trae consecuencias como las que comentas.
En su lugar usa millis() pero su uso es diferente al de delay asi que ve a Documentación => Indice de temas tutoriales => millis() y lee al respecto y luego debatimos como seguir.

Hola surbyte, muchas gracias por tu respuesta.

Disculpa que no ubicara correctamente el hilo en su sitio. Si que me leí los hilos que me comentas pero no supe donde postear; y ya veo que fallé :s.

Me reviso el tema de los millis() y vuelvo a escribir si no doy con la solución a mi problema;)

Gracias de nuevo.

Hola surbyte! Buenas noches;)

He estado estos días conociendo la función millis() como me recomendaste. He podido ver su utilidad y distintas maneras de usarla.

Entiendo que puede substituir perfectamente a la función delay(), generando muchos menos problemas y permitiendo más control y precisión en la acción que queramos temporizar.

Dicho esto, no he sido capaz de incorporarlo en mi código :confused: . He hecho distintas pruebas per no consigo activar los distintos motores de manera secuencial.

He simplificado mi código a 4 steppers de momento, para intentar tener un control a pequeña escala. Una vez sea capaz de gestionar los tiempos de activación, ya incrementaré el número de steppers.

  // Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library 
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support 
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

unsigned long t;  

char serialData;

Adafruit_MotorShield V2_02(0x61);
Adafruit_MotorShield V2_01(0x60); 

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = V2_01.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = V2_01.getStepper(200, 2);
Adafruit_StepperMotor *myStepper3 = V2_02.getStepper(200, 1);
Adafruit_StepperMotor *myStepper4 = V2_02.getStepper(200, 2);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1() {  
  myStepper1->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() {  
  myStepper2->onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  myStepper2->onestep(BACKWARD, DOUBLE);
}
void forwardstep3() {  
  myStepper3->onestep(FORWARD, DOUBLE);
}
void backwardstep3() {  
  myStepper3->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep4() {  
  myStepper4->onestep(FORWARD, DOUBLE);
}
void backwardstep4() {  
  myStepper4->onestep(BACKWARD, DOUBLE);
}


// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);
AccelStepper stepper4(forwardstep4, backwardstep4);


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

  serialData = (char)(('0'));
   
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(300.0);
  stepper1.moveTo(0);
    
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(300.0);
  stepper2.moveTo(0);
  
  stepper3.setMaxSpeed(1000.0);
  stepper3.setAcceleration(300.0);
  stepper3.moveTo(0);
    
  stepper4.setMaxSpeed(1000.0);
  stepper4.setAcceleration(300.0);
  stepper4.moveTo(0);
  
}

void loop()
{

  if (Serial.available()) {
    serialData = (Serial.read());
    if (serialData == ('0')) {
      
      Serial.println("HAS ENVIAT ORDRE 0");
      
      stepper1.moveTo(0);
      stepper2.moveTo(0);
      stepper3.moveTo(0);
      stepper4.moveTo(0);    
    }
    
    if (serialData == ('1')) {
      
        Serial.println("HAS ENVIAT ORDRE 1");
        t = millis();
        
        if (millis()-t>=5000){
          stepper1.moveTo(100);
        }
        if ((millis()-t<5000)&&(millis()-t>=10000)){
          stepper2.moveTo(100);
        }
        if ((millis()-t<10000)&&(millis()-t>=15000)){
          stepper3.moveTo(100);
        }
        if ((millis()-t<15000)&&(millis()-t>=20000)){
          stepper4.moveTo(100);
        }

      }
   }
  

    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
        stepper1.moveTo(-stepper1.currentPosition());
    
    if (stepper2.distanceToGo() == 0)
      	stepper2.moveTo(-stepper2.currentPosition());

    if (stepper3.distanceToGo() == 0)
        stepper3.moveTo(-stepper3.currentPosition());

    if (stepper4.distanceToGo() == 0)
        stepper4.moveTo(-stepper4.currentPosition());

    stepper1.run();
    stepper2.run();
    stepper3.run();
    stepper4.run();
    
}

Mi intención, con este skecth, es que al pulsar la tecla '1', el programa ejecute la primera condición, cuando millis()-t>=5000 accione sobre el stepper1. Y cada 5 segundos vaya incorporando la acción de los siguientes steppers hasta tener los 4 funcionando.

Esa sería la idea, pero al ejecutar el programa, los steppers no se mueven en ningún momento. :frowning:

No sé si voy muy desencaminado, o no he entendido correctamente el uso de la función millis().

Si puedes orientar un poco, será de mucho agradecer.

Muchas gracias por adelantado!

A ver asi, no he respetado tu criterio para la opción '1' en los tiempos

// Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

unsigned long t; 

char serialData;

Adafruit_MotorShield V2_02(0x61);
Adafruit_MotorShield V2_01(0x60);

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = V2_01.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = V2_01.getStepper(200, 2);
Adafruit_StepperMotor *myStepper3 = V2_02.getStepper(200, 1);
Adafruit_StepperMotor *myStepper4 = V2_02.getStepper(200, 2);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() { 
  myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1() { 
  myStepper1->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() { 
  myStepper2->onestep(FORWARD, DOUBLE);
}
void backwardstep2() { 
  myStepper2->onestep(BACKWARD, DOUBLE);
}
void forwardstep3() { 
  myStepper3->onestep(FORWARD, DOUBLE);
}
void backwardstep3() { 
  myStepper3->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep4() { 
  myStepper4->onestep(FORWARD, DOUBLE);
}
void backwardstep4() { 
  myStepper4->onestep(BACKWARD, DOUBLE);
}


// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);
AccelStepper stepper4(forwardstep4, backwardstep4);
byte = estado;


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

  serialData = (char)(('0'));
   
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(300.0);
  stepper1.moveTo(0);
   
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(300.0);
  stepper2.moveTo(0);
 
  stepper3.setMaxSpeed(1000.0);
  stepper3.setAcceleration(300.0);
  stepper3.moveTo(0);
   
  stepper4.setMaxSpeed(1000.0);
  stepper4.setAcceleration(300.0);
  stepper4.moveTo(0);
  estado = 0;
 
}

void loop() {
  if (Serial.available()) {
      serialData = Serial.read();
      if (serialData == '0') {
          Serial.println("HAS ENVIAT ORDRE 0");
          stepper1.moveTo(0);
          stepper2.moveTo(0);
          stepper3.moveTo(0);
          stepper4.moveTo(0);   
          serialData = 0;               // si no quieres que funciona solo una vez quita esta linea
      }

      if (serialData == '1') {
          Serial.println("HAS ENVIAT ORDRE 1");
          estado = 0;
          serialData = 0;
          flag = true;
          t = millis();
      }
  }

  if (flag) {
      estado = (millis()-t)/5000UL;  // Si millis() < 5000 da 0
                                                // si millis() >= 5000 hasta 10000 da 1 
                                                // si millis() >= 10000 hasta 15000 da 2 y asi

      switch(estado) {
              case 1: stepper1.moveTo(100);
                      break;
              case 2: stepper2.moveTo(100);
                      break;
              case 3: stepper3.moveTo(100);
                      break;
              case 4: stepper4.moveTo(100);
                      break;
              case 5: flag = false;
                      break;

      }
  }
 
  // Change direction at the limits
  if (stepper1.distanceToGo() == 0)
      stepper1.moveTo(-stepper1.currentPosition());
 
  if (stepper2.distanceToGo() == 0)
      stepper2.moveTo(-stepper2.currentPosition());

  if (stepper3.distanceToGo() == 0)
      stepper3.moveTo(-stepper3.currentPosition());

  if (stepper4.distanceToGo() == 0)
      stepper4.moveTo(-stepper4.currentPosition());

  stepper1.run();
  stepper2.run();
  stepper3.run();
  stepper4.run();
}

hola surbyte!

Muchas gracias por tu aporte, me funciona perfectamente. Con este código puedo gestionar los tiempos como quiero. GENIAL!

Me sirve a la perfección para lo que quiero hacer, pero quería saber si habría alguna manera de que los tiempos de espera pudieran ser irregulares. En tu ejemplo, serían de 5s? (Es por curiosidad porque creo que para este proyecto no lo voy a necesitar).

Por otro lado, tengo una duda respecto a la posición inicial de los steppers. Quisiera guardarme la posición calibrada en la Eeprom para que, en posibles apagones, siempre inicie la misma posición 0.

Pero no tengo claro si, trabajando con steppers, eso es posible ya que entiendo los pasos como una rueda infinita que no sé si hay manera de fijar una posición exacta en cada inicialización de la placa.

Si me puedes aclarar esta duda, será de mucho agradecer.

Gracias de nuevo!:wink:

Buenas,
me interesa también este tema, porque también tengo que trabajar con motores paso a paso en un proyecto que tengo a la vista.

¿Esta librería es también adecuada para trabajar con drivers industriales a través de las entradas digitales "clock/direction"? Me refiero a drivers que ya manejan internamente las secuencias de las bobinas y el arduino únicamente tendría que proporcionar los pulsos correspondientes a los pasos (o fracción de pasos) y la señal correspondiente a la dirección de giro.

No he visto este uso entre los ejemplos que vienen con la librería.

saludos,

hola surbyte!

siguiendo con tu propouesta, ahora estaba teniendo problemas queriendo tener distintas secuencias, según la opción elegida.

He creado una variable para guardar la opción elegida (int option) y usando una nueva estructura de 'switch', gestiono distintos 'case' según la opción que me entra por teclado.

¿Crees que es una buena opción hacerlo así?¿Puedo tener algún problema a la larga?

Te dejo aquí el código para que puedas revisar las modificaciones, GRACIAS!

// Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

unsigned long t;

char serialData;
int option;

Adafruit_MotorShield V2_02(0x61);
Adafruit_MotorShield V2_01(0x60);

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = V2_01.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = V2_01.getStepper(200, 2);
Adafruit_StepperMotor *myStepper3 = V2_02.getStepper(200, 1);
Adafruit_StepperMotor *myStepper4 = V2_02.getStepper(200, 2);


// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {
  myStepper1->onestep(FORWARD, DOUBLE);
}
void backwardstep1() {
  myStepper1->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() {
  myStepper2->onestep(FORWARD, DOUBLE);
}
void backwardstep2() {
  myStepper2->onestep(BACKWARD, DOUBLE);
}
void forwardstep3() {
  myStepper3->onestep(FORWARD, DOUBLE);
}
void backwardstep3() {
  myStepper3->onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep4() {
  myStepper4->onestep(FORWARD, DOUBLE);
}
void backwardstep4() {
  myStepper4->onestep(BACKWARD, DOUBLE);
}


// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);
AccelStepper stepper4(forwardstep4, backwardstep4);

byte estado;
boolean flag;

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

  serialData = (char)(('0'));
   
  stepper1.setMaxSpeed(1000.0);
  stepper1.setAcceleration(300.0);
  stepper1.moveTo(0);
   
  stepper2.setMaxSpeed(1000.0);
  stepper2.setAcceleration(300.0);
  stepper2.moveTo(0);
 
  stepper3.setMaxSpeed(1000.0);
  stepper3.setAcceleration(300.0);
  stepper3.moveTo(0);
   
  stepper4.setMaxSpeed(1000.0);
  stepper4.setAcceleration(300.0);
  stepper4.moveTo(0);
  estado = 0;
  flag=false;
 
}

void loop() {
  if (Serial.available()) {
      serialData = Serial.read();
      if (serialData == '0') {
          Serial.println("HAS ENVIAT ORDRE 0");
          stepper1.moveTo(0);
          stepper2.moveTo(0);
          stepper3.moveTo(0);
          stepper4.moveTo(0);   
          option = 0;
          //serialData = 0;               // si no quieres que funciona solo una vez quita esta linea
      }

      if (serialData == '1') {
          Serial.println("HAS ENVIAT ORDRE 1");
          estado = 0;
          option = 1;
          serialData = 0;
          flag = true;
          t = millis();
      }
      
      if (serialData == '2') {
          Serial.println("HAS ENVIAT ORDRE 2");
          estado = 0;
          option = 2;
          serialData = 0;
          flag = true;
          t = millis();
      }      
  }


switch(option){

  case 1:
  if (flag) {
      estado = (millis()-t)/2000UL;  // Si millis() < 2000 da 0
                                                // si millis() >= 2000 hasta 4000 da 1
                                                // si millis() >= 4000 hasta 6000 da 2 y asi

      switch(estado) {
              case 0: stepper1.moveTo(100);
                      break;
              case 1: stepper2.moveTo(100);
                      break;
              case 2: stepper3.moveTo(100);
                      break;
              case 3: stepper4.moveTo(100);
                      break;

      }
  }
  break;

  case 2:
    if (flag) {
      estado = (millis()-t)/500UL;  // Si millis() < 500 da 0
                                                // si millis() >= 500 hasta 1000 da 1
                                                // si millis() >= 1000 hasta 1500 da 2 y asi

      switch(estado) {
              case 0: stepper1.moveTo(200);
                      break;
              case 1: stepper3.moveTo(200);
                      break;
              case 2: stepper2.moveTo(-200);
                      break;
              case 3: stepper4.moveTo(-200);
                      break;
              case 4: flag = false;
                      break;

      }
  }
  break;

}
 
  // Change direction at the limits
  if (stepper1.distanceToGo() == 0)
      stepper1.moveTo(-stepper1.currentPosition());
 
  if (stepper2.distanceToGo() == 0)
      stepper2.moveTo(-stepper2.currentPosition());

  if (stepper3.distanceToGo() == 0)
      stepper3.moveTo(-stepper3.currentPosition());

  if (stepper4.distanceToGo() == 0)
      stepper4.moveTo(-stepper4.currentPosition());

  stepper1.run();
  stepper2.run();
  stepper3.run();
  stepper4.run();
}