multi Stepper control issues

My program requires the control of 2 stepper motors running at different speeds and distances. stepper1 needs to run at a designated speed and designated distance. stepper2 needs to run at a designated slower speed, a designated distance and then reverse and run to 0 position repeatedly until stepper1 reaches its designated distance. The code listed works for all aspects except I haven't found a way to designate a distance for stepper1. If I try to set moveTo() using runSpeed() on stepper1 it doesn't run. If I use moveTo() and run() it also doesn't move. I am using the AccelStepper.h library and an UNO with 8825 drivers. Any help/suggestions would be appreciated.

if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == StepVal2))
    stepper2.moveTo(0);
  stepper2.run();

  if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == 0))
    stepper2.moveTo(StepVal2);
  stepper2.run();
  stepper1.runSpeed();

You need to post the complete program. The problem is usually in the other part - which is why you have not found it :slight_smile:

In the snippet you have posted you have not even included the code where stepper1 is given a destination.

...R

Case 5 has what should be the reversal code, but when the data for establishing moveTo() and speeds is provided, this code runs at the proper speeds, but stepper2 does not reverse. This code now runs with a moveTo() value for stepper1 and stepper1 runs the proper distance and stops. I just need to get stepper2 to reverse at the moveTo() value of 800 (1 revolution).

//modified to facilitate using for automatic coil winding machine

//------------------------------- librarys ----------------------------------
#include <AccelStepper.h>
#include <LiquidCrystal_I2C.h>
//#include <Wire.h>
//#include <rgb_lcd.h>
//#include <Servo.h>

//------------------------------- lcd ----------------------------------
//rgb_lcd lcd;
LiquidCrystal_I2C lcd(0x20, 16, 2);

//------------------------------- stepper 1 and 2 ----------------------------------
AccelStepper stepper1 = AccelStepper(1, 7, 8);
AccelStepper stepper2 = AccelStepper(1, 9, 10);
long StepVal2 = 800;       //moveTo variable-Revolutions=StepVal/800 for 1/4 step
long StepVal1;
float sps1;                    //Steps per second-sets speed-stepper1
float sps2;                 //Steps per second-sets speed-stepper2 
int move_finished = 1;
//------------------------------- servo ------------------------------------------
//Servo snippers;
//#define servo 10
//#define openAngle 90
//#define closedAngle 0

//------------------------------- input ------------------------------------------
//Use A0 to A3 for stepper interface board layout.
#define leftButton A0
#define upButton A1
#define downButton A2
#define rightButton A3

//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
//unsigned int wireQuantity = 0;
float wireSize = 0;
//-------------------------------Stepper 1 Speed variables----------------------------
int SpdSet = 60;
float ratio;

//-------------------------------Stepper 2 Speed variables--------------------------



//------------------------------- system settings --------------------------------
int state = 0;
int incrementSpeed = 1;
unsigned int previousWireLength = 0;
float previousWireSize = 0;
int previousSpdSet;

//float mmPerStep = 0.18096;
//float mmPerStep = 0.02127;      //base on 1/8 step
//float mmPerStep = 0.0431984;      //base on 1/4 step
float mmPerStep = 0.0431984;      //2.3578 turns per inch based on 1/4 step, 6/32 core size
void setup() {
  Serial.begin(9600);
  lcd.begin(); //LCD columns and rows
  //lcd.setRGB(255,255,0); //backlight colour

  stepper1.setMaxSpeed(1600.0);    //Top speed limit=150rpm
  stepper1.setAcceleration(1600.0);
  //stepper1.setSpeed(-sps1);        //speed = DESIRED_RPM * STEPS_PER_REV / 60

  stepper2.setMaxSpeed(1600.0);   //Top speed limit=150rpm
  stepper2.setAcceleration(1600.0);

  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);

}

