Using a stepper motor without delayMicroseconds

Hello
I am using a TB6600 stepper driver using the code example below and it works fine but I need a way for it to work without using delayMicroseconds, because I don't want delays when I eventually start adding other functions. I've tried using other available libraries but they require inputs of 2 or 4 pin connections when I am using 3 Arduino pins. I've tried using the example of "blink without delays" but the motor starts to stutter & doesn't run properly.

I am new to Arduino & would greatly appreciate if someone could put me on the right path to write a function(s) to control my stepper motor independently.

Thanks in advance.

CODE:


const int stepPin = 5; 
const int dirPin = 2; 
const int enPin = 8; 

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600); // initialize the serial port:
 Serial.println("Ready to go!!!");
 pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
   pinMode(enPin, OUTPUT);

     digitalWrite(enPin, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

for (int x = 0; x < 200; x++) { //previously 800

digitalWrite(stepPin, HIGH);
delayMicroseconds(500);
digitalWrite(stepPin, LOW);
delayMicroseconds(500);
}
delay(1000);

}

Show us your attempt.

Indeed, the "blink without delay" method should drive the stepper to moderate speeds. It is the method used by the AccelStepper library.

A different method is to use Timer interrupts. MobaTools is a good full featured stepper library with this method.

Setting up the timer interrupts using timer libraries like TimerOne or by coding the timers yourself is another route.

Robin2's simple stepper program tutorial has an example of how to write stepper code using millis() for step timing.

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW

byte directionPin = 9;
byte stepPin = 8;

byte buttonCWpin = 10;
byte buttonCCWpin = 11;

boolean buttonCWpressed = false;
boolean buttonCCWpressed = false;

byte ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds

void setup() { 

     Serial.begin(9600);
     Serial.println("Starting Stepper Demo with millis()");

     pinMode(directionPin, OUTPUT);
     pinMode(stepPin, OUTPUT);
     pinMode(ledPin, OUTPUT);
     
     pinMode(buttonCWpin, INPUT_PULLUP);
     pinMode(buttonCCWpin, INPUT_PULLUP);
     
}

void loop() { 
    
    curMillis = millis();
    readButtons();
    actOnButtons();
    
}

void readButtons() {
    
    buttonCCWpressed = false;
    buttonCWpressed = false;
    
    if (digitalRead(buttonCWpin) == LOW) {
        buttonCWpressed = true;
    }
    if (digitalRead(buttonCCWpin) == LOW) {
        buttonCCWpressed = true;
    }
}

void actOnButtons() {
    if (buttonCWpressed == true) {
        digitalWrite(directionPin, LOW);
        singleStep();
    }
    if (buttonCCWpressed == true) {
        digitalWrite(directionPin, HIGH);
        singleStep();
    }
}

void singleStep() {
    if (curMillis - prevStepMillis >= millisBetweenSteps) {
            // next 2 lines changed 28 Nov 2018
        //prevStepMillis += millisBetweenSteps;
        prevStepMillis = curMillis;
        digitalWrite(stepPin, HIGH);
        digitalWrite(stepPin, LOW);
    }
}

And +1 for the MobaTools stepper library. Easier, I think, to learn and use than Accelstepper.

Hi LarryD
Please see code below. 500 micros is the maximum time between digital writes before the motor throws a wobble. So it seems like when I add functions & additional code that causes a problems as it would take more than 500 micros to make the next digitalWrite, rather than having only a simple "for loop" in my sketch..


const int stepPin = 5; 
const int dirPin = 2; 
const int enPin = 8; 
int x = 0; 

unsigned long previousMicros = 0;  
const long interval = 500; 
unsigned long previousMicros2 = 0; 
const long interval2 = 500;  //
unsigned long checkintervalfinished = 0; 
unsigned long checkintervalfinished2 = 0; 
 unsigned long currentMicros;
 unsigned long currentMicros2;
int y = 0;
int HIGHonoff =0;
int LOWonoff =1;
int seconddelay=0;
int firstdelay=0;

void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600); // initialize the serial port:
 Serial.println("Ready to go!!!");
 pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
   pinMode(enPin, OUTPUT);

     digitalWrite(enPin, LOW);
  
}



