Stepper motor randomly changing direction

Grettings!

So I have a problem. My stepper motor (Nema23, driver DM542) sometimes goes in the wrong direction. I have it programmed to go forward, than backward, than backward some more and with a switch back to home position. At these direction change points, it sometimes goes the wrong way. I am using AccelStepper library.

For example my code is something like this:
currentPosition(0)
moveTo(5000)
if currentPosition(5000), go to case2
case2: moveTo(6000)

Six times it will move from 5000(steps) to 6000, but on the seventh time it will go from 5000 to 4000 instead, changing direction.

My thoery so far is that maybe the dir output is sometimes too slow or that the stepper driver is not good. Any suggestions? Thank you.

Your sketch would be very useful.

Could you take a few moments to Learn How To Use The Forum.
Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

void zacetni_polozaj(){
  digitalWrite(rokaVENTIL, HIGH);
  if(rokaSENSOR2.read() == HIGH){
    digitalWrite(gripVENTIL, HIGH);
  }
  if(gripSENSOR1.read() == HIGH){
    zacetni_polozaj_finished = HIGH;
  }
}

void pomik_naprej(){
  if(alarmFinished == HIGH){
    stepper.moveTo(motorValue);
    stepper.run();
  }
  else{
    stepper.stop();
    stepper.run();
  }
  if(stepper.currentPosition() == motorValue){
    pomik_naprej_finished = HIGH;
  }
}

void odrez_zaga(){
  unsigned long currentMillis = millis();
  digitalWrite(zagaMOTOR, HIGH);
  digitalWrite(gripVENTIL, LOW);
  
  if(gripSENSOR2.read() == HIGH){
    if(zagaSENSOR2.read() == LOW){
      if(timeDelay == HIGH){
       previousMillis = currentMillis; 
      }
      if (currentMillis - previousMillis >= 700) {
      digitalWrite(zagaKONTAKTOR2, HIGH);
      }
      else{
        timeDelay = LOW;
      }
    }
    else{
      digitalWrite(zagaKONTAKTOR2, LOW);
      digitalWrite(zagaMOTOR, LOW);
      odrez_zaga_finished = HIGH;
      timeDelay = HIGH;
      zaga_nazaj = HIGH;
    }
  }
}

void pomik_dodatni(){
   digitalWrite(rokaVENTIL, LOW);
  unsigned long currentMillis = millis();
  if(zaga_nazaj == HIGH){
  if(zagaSENSOR1.read() == LOW){
     if(timeDelay == HIGH){
       previousMillis = currentMillis; 
      }
      if (currentMillis - previousMillis >= 100) {
      digitalWrite(zagaKONTAKTOR1, HIGH);
      }
      else{
        timeDelay = LOW;
      }
  }
  else{
    digitalWrite(zagaKONTAKTOR1, LOW);
    zaga_nazaj = LOW;
    timeDelay = HIGH;
  }
  }
  if(alarmFinished == HIGH){
    stepper.moveTo(motorValue - 120);
    stepper.run();
  }
  else{
    stepper.stop();
    stepper.run();
  }
  if(stepper.currentPosition() == (motorValue - 120) && zagaSENSOR3.read() == HIGH && rokaSENSOR1.read() == HIGH){
    pomik_dodatni_finished = HIGH;
  }
}

void koncni_polozaj(){
  if(rokaSENSOR1.read() == HIGH){
    alarmOverride = HIGH;
    digitalWrite(cikelLED, HIGH);
  }
  if(flisSENSOR.read() == LOW && alarmSENSOR.read() == LOW && zagaSENSOR3.read() == HIGH){
    alarmOverride = LOW;
    digitalWrite(cikelLED, LOW);
    koncni_polozaj_finished = HIGH;
  }
   
}

