[SOLVED] Why my stepper runs slower steps when using millis() than delay()?

Hello,

Because I want to include my stepper in a real time final diploma project.

I don't want to use delay() to improve code overall performance.

I developed a code to run the stepper using millis(), it worked but it runs little slower than when using delay()

What is the reason?

This is the code for using delay:

void clockwise(void){
        digitalWrite(in4, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(1);
        digitalWrite(in4, HIGH);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(1);  
        digitalWrite(in4, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(1);    
        digitalWrite(in4, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, LOW);
    delay(1);
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, LOW);
    delay(1);    
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, HIGH);
    delay(1);      
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, HIGH);
    delay(1);        
        digitalWrite(in4, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, HIGH);
    delay(1);   
}

This is the code for using millis:

void stepper_run_cw(void){
  stepper_step_cw(1,0,0,0,1);
  stepper_step_cw(1,1,0,0,1);
  stepper_step_cw(0,1,0,0,1);
  stepper_step_cw(0,1,1,0,1);
  stepper_step_cw(0,0,1,0,1);
  stepper_step_cw(0,0,1,1,1);
  stepper_step_cw(0,0,0,1,1);
  stepper_step_cw(1,0,0,1,1);  
}


void stepper_step_cw(uint8_t m_in1, uint8_t m_in2, uint8_t m_in3, uint8_t m_in4, uint8_t delay_time){
  if (!stepper_run){
    digitalWrite(in1, m_in1);
    digitalWrite(in2, m_in2);
    digitalWrite(in3, m_in3);
    digitalWrite(in4, m_in4);
    stepper_start = millis();
    stepper_run = 1;
  }

  if(stepper_run){
    stepper_current = millis();
    if(stepper_current - stepper_start >= delay_time){
      stepper_run = 0;
    }    
  }
}

Perhaps there are more electrons available to the circuit when using millis then when using delay and those more electrons weigh more?

What ever running heavier means.

Could you restate your issue?

Idahowalker:
Perhaps there are more electrons available to the circuit when using millis then when using delay and those more electrons weigh more?

What ever running heavier means.

Could you restate your issue?

I modified my word usage, it meant little slower.

You know the feel/sound when you hold a small stepper motor than is running on one certain code and little slower with other code with same timing.

The feel/sound of the first code is little smoother and faster where with the code I used millis() it's little not as smooth and I think it's a little slower.

Please post the complete version of both programs.

What stepper motor and stepper motor driver are you using?

...R

Robin2:
Please post the complete version of both programs.

What stepper motor and stepper motor driver are you using?

...R

OK, this my testing code.

The stepper is the 28BYJ with ULN2003.

// this library is for the 28BYJ stepper motor

#define in1 6
#define in2 7
#define in3 8
#define in4 9
#define ir1 A0


uint32_t stepper_start;
uint32_t stepper_current;
uint32_t stepper_period;
byte stepper_run;

void clockwise(uint8_t stepper_speed);
void C_clockwise(uint8_t stepper_speed);
void stepper_step(uint8_t m_in1, uint8_t m_in2, uint8_t m_in3, uint8_t m_in4, uint8_t delay_time);
void stepper_run_cw(uint8_t stepper_speed);
void stepper_run_ccw(uint8_t stepper_speed);
void setup() {
  // put your setup code here, to run once:
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
pinMode(ir1,INPUT);

}

void loop() {
  //if(!digitalRead(ir1)){clockwise();}else{c_clockwise();}
 //stepper_run_ccw(1);
 stepper_run_cw(1);
 // c_clockwise(10);
}

void stepper_run_cw(uint8_t stepper_speed){
  stepper_step(1,0,0,0,stepper_speed);
  stepper_step(1,1,0,0,stepper_speed);
  stepper_step(0,1,0,0,stepper_speed);
  stepper_step(0,1,1,0,stepper_speed);
  stepper_step(0,0,1,0,stepper_speed);
  stepper_step(0,0,1,1,stepper_speed);
  stepper_step(0,0,0,1,stepper_speed);
  stepper_step(1,0,0,1,stepper_speed);  
}

void stepper_run_ccw(uint8_t stepper_speed){
  stepper_step(1,0,0,1,stepper_speed);
  stepper_step(0,0,0,1,stepper_speed);
  stepper_step(0,0,1,1,stepper_speed);
  stepper_step(0,0,1,0,stepper_speed);
  stepper_step(0,1,1,0,stepper_speed);
  stepper_step(0,1,0,0,stepper_speed);
  stepper_step(1,1,0,0,stepper_speed);
  stepper_step(1,0,0,0,stepper_speed);  
}

