Stepper motor - precision

Hi,
I'm using a esp32 and stepper motor: 17hS08-1004S + drv8825.
I wrote a simple test program, to understand how AccelStepper works.

I'm worry about one thing - I do only full turns in my code. Always never stepper doesn't stop in the start position. Even during 1-5 rounds.
I was trying to play with speed and acceleration but without any results.

Attaching example code.

Could you advise?
Thanks!

#include <Arduino.h>
#include <Wire.h>

#include <AccelStepper.h>

#define DEG_PER_STEP 1.8
#define STEP_PER_REVOLUTION (360 / DEG_PER_STEP)
#define DIR_PIN 18
#define STEP_PIN 19
#define TOUCHABLE 12
#define TOUCHABLE_THRESHOLD 60
#define MOTOR_INTERFACE_TYPE 1

#define MAX_SPEED 1500
#define SPEED 1000
#define ACCELERATION 6000
#define ROUNDS 20

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(MOTOR_INTERFACE_TYPE, STEP_PIN, DIR_PIN);

void printSpeed();
void constantMove();

void setup() {
  Serial.begin(115200);

  // Set the maximum speed in steps per second:
  stepper.setMaxSpeed(MAX_SPEED);
  stepper.setAcceleration(ACCELERATION);
  stepper.setCurrentPosition(0);
}


uint32_t lastTime = millis();
int32_t lastPos = 0;
bool isRuning = false;

void loop() {

  const int touch = touchRead(TOUCHABLE);
  if (touch < TOUCHABLE_THRESHOLD) {
    Serial.printf("Touched: %d, Starting... \n", touch);

    int posToGo = ROUNDS * STEP_PER_REVOLUTION;
    int speed = SPEED;

    if (posToGo == stepper.currentPosition()) {
      posToGo = 0;
      speed = -speed;
    }

    stepper.moveTo(posToGo);
    stepper.setSpeed(speed);

    isRuning = true;
    delay(200);
  }

  if (stepper.distanceToGo() == 0 && isRuning == true) {
    Serial.printf("Finished! CurrentPos: %d\n", stepper.currentPosition());
    isRuning = false;
  }

  printSpeed();

  //constantMove();
  stepper.run();
}

void constantMove() {
  stepper.setSpeed(SPEED);
  stepper.runSpeed();
}

void printSpeed() {

  const int32_t pos = stepper.currentPosition();
  static const int printPerRounds = 5;
  if (pos % (( int )STEP_PER_REVOLUTION * printPerRounds) == 0 && lastPos != pos) {
    const uint32_t currentTime = millis();
    Serial.printf("Current pos = %d,  Time = %d \n", stepper.currentPosition(), (currentTime - lastTime));
    lastTime = millis();
    lastPos = pos;
  }

}

Are you using a 12V or more power supply with at least a 2.5A rating?
Did you put a 100uF on the Vmot pin?
Did you set the current to 1A?

Hi @last_not_used_login

not sure if this is your problem but feel free to have a look at this sketch:

/*
  Forum: https://forum.arduino.cc/t/stepper-motor-precision/1213294
  Wokwi: https://wokwi.com/projects/387378409878463489

*/


#include <Arduino.h>
#include <Wire.h>

#include <AccelStepper.h>

#define DEG_PER_STEP 1.8
#define STEP_PER_REVOLUTION (360 / DEG_PER_STEP)
#define DIR_PIN 18
#define STEP_PIN 19
#define TOUCHABLE 12
#define TOUCHABLE_THRESHOLD 60
#define MOTOR_INTERFACE_TYPE 1

#define MAX_SPEED 1500
#define SPEED 1000
#define ACCELERATION 6000
#define ROUNDS 20

//Just to simulate the Touch with a button
const byte buttonPin = 14;

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(MOTOR_INTERFACE_TYPE, STEP_PIN, DIR_PIN);

void printSpeed();
void constantMove();

void setup() {
  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP);

  // Set the maximum speed in steps per second:
  stepper.setMaxSpeed(MAX_SPEED);
  stepper.setAcceleration(ACCELERATION);
  stepper.setCurrentPosition(0);
}


uint32_t lastTime = millis();
int32_t lastPos = 0;
bool isRuning = false;