void pomik_nazaj(){
  digitalWrite(rokaVENTIL, LOW);
  if(alarmFinished == HIGH){
    stepper.moveTo(startX);
    stepper.run();
  }
  else{
    stepper.stop();
    stepper.run();
  }
  if(stepper.currentPosition() == startX && rokaSENSOR1.read() == HIGH){
    pomik_nazaj_finished = HIGH;
  }
}

void loop() {
dolzinaGUMB.update();
gripGUMB.update();
gripSENSOR1.update();
gripSENSOR2.update();
alarmGUMB.update();
alarmSENSOR.update();
flisSENSOR.update();
homingGUMB.update();
endSTIKALO1.update();
endSTIKALO2.update();
cikelSTIKALO.update();
rokaSENSOR1.update();
rokaSENSOR2.update();
zagaSENSOR1.update();
zagaSENSOR2.update();
zagaSENSOR3.update();
unsigned long currentMillis = millis();




//HOMING---HOMING---HOMING---HOMING---HOMING---HOMING---HOMING---HOMING---HOMING---HOMING---


if (homingGUMB.rose() && stepper.isRunning() == LOW){
  digitalWrite(homingLED, HIGH);
  homingState = HIGH;
}
  
if (homingState == HIGH && alarmFinished == HIGH && dolzinaFinished == HIGH && cikelSTIKALO.read() == LOW) {
  homingFinished = LOW;
  homingAlarmOverride = HIGH;
  alarmOverride  = LOW;
  if (initialHoming == LOW){
    if(endSTIKALO1.read() == HIGH) {
       stepper.setMaxSpeed(50.0);
       stepper.setAcceleration(50.0);
       stepper.moveTo(initial_homing);  
       initial_homing--; 
       stepper.run();  
      }
    else {
      initialHoming = HIGH;
      stepper.setCurrentPosition(0);
     }
   }

  if(initialHoming == HIGH){
    stepper.moveTo(20);
    stepper.setMaxSpeed(40.0);
    stepper.setAcceleration(40.0);
    stepper.run();
   }
  if(stepper.currentPosition() == 20){
    homingState = LOW;
    initialHoming = LOW;
    homingAlarmOverride = LOW;
    homingFinished = HIGH;
    digitalWrite(homingLED, LOW);
    stepper.setCurrentPosition(0);
   }
}

//HOMING_ALARM---HOMING_ALARM---HOMING_ALARM---HOMING_ALARM---HOMING_ALARM---HOMING_ALARM---HOMING_ALARM---

if((endSTIKALO1.read() == LOW || endSTIKALO2.read() == HIGH) && homingAlarmOverride == LOW){
  homingFinished = LOW;
  digitalWrite(homingLED, ledState);
   stepper.setCurrentPosition(0);
   stepper.moveTo(0);
   stepper.run();
}

//RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---RESET---

if (cikelSTIKALO.fell() && homingFinished == HIGH){
  stopingMotor = HIGH;
  alarmOverride  = LOW; 
  zaga_nazaj = HIGH;
}


if (stopingMotor == HIGH) {
  digitalWrite(zagaMOTOR, LOW);
  digitalWrite(zagaKONTAKTOR1, LOW);
  digitalWrite(zagaKONTAKTOR2, LOW);
  if(stepper.isRunning() == HIGH){
    stepper.setMaxSpeed(Spp);
    stepper.setAcceleration(Acc);
    stepper.stop();
    stepper.run();
  }
  else {
    resetFinished = LOW;
    stopingMotor = LOW;
  }
}
if(resetFinished == LOW && homingFinished == HIGH && dolzinaFinished == HIGH && cikelSTIKALO.read() == LOW){
  zacetni_polozaj_finished = LOW;
  pomik_naprej_finished = LOW;
  odrez_zaga_finished = LOW;
  pomik_dodatni_finished = LOW;
  koncni_polozaj_finished = LOW;
  pomik_nazaj_finished = LOW;
  digitalWrite(cikelLED, LOW);
  alarmOverride  = LOW;
  digitalWrite(rokaVENTIL, LOW);
  unsigned long currentMillis = millis();
  if(zagaSENSOR3.read() == HIGH){
    zaga_nazaj = LOW;
  }
  if(zaga_nazaj == HIGH){
   if(zagaSENSOR1.read() == LOW){
     if(timeDelay == HIGH){
       previousMillis = currentMillis; 
      }
      if (currentMillis - previousMillis >= 1000) {
      digitalWrite(zagaKONTAKTOR1, HIGH);
      }
      else{
        timeDelay = LOW;
      }
   }
   else{
    digitalWrite(zagaKONTAKTOR1, LOW);
    timeDelay = HIGH;
    zaga_nazaj = LOW;
   }
  }
  stepper.setMaxSpeed(Spp);
  stepper.setAcceleration(Acc);
  if (alarmFinished == HIGH){
      stepper.moveTo(0);
      stepper.run(); 
  }
  else {
    stepper.stop();
    stepper.run();  
  }
  if(stepper.currentPosition() == 0 && rokaSENSOR1.read() == HIGH && zagaSENSOR3.read() == HIGH){
    resetFinished = HIGH;
    zaga_nazaj = HIGH;
    cikel_state = 6;
  }
}

//CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---CIKEL---

if(stepper.currentPosition() == startX){
  startPozicija = HIGH;  
}
else{
  startPozicija = LOW;
}
if(stepper.currentPosition() == motorValue){
  endPozicija = HIGH;
}
else{
  endPozicija = LOW;
}
if(stepper.currentPosition() == motorValue + 400){
  endPlusPozicija = HIGH;
}
else{
  endPlusPozicija = LOW;
}

if (cikelSTIKALO.read() == HIGH && resetFinished == HIGH && homingFinished == HIGH && dolzinaFinished == HIGH && gripFinished == HIGH && stopingMotor == LOW){
  stepper.setMaxSpeed(Spp);
  stepper.setAcceleration(Acc);
  switch (cikel_state)
  {
  case 1:
    pomik_nazaj_finished = LOW;
    if(zacetni_polozaj_finished == LOW){
      zacetni_polozaj();
    }
    else {
      cikel_state = 2;
    }
    break;
    
  case 2:
    zacetni_polozaj_finished = LOW;
    if (pomik_naprej_finished == LOW){
      pomik_naprej(); 
    }
    else{
      cikel_state = 3;
    }
    break;

  case 3:
    pomik_naprej_finished = LOW;
    if (odrez_zaga_finished == LOW){
      odrez_zaga();  
    }
    else{
      cikel_state = 4;
    }
    break;

  case 4:
    odrez_zaga_finished = LOW;
    if (pomik_dodatni_finished == LOW){
      pomik_dodatni();
    }
    else{
      cikel_state = 5;
    }
    break;
    
  case 5:
    pomik_dodatni_finished = LOW;
    if(koncni_polozaj_finished == LOW){
      koncni_polozaj();
    }
    else{
      cikel_state = 6;
    }
    break;

  case 6:
    koncni_polozaj_finished = LOW;
    if (pomik_nazaj_finished == LOW){
      pomik_nazaj();
    }
    else{
      cikel_state = 1;
    }
    break;  
   }
 }  
}

