Stepper motor control using millis()

Hi, I've been trying to use millis() for assigning speed to my stepper motor, and it's work. But the problem is how to assign the distance. For example, move the motor 10 mm up and 10 mm down with any speed buy using millis o micros

// Example sketch to control a stepper motor with TB6600 stepper motor driver and Arduino without a library: number of revolutions, speed and direction.
// Define stepper motor connections and steps per revolution:
#define dirPin 2
#define stepPin 3
#define stepsPerRevolution 6400
unsigned long previo1 = 0;
unsigned long previo2 = 0;
unsigned long current;
boolean estado1 = false;
boolean estado2 = false;
int velocidad; //speed
int desplazamiento = 50; //data en mm

void setup() {
  // Declare pins as output:
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
}

void loop() {
  digitalWrite(dirPin, HIGH); //direction.
  for (int i = 0; i < desplazamiento; i++) //distance
  {
    girar_arriba();
  }
  digitalWrite(dirPin, LOW);//direction.
  for (int i = 0; i < desplazamiento; i++) //distance
  {
    girar_abajo();
  }
}
void girar_arriba()
{
  for (int i = 0; i < 1280; i++)//1280 move 1mm
  {
    current = micros();
    while (current - previo2 > 187) {
      previo2 = current;
      if (digitalRead(3))
        digitalWrite(3, false);
      else
        digitalWrite(3, true);
    }
  }
}
void girar_abajo()
{

  for (int i = 0; i < 1280; i++)//1280 move 1mm
  {
    current = micros();
    while (current - previo1 > 187) {
      previo1 = current;
      if (digitalRead(3))
        digitalWrite(3, false);
      else
        digitalWrite(3, true);
    }
  }
}

Hi @peter_hr

welcometo the forum.
well done to post your code as a code-section.

trying to move a stepper-motor for a certain distance by measuring time is over-complicated.

Calculate the number of steps that are equal to 10 mm.

If your comment

is correct there is written: 1280 steps = 1mm
10 mm would be 1280 * 10 = 12800 steps.
Drive 12800 steps at whatever speed your stepper-motor can drive and you are done.

There are several libraries for driving stepper-motors. I recommend to use the library called MobaTools.
The big advantage of the MobaTools is step-creation in the backround.
This enables to do things "in parallel" to running the stepper-motor.

You can install the MobaTools-library from the library-manager of the arduino-IDE

This is the documentation
https://github.com/MicroBahner/MobaTools/blob/master/MobaTools-243-en.pdf
Many users use this library and the author is active in the forum here too.

best regards Stefan

Ohh thanks for answering, I wouldn't like to use a library, and I tried to do that (1280*n) but it doesn't work, maybe because for instruction has a limit

Are you forced to not use a library?
If not what is the reason for "not liking to use a library?"

you are using integer-variables
integers are signed integers with a value-range of +- 32768
If your number go beyond +32768 you get negative numbers
use unsigned long
which can count up to 4.294.967.295 (2^32 - 1)

If you want precise help you will have to post always your complete sketch

best regards Stefan

the above code isn't do what you think. the while condition will only be true when the time difference is > 187. so instead of stepping the motor 1280 times, it may only step the motor a few times.