void loop() {
  if (!digitalRead(rightButton)) {
    if (state == 6) {
      state = 0;
    }
    else {
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 5) {
    state -= 1;
    delay(200);
    lcd.clear();
  }


  switch (state) {
    case 0:
      homeScreen();
      break;
    case 1:
      SetSpeed();
      break;
    case 2:
      chooseWireLength();
      break;
    case 3:
      //state = 4;
      chooseWireSize();
      break;
    case 4:
      confirm();
      if (StepVal1 == 0)                            //If no length was entered goto finishedCutting()
        state  = 6;
      break;
    case 5:                                         //coil wind routine using 2 steppers
      //lcd.setCursor(0, 0);
      //lcd.print("Spd1 "); lcd.print(sps1,2);lcd.print("Spd2 "); lcd.print(sps12, 2);
      move_finished = 0;
      stepper1.setSpeed(sps1);
      stepper2.setSpeed(sps2);
      stepper1.moveTo(StepVal1);
      stepper2.moveTo(StepVal2);
      {
        if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == StepVal2))
        stepper2.moveTo(0);
        stepper2.run();
        if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == 0))
        stepper2.moveTo(StepVal2);
        stepper2.run();
        stepper1.run(); //|| !stepper2.run());       //runs both steppers at same time
      }
      //-----------------------Monitor stepper1 and stop both steppers when distanceToGo=0 ----
      if ((move_finished == 0) && (stepper1.distanceToGo() == 0)) {   // && (stepper2.distanceToGo() == 0)) {
        stepper1.setCurrentPosition(0);             //resets stepper1 position to zero after completion
        stepper2.setCurrentPosition(0);             //resets stepper2 position to zero after completion
        move_finished = 1;                          //both steppers are at moveTo position
        state = 6;                                  //sets state to finishedCutting() mode
        finishedCutting();                          //goes to case 6 finishedCutting() routine
      }
      break;
    case 6:
      stepper1.setCurrentPosition(0);             //resets stepper1 position to zero after completion
      stepper2.setCurrentPosition(0);             //resets stepper2 position to zero after completion
      finishedCutting();
      break;
  }
}
//----------------------------------------Home Screen-----------------------------------
void homeScreen() {
  lcd.setCursor(0, 0);
  lcd.print("Auto Coil Winder");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
//----------------------------------------Set the Stepper speed--------------------------
void SetSpeed() {
  SpdSet = changeValue(SpdSet);
  if (previousSpdSet != SpdSet) {
    ratio = (SpdSet / 60.0000);          //Desired rpm's divided by 60
    sps1 = ((ratio * 800.0000) * 1.02);                 //Steps per second(1/4 micro step
    lcd.clear();
    previousSpdSet = SpdSet;
  }
  lcd.setCursor(0, 0);
  lcd.print(("RPM:" + (String)SpdSet) + " " + (String)sps1);
  displayNavigation();
}
//---------------------------------------Set the wire length-------------------------------
void chooseWireLength() {
  wireLength = changeValue(wireLength);
  //----2.307 based on 6/32 core-circumference=.43354 1in/.43354=2.30659 turns/per/inch-----
  unsigned long stepsToTake = (unsigned long)wireLength * 2.307 * 800;
  StepVal1 = stepsToTake;
  //clear LCD if required
  if (previousWireLength != wireLength) {
    lcd.clear();
    previousWireLength = wireLength;
  }

  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "in");
  displayNavigation();
}

void chooseWireSize() {
  wireSize = changeValue(wireSize);

  if (previousWireSize != wireSize) {
    //lcd.clear();
    previousWireSize = wireSize;
  }
  //Display information on LCD
  lcd.setCursor(0, 0);
  previousWireSize = previousWireSize / 1000;
  //2mm pitch lead screw-moves(.07874/800=.000098 per step) Multiplying by ratio keeps steppers in sync
  //so stepper2 will move the correct amount for the wire thickness and the stepper1 speed.
  sps2 = ((previousWireSize /.000098)* ratio);     
  //sps2 = (previousWireSize /.000098);
  //sps2 = sps2*ratio;
  lcd.print("Wire Size:"); lcd.println(previousWireSize, 4);
  displayNavigation();
}