Well here is the code. No void setup and other bits because of character limit. Somehow the dir output gets reversed sometimes, as I have said.

Can you tell us when this problem started? What did you change in the program to make it start?

Paul

Well I wrote the program, fixed the bugs and started to use it. So the problem is here from the start. I measured the continuity of the motor coils. They are fine, as are the wires from the “PLC” to the driver.

Some guy suggested to step it really slow and grab the shaft. If it stops than one coil is open in the stepper driver. Is this sound strategy?

Klema:
Well here is the code. No void setup and other bits because of character limit.

Please post the complete program - the problem is often in the other part. If the program is too long then add your .ino file as an attachment.

So the problem is here from the start

If that is the case, how did the program get so big before you fixed the problem? It is always much easier to help with a short program that only deals with the problem issue.

You have not told us what signals the motor to change direction? Is it just the program code or is there some hardware such as a limit switch?

...R

Robin2:
Please post the complete program - the problem is often in the other part. If the program is too long then add your .ino file as an attachment.
If that is the case, how did the program get so big before you fixed the problem? It is always much easier to help with a short program that only deals with the problem issue.

You have not told us what signals the motor to change direction? Is it just the program code or is there some hardware such as a limit switch?

…R

Attached the whole code. The program got so big before I fixed the problem, because I just wrote the whole program and everything works except for this random dir change.

