Accelstepper library stepper movement interrupted problem

I'm working on a coil winding machine. I have 2 steppers. One is rotating the pipe where the wire is winded on and the other one is controlling a slider to go from right to left in a certain interval after each rotation of the rotating Stepper. After realising it doesn't work that great I did some trial and error and found out the problem is in the software. It turns out that everytime the slider Steppermotor should make its steps it make about half of them gets shortly interrupted and than makes almost the res tof the steps. So steps are lost and its kind of random and not everytime the same. After Trial and Error I can say that its not a mechanical problem (too little torque of stepper etc.). I only put the custom void that makes the winding process in here because the rest is too long.

(stepper1 = rotating // stepper2 = slider)

void WindCoil(){
      if (didMyOneTimeAction == false){
    didMyOneTimeAction = true;
    stepper1.setCurrentPosition(0);
     }
      stepper1.setMaxSpeed(200.0);
      stepper1.setAcceleration(30.0);
      stepper2.setMaxSpeed(500);
      stepper2.setAcceleration(500);
      stepper1.moveTo(-rotationsteps); 

                                                                                                         //Here's the problem
      rotations = stepper1.currentPosition()/200;            // Here are the steps of the                                      
                                                                                                 //slider which get
      if(rotations != rotationsold){                               //triggered every 200 steps (one rotation) of                                      
      rotationsold = rotations;                                    //the rotating stepper                                  
      stepper2.move(100); //slidersteps                                         
                                                                                                      
     }
      stepper2.run();
      stepper1.run();
      
      if (stepper1.distanceToGo() == 0){
        delay(200);
        parameters [3] = 0;
        didMyOneTimeAction = false;
      }
      
    }

What Arduino are you using? Do you have a limit switch for homing?

Often the problem is in the code you do not post. Please post your entire sketch.

You should not need to execute the following every time you call WindCoil(). per the AccelStepper library documentation:

"This is an expensive call since it requires a square root to be calculated. Don't call more often than needed"

You can really believe the experienced users here
in 99% of all cases where a code-snippet was posted

  • either the bug was outside the code-snippet
  • or the rest of the code is crucial to understand the logic to find the bug

Even if you code should have 5000 lines post the complete sktech.
The experienced users will find orientation in your code or clearly tell you structure your code in functions.

But with a small code-snippet it is almost impossible to understand what your code is doing
best regards Stefan

I'm using an Arduino uno and I have a limitswitch for homing. I will send here the complete sketch. I have many variables that are labeled in german. They are basically to calculate the needed steps for a certain thickness of wire. I'm also using an LCD and 5 buttons to enter all the needed parameters. The LCD menu with the buttons is based on this youtube video: Ep. 59 - Arduino LCD Display Menu System Tutorial, Scrolling Menu, Changeable Variables for Projects - YouTube
Also I made it so that if some parameters are 1 as an example the parameter [4] than the void autohome gets activated and so on. The code is probably quite confusing because I'm not really into coding but I hope someone can figure it out. Everything works except the mentioned thing with the slider motor movement getting randomly interrupted sometimes. Thanks in advance!

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);


#include <AccelStepper.h>
float count = 0;
float rotations = 0; 
float slidersteps;
float Durchmesser = 0.10;
float Wicklungen;
float rotationsteps = 0;
float Lange;
float rotationsold = 0;
float Start;
float OnlyRotate;
float CoilDiameter;
float WireLength;
int Endswitch;
int Multiplier;

boolean didMyOneTimeAction = false;

AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);


//Input & Button Logic
const int numOfInputs = 4;
const int inputPins[numOfInputs] = {6,9,8,7};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW,LOW,LOW,LOW};
bool inputFlags[numOfInputs] = {LOW,LOW,LOW,LOW};
long lastDebounceTime[numOfInputs] = {0,0,0,0};
long debounceDelay = 5;

//LCD Menu Logic
const int numOfScreens = 9;
int currentScreen = 0;
String screens[numOfScreens][2] = {{"Turns",""}, {"Wire Diameter", "mm"}, 
{"Coil Length","cm"},{"Start Winding",""}, {"Auto Home", ""}, {"Only Rotate",""}, {"Move Sled",""}, {"Coil Diameter","cm"}, {"need Wire Length","m"}};
float parameters[numOfScreens];