void stepper_step(uint8_t m_in1, uint8_t m_in2, uint8_t m_in3, uint8_t m_in4, uint8_t delay_time){
  if (!stepper_run){
    digitalWrite(in1, m_in1);
    digitalWrite(in2, m_in2);
    digitalWrite(in3, m_in3);
    digitalWrite(in4, m_in4);
    stepper_start = millis();
    stepper_run = 1;
  }

  if(stepper_run){
    stepper_current = millis();
    if(stepper_current - stepper_start >= delay_time){
      stepper_run = 0;
    }    
  }
}

void clockwise(uint8_t stepper_speed){
        digitalWrite(in4, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(stepper_speed);
        digitalWrite(in4, HIGH);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(stepper_speed);  
        digitalWrite(in4, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in1, LOW);
    delay(stepper_speed);    
        digitalWrite(in4, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, LOW);
    delay(stepper_speed);
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, LOW);
    delay(stepper_speed);    
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in1, HIGH);
    delay(stepper_speed);      
        digitalWrite(in4, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, HIGH);
    delay(stepper_speed);        
        digitalWrite(in4, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in1, HIGH);
    delay(stepper_speed);   
}

void c_clockwise(uint8_t stepper_speed){
        digitalWrite(in1, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in4, LOW);
    delay(stepper_speed);
        digitalWrite(in1, HIGH);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in4, LOW);
    delay(stepper_speed);  
        digitalWrite(in1, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in4, LOW);
    delay(stepper_speed);    
        digitalWrite(in1, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, LOW);
    delay(stepper_speed);
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, LOW);
    delay(stepper_speed);    
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, HIGH);
    delay(stepper_speed);      
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in4, HIGH);
    delay(stepper_speed);        
        digitalWrite(in1, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in4, HIGH);
    delay(stepper_speed);   
}

wolfrose:
OK, this my testing code.

You need to learn about looping to avoid all that repetitive code.

...R

Robin2:
You need to learn about looping to avoid all that repetitive code.

…R

How about this one? Also thanks for telling me about improving my looping method :slight_smile:

// this library is for the 28BYJ stepper motor

#define in1 6
#define in2 7
#define in3 8
#define in4 9

uint8_t stepper_masks[] = {0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90};


void cw_loop(uint8_t stepper_speed)


void setup() {
  for(byte i=in1;i<=in4;i++){
    pinMode(i,OUTPUT);}

}

void loop() {

  cw_loop(10);
}



void cw_loop(uint8_t stepper_speed){
  for(byte k=0;k<8;k++){
    for(byte i=in1;i<=in4;i++){
      digitalWrite(i, 0<(stepper_masks[k]&0x80>>i-6));
      delay(stepper_speed);    
    }  
  }
}

I have a question:

What is this stepper motor next to the 28BYJ stepper motor? It doesn't have any info of model to search for its datasheet.

wolfrose:
How about this one?

It is admirably shorter.

Do you understand it?

Have you tried it?

This is a function from my own program that uses a 28BYJ stepper motor

//===================

void moveOneFullStep() {

 static unsigned long prevStepMicros;
 static char stepSequence = 0;

 if (firstStepOfSequence == true) {
 prevStepMicros = micros();
 firstStepOfSequence = false;
 }

 if (micros() - prevStepMicros < tableStepIntervalMicros) {
 return;
 }
 else {
 stepCount ++;
 prevStepMicros += tableStepIntervalMicros;
 }

 if(tableDirection == 'F'){
 stepSequence++;
 }else{
 stepSequence--;
 }

 if(stepSequence>3){
 stepSequence=0;
 }
 if(stepSequence<0){
 stepSequence=3;
 }



 switch(stepSequence){
 case 0:
 digitalWriteFast(stepperPin1, HIGH);
 digitalWriteFast(stepperPin2, HIGH);
 digitalWriteFast(stepperPin3, LOW);
 digitalWriteFast(stepperPin4, LOW);
 break;
 case 1:
 digitalWriteFast(stepperPin1, LOW);
 digitalWriteFast(stepperPin2, HIGH);
 digitalWriteFast(stepperPin3, HIGH);
 digitalWriteFast(stepperPin4, LOW);
 break;
 case 2:
 digitalWriteFast(stepperPin1, LOW);
 digitalWriteFast(stepperPin2, LOW);
 digitalWriteFast(stepperPin3, HIGH);
 digitalWriteFast(stepperPin4, HIGH);
 break;
 case 3:
 digitalWriteFast(stepperPin1, HIGH);
 digitalWriteFast(stepperPin2, LOW);
 digitalWriteFast(stepperPin3, LOW);
 digitalWriteFast(stepperPin4, HIGH);
 break;
 }
}