There are limit switches (only for safety and homing) The main cycle is controlled by counting steps, so the code tells it when to stop or change direction.

As I have said
the code says more or less:
case 1
moveTo(5000)
run()
if (currentPosition(5000)) go to case 2
case 2
moveTo(6000)
run()

But sometimes the motor will go to 4000 instead of 6000. The dir will mess up. I than try to home the stepper but it still goes the wrong way. Only shuting the power off/on will make it work normaly. Somehow the dir output does nothing more.

KODA_ZA_STROJ.ino (13.8 KB)

Is there a breadboard somewhere in your wiring?

Paul

Paul_KD7HB:
Is there a breadboard somewhere in your wiring?

Paul

No. Wires from Controllino Maxi to DM542 driver to Nema 23 all at 24VDC.

When moveTo() and run() code finishes a move and starts a new move (new moveTo() and run()) the direction problem arises, never in between a move. EVEN if the previous move and the new move have the same direction. The motor can still go the other way instead.

Does dir output always comunicate with the driver/motor or only before the move to give it direction?

a) loose wire
b) steprate too high
c) step signal too short

Klema:
As I have said
the code says more or less:
case 1
moveTo(5000)
run()
if (currentPosition(5000)) go to case 2
case 2
moveTo(6000)
run()

I suggest you write a short program that just tries that - ideally extract the relevant code from your long program. It will make it much easier to find the problem.

I can’t make sense of your program without, at least, a translation of the function names and the names of the important variables.

Also there is far too much code in your loop() function. It would be much better to split that up into several smaller functions (with meaningful names) that are called from loop.

The great advantage of short functions is that you can copy one of them into another test program, verify that it works and then forget about it.

The program got so big before I fixed the problem, because I just wrote the whole program and everything works except for this random dir change.

When writing a program test it after every 5 or 6 lines.

…R
Planning and Implementing a Program

zwieblum:
a) loose wire
b) steprate too high
c) step signal too short

About c) how would you make step signal longer?

The step signal is a pulse of definite length. If you make it too short, it won't work.

Klema:
About c) how would you make step signal longer?

As you say that the problem only arises at the direction-change points I reckon the step signal is perfectly OK.

...R

zwieblum:
a) loose wire
b) steprate too high
c) step signal too short

I'd add
d) DM542 has optocouplers that are too slow, such that step/direction pulse timing is being changed too much.

MarkT:
d) DM542 has optocouplers that are too slow, such that step/direction pulse timing is being changed too much.

Just curious ...

It seems unlikely that the direction pin is changing too fast - after all there will be several steps in each direction and, if the motor is moving correctly in a direction without missing steps doesn't that indicate that the step pulses are satisfactory?

(All based on info in the Original Post)

...R

Not necessarily. The max. steprate depends on the powersupply and the driver, too. When the pulsewidth is too small the driver misses steps, which is equiv. to randomly halven the staprate, which will most likely exeed the acc limit for the given combination which will then result in funny things happening.

zwieblum:
Not necessarily.

What exactly are you referring to? And have I missed something in the Original Post?

I read the Original Post to say the motor works fine in both directions, the problem only arises at the point of changing direction. And I suspect there are plenty of DM542 drivers working happily with the AccelStepper library.

...R

I was referring to your post.

zwieblum:
I was referring to your post.

What, specifically, in my Post (I presume you mean Reply #15)

...R