i beleive (not tested) the following to move the stepper the desired distance (10mm), but not necessarily the way you want with a timer (presumably instead of a delay.

void girar_abajo ()
{
    for (int i = 0; i < 1280; i++)  {
        digitalWrite (3, LOW);
        delayMicroseconds (187);
        
        digitalWrite (3, HIGH);
        delayMicroseconds (187);
    }
}

It's a project, so for that, I prefer not to use a library, I'll need to use millis and micros, and some libraries use only micros or milli, and I need both of them

Thanks, I've use that code, but have a error and I need more precision

not a real reason.

completely nonsense
you can use millis() and micros() whereever and how often you want

very unprecise description. more precision in what? And how much precisision in numbers?

this is blocking code. No advantage over using delayMicroseconds()

What driver are you using?

Most stepper drivers do not need a 50% duty cycle square wave on the pin, and you could use a simpler, blocking

  digitalWrite(stepPin,HIGH);
  digitalWrite(stepPin,LOW);
  delayMicroseconds(374);

or a nice non-blocking millis-based step routine:

void stepAsNeeded(unsigned long interval){
  static unsigned long lastStepUs = 0;
  unsigned long now = micros();
  if(now - lastStepUs < interval  || stepsToGo == 0) {
     return;
  }
  // otherwise, take a step
  digitalWrite(stepPin,HIGH);
  lastStepUs = now;
  --stepsToGo;
  digitalWrite(stepPin,LOW);
}

This modification of your code calls that non-blocking routine in loop(), along with a little bit of a state machine to initiate new moves whenever it stops.

// https://wokwi.com/projects/364535266637057025
// for https://forum.arduino.cc/t/stepper-motor-control-using-millis/1126030

// Example sketch to control a stepper motor with TB6600 stepper motor driver and Arduino without a library: number of revolutions, speed and direction.
// Define stepper motor connections and steps per revolution:
#define dirPin 2
#define stepPin 3
#define stepsPerRevolution 6400UL
unsigned long previo1 = 0;
unsigned long previo2 = 0;
unsigned long current;
boolean estado1 = false;
boolean estado2 = false;
int velocidad; //speed
int desplazamiento = 50; //data en mm
unsigned long usPerStep = 187 * 2;

void setup() {
  // Declare pins as output:
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  Serial.begin(115200);
}

unsigned long stepsToGo = 0;
int mode = 0;

void loop() {

  if (stepsToGo == 0 ) { // setup new motion
    if (mode == 0 ) {
      Serial.print('H');
      digitalWrite(dirPin, HIGH); //direction.
      stepsToGo = desplazamiento * stepsPerRevolution;
      mode = 1; // plan following motion
    } else {
      Serial.print("L");
      digitalWrite(dirPin, LOW);//direction.
      stepsToGo = desplazamiento * stepsPerRevolution;
      mode = 0; // plan following motion
    }
  }
  stepAsNeeded(usPerStep);
}

void stepAsNeeded(unsigned long interval) {
  static unsigned long lastStepUs = 0;
  unsigned long now = micros();
  if (now - lastStepUs < interval  || stepsToGo == 0) {
    return;
  }
  // otherwise, take a step
  digitalWrite(stepPin, HIGH);
  lastStepUs = now;
  --stepsToGo;
  digitalWrite(stepPin, LOW);
}

Hello, how's it going. I'm using TB6600 driver by Toshiba, I will try to test your code, and thanks for answering

Excuse me, how can I stop this code, for example, I only want to do 5 cycles, I try to do it with for cycle , but it doesn't work, could you show me an idea, please?

This code?

I'd use a global variable to keep track of the 5 cycles, decrement each time a cycle finishes, and add an if statement:


int cycles = 5;  // how many cycles to run

void loop() {

  if(cycles > 0){
  
  if (stepsToGo == 0 ) { // setup new motion
    if (mode == 0 ) {
      Serial.print('H');
      digitalWrite(dirPin, HIGH); //direction.
      stepsToGo = desplazamiento * stepsPerRevolution;
      mode = 1; // plan following motion
    } else {
      Serial.print("L");
      digitalWrite(dirPin, LOW);//direction.
      stepsToGo = desplazamiento * stepsPerRevolution;
      mode = 0; // plan following motion
      cycles = cycles -1; // Finished a H+L cycle, so count down. 
    }
  }
  
  } // end of cycle check

  stepAsNeeded(usPerStep);
}

This makes it possible so that if you ever need to restart the 5 cycles, you could add some button check that reloads by resetting cycles = 5;

Thanks, I was thinking to do that, cuz I tried differents ways and none of them worked. I will try that form tomorrow, good evening

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