void confirm() {
  lcd.setCursor(0, 0);
  lcd.print((String)SpdSet + "rpm " + (String)wireLength + "in " + (String)sps2);
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
void finishedCutting() {
  wireLength = 0;                  //reset wireLength value to zero
  wireSize = 0;                //reset wireLength value to zero
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Winding COMPLETE");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(500);                     //display winding complete for 500 milli seconds before starting over
  state = 0;                      //starts program at beginning screen
}
int changeValue(int currentValue) {
  if (!digitalRead(upButton)) {
    delay(100);
    //incrementSpeed = 10;
    currentValue += incrementSpeed;
    incrementSpeed ++;

  }
  if (!digitalRead(downButton)) {
    if (currentValue - incrementSpeed >= 0) {
      delay(100);
      currentValue -= incrementSpeed;
      incrementSpeed ++;
    }
    else {
      currentValue = 0;
    }
  }
  if (digitalRead(downButton) && digitalRead(upButton)) {
    incrementSpeed = 1;
  }
  return currentValue;
}
void displayNavigation() {
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}

The thing that struck me immediately I looked at your code is how all the other CASE sections are short except for CASE 5. That suggests to me that all (or most) of the code in CASE 5 should be moved into a function. However that won't of itself solve the problem.

If this was my program I would move the two calls to stepperX.run() so they are the last thing in loop() and are not inside any other clauses.

...R

Not sure exactly why, but this code currently works as desired. I have made so many changes that I'm not sure what the differences are. Stepper1 rotates at desired speed, for the desired distance and stepper2 moves at a slower assigned speed, reverses (in this case) after 4 revolutions continuously until stepper1 reaches its assigned position. Thanks for your time and suggestions. :slight_smile:

//modified to facilitate using for automatic coil winding machine

//------------------------------- librarys ----------------------------------
#include <AccelStepper.h>
#include <LiquidCrystal_I2C.h>
//#include <Wire.h>
//#include <rgb_lcd.h>
//#include <Servo.h>

//------------------------------- lcd ----------------------------------
//rgb_lcd lcd;
LiquidCrystal_I2C lcd(0x20, 16, 2);

//------------------------------- stepper 1 and 2 ----------------------------------
AccelStepper stepper1 = AccelStepper(1, 7, 8);
AccelStepper stepper2 = AccelStepper(1, 9, 10);
float StepVal2 = 3200;        //moveTo variable-Revolutions=StepVal/800 for 1/4 step
float StepVal1;
float sps1;                 //Steps per second-sets speed-stepper1
float sps2;                 //Steps per second-sets speed-stepper2 
int move_finished = 1;
//------------------------------- servo ------------------------------------------
//Servo snippers;
//#define servo 10
//#define openAngle 90
//#define closedAngle 0

//------------------------------- input ------------------------------------------
//Use A0 to A3 for stepper interface board layout.
#define leftButton A0
#define upButton A1
#define downButton A2
#define rightButton A3

//------------------------------- user settings ----------------------------------
unsigned int wireLength = 0;
//unsigned int wireQuantity = 0;
float wireSize = 0;
//-------------------------------Stepper 1 Speed variables----------------------------
int SpdSet = 60;
float ratio;

//-------------------------------Stepper 2 Speed variables--------------------------



//------------------------------- system settings --------------------------------
int state = 0;
int incrementSpeed = 1;
unsigned int previousWireLength = 0;
float previousWireSize = 0;
int previousSpdSet;
float mmPerStep = 0.0431984;      //2.3578 turns per inch based on 1/4 step, 6/32 core size
void setup() {
  Serial.begin(9600);
  lcd.begin(); //LCD columns and rows
  //lcd.setRGB(255,255,0); //backlight colour

  //stepper1.setMaxSpeed(800.0);    //Top speed limit=150rpm
  stepper1.setAcceleration(800.0);
  //stepper1.setSpeed(sps1);        //speed = DESIRED_RPM * STEPS_PER_REV / 60

  //stepper2.setMaxSpeed(800);   //Top speed limit=150rpm
  stepper2.setAcceleration(800.0);
  //stepper2.setSpeed(131);

  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);

}
void loop() {
  if (!digitalRead(rightButton)) {
    if (state == 6) {
      state = 0;
    }
    else {
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 5) {
    state -= 1;
    delay(200);
    lcd.clear();
  }


  switch (state) {
    case 0:
      homeScreen();
      break;
    case 1:
      SetSpeed();
      break;
    case 2:
      chooseWireLength();
      break;
    case 3:
      //state = 4;
      chooseWireSize();
      break;
    case 4:
      confirm();
      if (StepVal1 == 0)                            //If no length was entered goto finishedCutting()
        state  = 6;
      break;
    case 5:                                         //coil wind routine using 2 steppers
    move_finished = 0;
      if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == StepVal2))
    stepper2.moveTo(0);
  stepper2.run();

  if ((stepper2.distanceToGo() == 0) && (stepper2.currentPosition() == 0))
    stepper2.moveTo(StepVal2);
  stepper2.run();
  stepper1.run();            //runs stepper1 at constant speed and continuously

      //-----------------------Monitor stepper1 and stop both steppers when distanceToGo=0 ----
      if ((move_finished == 0) && (stepper1.distanceToGo() == 0)) {   // && (stepper2.distanceToGo() == 0)) {
        stepper1.setCurrentPosition(0);             //resets stepper1 position to zero after completion
        stepper2.setCurrentPosition(0);             //resets stepper2 position to zero after completion
        move_finished = 1;                          //both steppers are at moveTo position
        state = 6;                                  //sets state to finishedCutting() mode
        finishedCutting();                          //goes to case 6 finishedCutting() routine
      }    
      break;
    case 6:
      stepper1.setCurrentPosition(0);             //resets stepper1 position to zero after completion
      stepper2.setCurrentPosition(0);             //resets stepper2 position to zero after completion
      finishedCutting();
      break;
  }
}
//----------------------------------------Home Screen-----------------------------------
void homeScreen() {
  lcd.setCursor(0, 0);
  lcd.print("Auto Coil Winder");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
//----------------------------------------Set the Stepper speed--------------------------
void SetSpeed() {
  SpdSet = changeValue(SpdSet);
  if (previousSpdSet != SpdSet) {
    ratio = (SpdSet / 60.0000);          //Desired rpm's divided by 60
    sps1 = ((ratio * 800.0000) * 1.02);                 //Steps per second(1/4 micro step
    lcd.clear();
    previousSpdSet = SpdSet;
    //stepper1.setSpeed(sps1);
    stepper1.setMaxSpeed(sps1);
    //stepper1.moveTo(4800);
  }
  lcd.setCursor(0, 0);
  lcd.print(("RPM:" + (String)SpdSet) + " " + (String)sps1);
  displayNavigation();
}
//---------------------------------------Set the wire length-------------------------------
void chooseWireLength() {
  wireLength = changeValue(wireLength);
  //----2.307 based on 6/32 core-circumference=.43354 1in/.43354=2.30659 turns/per/inch-----
  unsigned long stepsToTake = (unsigned long)wireLength * 2.307 * 800;
  StepVal1 = stepsToTake;
  //clear LCD if required
  if (previousWireLength != wireLength) {
    lcd.clear();
    previousWireLength = wireLength;
  }

  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "in");
  stepper1.moveTo(StepVal1);
  displayNavigation();
}