void loop() {

  int touch = touchRead(TOUCHABLE);
  touch = isTouchedByButton();
  if (touch < TOUCHABLE_THRESHOLD && !isRuning) {
    Serial.printf("Touched: %d, Starting... \n", touch);

    int posToGo = ROUNDS * STEP_PER_REVOLUTION;
    int speed = SPEED;

    if (posToGo == stepper.currentPosition()) {
      posToGo = 0;
      speed = -speed;
    }

    stepper.moveTo(posToGo);
    stepper.setSpeed(speed);

    isRuning = true;
    delay(200);
  }

  if (stepper.distanceToGo() == 0 && isRuning == true) {
    Serial.printf("Finished! CurrentPos: %d\n", stepper.currentPosition());
    isRuning = false;
  }

  printSpeed();

  //constantMove();
  stepper.run();
}

void constantMove() {
  stepper.setSpeed(SPEED);
  stepper.runSpeed();
}

void printSpeed() {

  const int32_t pos = stepper.currentPosition();
  static const int printPerRounds = 5;
  if (pos % (( int )STEP_PER_REVOLUTION * printPerRounds) == 0 && lastPos != pos) {
    const uint32_t currentTime = millis();
    Serial.printf("Current pos = %d,  Time = %d \n", stepper.currentPosition(), (currentTime - lastTime));
    lastTime = millis();
    lastPos = pos;
  }
}

int isTouchedByButton(){
  if (digitalRead(buttonPin) == LOW) {
    return 0;
  }
  return 100;

}

And check it out on Wokwi: https://wokwi.com/projects/387378409878463489

I introduced a function that simulates the touch by a button.

The main change is in this line

 if (touch < TOUCHABLE_THRESHOLD && !isRuning) {

On command the stepper goes from 0 to 4000 , stops there and with the next command it returns back to 0.

Good luck!

I have a 100uF capacitor, vref is set for 0,5V
My power supply have a limit around 4 or 5 Amps.

Are you suggest to increase the vref? I have read without micro steps connected, vref should be higher for 40%

That is true but I would not set it at the maximum, 0.65V for vref would be OK.
Otherwise your hardware set-up is good. So something wrong in the code.

Also remenber that steppers can loose steps when under a load and/or with high acceleration rates

Nope, Vref sets the current the same for any step setting. Definitely good to use some microstepping rather than full-steps, with full steps its very prone to miss-stepping due to resonance.

Depends on the torque you need. In full step position ( both coils are engaged with the same current) the DRV8825 sets the current to 71% of the setting. As already mentioned this is independent from the microstep setting. If you don't need the full torque this is better for stepper and driver ( they don't get as hot).

I increased VREF to 0,65V ~ 1.3A.
Seems the problem with precision is because of acceleration setting. When I put incredible high value as an acceleration than stepper is precise.
I guess I don't know how to use acceleration.

What is "incredible high value?" We can't read your mind: use numbers.
If your acceleration is too slow, the stepper may pass through a resonant speed point where it will jitter around and lose steps.

Conversely, if acceleration is too fast, then it may not turn at all. Mechanical systems are interesting :slight_smile:

100k

Could you explain how to adjust the acceleration?

You do it here. Try a lower number like 25000.

As adjust I meant adjusting of the number.
Could you explain what factors decide what the number should be?

Thanks!

Basically how fast you want it to accelerate. Acceleration will be limited by the voltage available from the supply and the inertia of the load. In more complex controller, I've been able to avoid the resonance (if indeed that's what the problem is) by setting the starting speed above zero, but if you can't do that then the next best thing is to change the acceleration.

If what you have now works, keep it.

Ok, so my understanding:
If the motto has high/ to high resonance
Than acceleration doesn't work and have to be high to break a resonance threshold. Where the voltage is a factor.
Is that correct?

Thanks!

Have you tried starting with acceleration of say, 400 and increasing gradually?

I started from 100. Finished with 100k, but I was multiplied by 10.
When acceleration is low,stepper loses the steps.
Do you know the explanation?

Thanks

Sorry, I don't,

Perhaps mid-band resonance - lower acceleration means the motor has more time at the resonant speed and is more likely to jump steps. Fix is more microstepping or mechanical damping, and keep the acceleration faster enough to pass mid-band quickly.

An unloaded stepper motor is very resonant, its perhaps the worst case.

So in theory activating the micro step should make acceleration possible. Is that correct?

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