void setup() {
  for(int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  //Serial.begin(9600);
  lcd.init();
  lcd.backlight();
}

void loop() {
  setInputFlags();
  resolveInputFlags();
  Wicklungen = parameters [0];
  Durchmesser = parameters [1];
  Start = parameters [3];
  OnlyRotate = parameters [5];
  slidersteps = Durchmesser * 100;
  rotationsteps = Wicklungen * 200;
  Lange = (Wicklungen * Durchmesser)/10;
  parameters [2] = Lange;
  CoilDiameter = parameters [7];
  WireLength = ((CoilDiameter *3.14) * Wicklungen)/100;
  parameters [8] = WireLength;
  
  stepper1.setMaxSpeed(200.0);
  stepper1.setAcceleration(30.0);
  stepper2.setMaxSpeed(500);
  stepper2.setAcceleration(500);
    if(Start == 1){
    WindCoil();
    }
    if(Start == 0){
    stepper1.stop();
    stepper2.stop();
    stepper1.setCurrentPosition(0);
    }
   
    if(OnlyRotate == 1){
      Rotate();
    }

if(parameters [6] == 1){
  MoveSled(1);
}
if(parameters [6] == -1){
  MoveSled(-1);
}

if(parameters [4] == 1){
  AutoHome();
}

}

void WindCoil(){
      if (didMyOneTimeAction == false){
    didMyOneTimeAction = true;
    stepper1.setCurrentPosition(0);
     }
      stepper1.setMaxSpeed(200.0);
      stepper1.setAcceleration(30.0);
      stepper2.setMaxSpeed(500);
      stepper2.setAcceleration(500);
      stepper1.moveTo(-rotationsteps); 
      rotations = stepper1.currentPosition()/200;
      if(rotations != rotationsold){
      rotationsold = rotations;
      stepper2.move(100); //slidersteps
     }
      stepper2.run();
      stepper1.run();
      
      if (stepper1.distanceToGo() == 0){
        delay(200);
        parameters [3] = 0;
        didMyOneTimeAction = false;
      }
      
    }

void Rotate(){
      stepper1.setMaxSpeed(40.0);
      stepper1.setAcceleration(30.0);
      stepper1.setSpeed(-30);
      stepper1.run();
}



void MoveSled(int Direction){
if (Direction == 1){
  stepper2.setMaxSpeed(200);
  stepper2.setSpeed(100);
  stepper2.run();
}
if (Direction == -1){
  stepper2.setMaxSpeed(200);
  stepper2.setSpeed(-100);
  stepper2.run();
}
}

void AutoHome(){
    stepper2.setMaxSpeed(800);
    stepper2.setSpeed(-800);
    stepper2.run();
    Endswitch = digitalRead(10);
    if(Endswitch == 0){
      parameters [4] = 0;
    }
   
}





void setInputFlags() {
  for(int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}

void resolveInputFlags() {
  for(int i = 0; i < numOfInputs; i++) {
    if(inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}

void inputAction(int input) {
  if(input == 0) {
    if (currentScreen == 0) {
      currentScreen = numOfScreens-1;
    }else{
      currentScreen--;
    }
  }else if(input == 1) {
    if (currentScreen == numOfScreens-1) {
      currentScreen = 0;
    }else{
      currentScreen++;
    } 
  }




  
  //Parameter Plus/Minus durch Drücken des Knopfes
  else if(input == 2) {
    if(currentScreen == 1){
      parameterChange(2);
    }
    if(currentScreen == 0){
      Multiplier = digitalRead(11);
    if(Multiplier == 0){
     parameterChange(6);
    }
    else{
     parameterChange(4); 
    }

    }
    if(currentScreen == 2){
      parameterChange(0);
    }
    if(currentScreen == 3){
    parameterChange(0);
    }
    if(currentScreen == 4){
    parameterChange(0);
    }
    if(currentScreen == 5){
    parameterChange(0);
    }        
    if(currentScreen == 6){
    parameterChange(0);
    } 
    if(currentScreen == 7){
    parameterChange(0);
    } 
    if(currentScreen == 8){
    parameterChange(0);
    } 
}

    else if(input == 3) {
    if(currentScreen == 1){
    parameterChange(3);
    }
    if(currentScreen == 0){
     Multiplier = digitalRead(11);
    if(Multiplier == 0){
     parameterChange(7);
    }
    else{
     parameterChange(5); 
    }
    }
    if(currentScreen == 2){
    parameterChange(1);
    }
    if(currentScreen == 3){
    parameterChange(1);
    }
    if(currentScreen == 4){
    parameterChange(1);
    }
    if(currentScreen == 5){
    parameterChange(1);
    }
    if(currentScreen == 6){
    parameterChange(1);
    }        
    if(currentScreen == 7){
    parameterChange(1);
    } 
    if(currentScreen == 8){
    parameterChange(1);
    } 
  }
}

void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen]++;
  }else if(key == 1) {
    parameters[currentScreen]--;
  }else if(key == 2){
    parameters[currentScreen] = parameters[currentScreen] + 0.01;
  }else if(key == 3){
    parameters[currentScreen] = parameters[currentScreen] - 0.01;
  }else if(key == 4){
    parameters[currentScreen] = parameters[currentScreen] + 10;
  }else if(key == 5){
    parameters[currentScreen] = parameters[currentScreen] - 10;
}else if(key == 6){
    parameters[currentScreen] = parameters[currentScreen] + 100;
}
else if(key == 7){
    parameters[currentScreen] = parameters[currentScreen] - 100;
}
}
void printScreen() {
  lcd.clear();
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0,1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}

I tried putting the code you mentioned so that it gets only send once but it sadly didn't change anything on the slider motor getting interrupted. I only tried it in the void Windcoil I sent first but it shouldn't make a difference to change it everywhere in the code when it makes no difference when the void Windcoil is running constantly I think.

Stepper 2 has a speed of 500 SPS when you are running WindCoil(). This means that stepper2.run() must be called at least every 2 milliseconds which means WindCoil() should be getting called that fast also. You are doing so much stuff in your loop() function I can't readily determine what is interfering.

If your code was structured using a state machine then you could be assured nothing is interfering while it is performing the WindCoil() operation.

Here is a state machine tutorial you might want to look at:

State Machine

shouldn't the slider steps be synchronized to the rotation and needs to reverse when it reaches either end. looks like the run independently

i can conceive that the rotation runs are a some specified speed and # of steps, but doesn't the slider need to repeatedly be restarted when it reaches the extreme ... is this implemented by repeatedly calling WindCoil()

seems like there is a better way, by stepping each synchronously, with a N:1 or 1:N ratio. isn't this the kind of thing done with 3d printers

the slider needs to move a small # of steps for each rotation

The machine is for winding Tesla coils. That means that there will only be one layer of windings . I have a start position and from there it goes to the left and not again to the right because only one layer of windings is needed.

I accidentally wrote that I'm using an Arduino Uno. I'm using an Arduino Nano although I don't think there's much if any difference between them.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.