void chooseWireSize() {
  wireSize = changeValue(wireSize);

  if (previousWireSize != wireSize) {
    previousWireSize = wireSize;
  }
  //Display information on LCD
  lcd.setCursor(0, 0);
  previousWireSize = previousWireSize / 1000;
  //2mm pitch lead screw-moves(.07874/800=.000098 per step) Multiplying by ratio keeps steppers in sync
  //so stepper2 will move the correct amount for the wire thickness and the stepper1 speed.
  sps2 = ((previousWireSize /.000098)* ratio);
  //stepper2.setSpeed(sps2);
  stepper2.setMaxSpeed(sps2);
  //stepper2.moveTo(10204.081);     
  //sps2 = (previousWireSize /.000098);
  //sps2 = sps2*ratio;
  lcd.print("Wire Size:"); lcd.println(previousWireSize, 4);
  displayNavigation();
}

void confirm() {
  lcd.setCursor(0, 0);
  lcd.print((String)SpdSet + "rpm " + (String)wireLength + "in " + (String)sps2);
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
void finishedCutting() {
  wireLength = 0;                  //reset wireLength value to zero
  wireSize = 0;                //reset wireLength value to zero
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Winding COMPLETE");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(500);                     //display winding complete for 500 milli seconds before starting over
  state = 0;                      //starts program at beginning screen
}
int changeValue(int currentValue) {
  if (!digitalRead(upButton)) {
    delay(100);
    //incrementSpeed = 10;
    currentValue += incrementSpeed;
    incrementSpeed ++;

  }
  if (!digitalRead(downButton)) {
    if (currentValue - incrementSpeed >= 0) {
      delay(100);
      currentValue -= incrementSpeed;
      incrementSpeed ++;
    }
    else {
      currentValue = 0;
    }
  }
  if (digitalRead(downButton) && digitalRead(upButton)) {
    incrementSpeed = 1;
  }
  return currentValue;
}
void displayNavigation() {
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}