void loop() {
  // put your main code here, to run repeatedly:
 currentMicros = micros();
currentMicros2 = micros();


 //  runonce
 if (y == 0){
y = 1;
 
   checkintervalfinished  = currentMicros;
    checkintervalfinished2  = currentMicros;
    previousMicros = currentMicros;  
    previousMicros2 = currentMicros;  
     digitalWrite(dirPin, HIGH);
 }

 

   if (x < 200) { 
    Serial.println("looping     222");
  x++;
  loop1();
 // -------------------------loop2();
  }
 
}


void loop1(){

  if(HIGHonoff ==0){
   digitalWrite(stepPin, HIGH); 
   HIGHonoff=1;
  }

  
 if(firstdelay ==0){
      if (micros() >= checkintervalfinished + interval  ){
 // if (currentMicros - previousMicros >= interval) {
 //Serial.println(currentMicros);
       Serial.println("firstdelay");
  //  previousMicros = currentMicros;
    digitalWrite(stepPin, LOW);
     LOWonoff = 0 ;

     firstdelay = 1;
 }
 }

 
 if(LOWonoff ==0){
   Serial.println("LOWonoff");
     LOWonoff = 1 ;
  checkintervalfinished  = currentMicros;
    checkintervalfinished2  = currentMicros;
    previousMicros = currentMicros;  
    previousMicros2 = currentMicros;  
   // seconddelay
   // loop2();
 }
if (firstdelay == 1 ) loop2();
 
}
void loop2(){
    if (micros() >= checkintervalfinished2 + interval  ){
  //if (currentMicros2 - previousMicros2 >= interval2) {
 //Serial.println(currentMicros2);
       Serial.println("loop2");
  checkintervalfinished  = currentMicros;
    checkintervalfinished2  = currentMicros;
    previousMicros = currentMicros;  
    previousMicros2 = currentMicros;  
    firstdelay=0;
seconddelay=0;
HIGHonoff=0;
  Serial.println("break");
    
//digitalWrite(stepPin, LOW);
  
  }
}

  



void runonce(){

digitalWrite(dirPin, HIGH);
   Serial.println(x);
if (x < 200) { //previously 800
 x++;
 delayMicroseconds(500);
 digitalWrite(stepPin, HIGH); 
 delayMicroseconds(500);
digitalWrite(stepPin, LOW);

}


//else (digitalWrite(stepPin, LOW));


}

Hi cattledog

I've installed MobaTools library and it seems to be on the right track, the only problem is the comments in the code are written in German :face_with_head_bandage:, so its taking me a while to work it out using google translate and I also need to figure out how to make it work without using button pins in the example.

Hi groundfungus

Thanks for the advice but AccelStepper functions require 4 pins, while I am only using 3 pins (stepPin = 5, dirPin = 2 and enPin = 8).
Also, 500 micros is the maximum delay between digitalWrite(s) before my motor starts to malfunction, so I can't get it working with millis. I tried 0.5 millis which I thought would be the same as 500 micros but to no avail.

But there is also a documentation in english. And there are some examples commented in english. E.g this one, which also doesn't use any button.

Depends how you create the AccelStepper object. AccelStepper can be used with step/dir drivers too.

500 micros HIGH then 500 LOW is 1000 steps per second or 300 RPM for a 200 step motor, hard (impossible?) to do without acceleration.
Try:

digitalWrite(stepPin, HIGH);
delayMicroseconds(20);
digitalWrite(stepPin, LOW );
delayMicroseconds(20000); // 20 thousand

Work speed up by reducing LOW time by 2000 at a time until you find the max speed without missing steps.

Thank you all for your advice and recommendations. The only example I managed to get working properly was MobaTools library (now that I have the english version of the manual).

However, there is one issue using MobaTools library, whenever the motor stops moving it seems like it de-magnetises the coils, so the motor shaft has no resistance/tension which I need to hold my robot arm in position until I am ready to move to the next position.

This does not not happen if I use a simple for loop and delayMicroseconds but I would prefer to use MobaTools library, however I can't see anything in the user manual that address this issue?

That can only be done by the enable input of the driver. This is done by MoToStepper only if you explicitely tell MoToStepper to do so ( with the attachEnable() method ). If you don't attach the enable pin to MoToStepper it has no possibility to disable the coils.

Hi MicroBahner

I commented out the line // myStepper.attachEnable( enPin, 10, LOW ); and it did indeed keep the coils enabled while the stepper was stationary.

THANK YOU VERY MUCH

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