In my application the motor only needs to move one way - but it should illustrate the concept by which the steps are generated and how the timing is done without using delay().

…R

Robin2:
It is admirably shorter.

Do you understand it?

Have you tried it?

This is a function from my own program that uses a 28BYJ stepper motor

//===================

void moveOneFullStep() {

static unsigned long prevStepMicros;
static char stepSequence = 0;

if (firstStepOfSequence == true) {
prevStepMicros = micros();
firstStepOfSequence = false;
}

if (micros() - prevStepMicros < tableStepIntervalMicros) {
return;
}
else {
stepCount ++;
prevStepMicros += tableStepIntervalMicros;
}

if(tableDirection == ‘F’){
stepSequence++;
}else{
stepSequence–;
}

if(stepSequence>3){
stepSequence=0;
}
if(stepSequence<0){
stepSequence=3;
}

switch(stepSequence){
case 0:
digitalWriteFast(stepperPin1, HIGH);
digitalWriteFast(stepperPin2, HIGH);
digitalWriteFast(stepperPin3, LOW);
digitalWriteFast(stepperPin4, LOW);
break;
case 1:
digitalWriteFast(stepperPin1, LOW);
digitalWriteFast(stepperPin2, HIGH);
digitalWriteFast(stepperPin3, HIGH);
digitalWriteFast(stepperPin4, LOW);
break;
case 2:
digitalWriteFast(stepperPin1, LOW);
digitalWriteFast(stepperPin2, LOW);
digitalWriteFast(stepperPin3, HIGH);
digitalWriteFast(stepperPin4, HIGH);
break;
case 3:
digitalWriteFast(stepperPin1, HIGH);
digitalWriteFast(stepperPin2, LOW);
digitalWriteFast(stepperPin3, LOW);
digitalWriteFast(stepperPin4, HIGH);
break;
}
}




In my application the motor only needs to move one way - but it should illustrate the concept by which the steps are generated and how the timing is done without using delay().

...R

This one worked like a charm :slight_smile:

I also like the method in your code, it’s different, based on the switch statement and controlled with .

I learned how stepSequence work, but did not understand how stepCount ++; has a roll in the function?

// this library is for the 28BYJ stepper motor

#define in1 6
#define in2 7
#define in3 8
#define in4 9

uint8_t s=0,stepper_masks[] = {0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90};

uint32_t stepper_start;
uint32_t stepper_current;
uint32_t stepper_period;

void stepper_step(uint8_t *mask, uint8_t delay_time);

///////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  for(byte i=in1;i<=in4;i++){
    pinMode(i,OUTPUT);}
    
  pinMode(13,OUTPUT); 

}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
 stepper_step(stepper_masks,1);

}
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////

void stepper_step(uint8_t *mask, uint8_t delay_time){
  if (!stepper_run){
    for(byte i=6;i<10;i++){
      digitalWrite(i, 0<(mask[s]&0x80>>i-6));
    }
    s++;if(s>7)s=0;
    stepper_start = millis();
    stepper_run = 1;
  }

  if(stepper_run){
    stepper_current = millis();
    if(stepper_current - stepper_start >= delay_time){
      stepper_run = 0;
    }    
  }
}

wolfrose:
I learned how stepSequence work, but did not understand how stepCount ++; has a roll in the function?

It doesn’t.

Other parts of my program need a count of the number of steps moved.

…R

Robin2:
It doesn't.

Other parts of my program need a count of the number of steps moved.

...R

Ah ok so you are applying the stepper motor to move by specific steps to achieve specific angles, right?

wolfrose:
Ah ok so you are applying the stepper motor to move by specific steps to achieve specific angles, right?

Yes - that is normally how stepper motors are used.

You have to understand that for the timing to work moveOneFullStep() must be called very frequently and on most of those calls nothing will happen because it is not yet time for a step. Consequently, by updating the stepCount variable the rest of the code can know when a step has actually occurred.

...R