Problem getting the correct speed on my NEMA17+A4489+potentiometer project

Hi everyone,
I'm very new to Arduino but I want to build a pickup winder, here is my problem:

my project is using

  • an A4988 stepper driver
  • a NEMA17 stepper motor (model 17HS4023, 1,8 step angle, 12V, 0,7/phase, 4 wires); Vref screw is set to 0,48V
  • a 10K potentiometer
  • an Arduino uno

For this project I used the codes on this page https://miliohm.com/how-to-drive-a-stepper-motor-easily-using-a4988-and-arduino/, and my wiring follows the diagram shown in that page.

The first code works very well, I can modify the stepDelay time in microseconds and it effectively changes the speed of the stepper, I can go to 320 microseconds and that's about the speed I actually want for my pickup winder.

Here's the code:

// Define pin connections & motor's steps per revolution
const int dirPin = 2;
const int stepPin = 3;
const int stepsPerRevolution = 500;
int stepDelay=2000;

void setup()
{
// Declare pins as Outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
}
void loop()
{
//clockwise
digitalWrite(dirPin, HIGH);

// Spin motor
for(int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
}
delay(1000); // Wait a second

//counterclockwise
digitalWrite(dirPin, LOW);

// Spin motor
for(int x = 0; x < stepsPerRevolution; x++)
{
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
}
delay(1000); // Wait a second
}
Citation

My problem is that I want a potentiometer to control the speed of the stepper. To do that I hooked up a potentiometer as shown in the diagram, and put it on A0;
the monitor is reading the values between 0 and 1023 and effectively converts to 10000 to 0 in terms of microseconds stepDelay. I didn't change anything in the wiring except the presence of the potentiometer. And yet ... the stepper is very very slow, even at maximum speed: when the potentiometer is turned all the way down, monitor reads 0 and stepdelay is at 10000, and all the way up 1023 and 0, but the motor runs way way slower than that.

I tried to tweak the numbers to get close to what I would use in the real situation (2500 microseconds to 400), but the stepper still doesn't turn at the desired speed (and it also seems to rattle a lot).

Here is the second code:

// Define pin connections & motor's steps per revolution
const int dirPin = 2;
const int stepPin = 3;
const int stepsPerRevolution = 500;
int stepDelay = 700;

void setup()
{
// Declare pins as Outputs
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
Serial.begin(9600);
}
void loop()
{
//clockwise
digitalWrite(dirPin, HIGH);
int pot = analogRead(A0);
stepDelay=map(pot, 0, 1023, 10000, 0);
Serial.println(stepDelay);
// Spin motor
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
}

What am I doing wrong, or what am I missing?
At this stage I could probably start using this project as a winder, without a speed knob, but it's kind of frustrating to know that I'm only a few steps away from making it work!

Thanks everyone !

analogRead takes a significant amount of time (around 100us).
You need to take that into account.

thanks, but how would that translate into speed not being correct? (as I said I'm very new to this)

Because it slows down your loop.

1 Like

Look at the Stepper.h library. You can use it with the driver board. It takes the speed in RPM,and allows you to select how many steps you want the motor to take per call to Run() (all steps mean one full revolution).

1 Like

I don't think these 100µs of analogRead are the problem here. This is much less than the wanted step delay.
The problem is the Serial.print. This is called every loop cycle which fills your serial buffer up. And then Serial.print has to wait until a character is transmitted to make room in the buffer. And a baudrate of 9600 is really slow.

I will do that just now, thanks !
I had a lot of troubles finding the right tutorials using RPM instead of stepDelay values.

They are part of the problem

I must add one thing: the project DOES work, for every position of the pot, the shaft does turn at a different speed, but 100x slower than expected

You could use my MobaTools library. This allows to define the speed in RPM. And - in contrast to Stepper.h it is not blocking. You can simply change the speed with your pot while the motor is running.

Did you try to remove the Serial.print() ?

thank you! I will look into that if I still can't find my solution in Stepper.h !

yes, I just did, still super slow

Seems to be a problem with the map function - I never saw really low values. I tried, and without Serial.print it got faster, but not as fast as expected. If you omit the mapping ist goes the other way round ( regarding the potentiometer ), but much faster.

There is an example 'minimumStepper' which can easily be extended to your potentiometer variant:

/* ====== minimumStepper =======================================
 *  Bare minimum to get a stepper with step/dir driver turning
 */
#include <MobaTools.h>
// Stepper connections - Please adapt to your own needs.
const byte stepPin = 3;
const byte dirPin = 2;

const int stepsPerRev = 200;    // Steps per revolution - may need to be adjusted

MoToStepper stepper1( stepsPerRev, STEPDIR );  // create a stepper instance

void setup() {
  Serial.begin(9600);
  stepper1.attach( stepPin, dirPin );
  stepper1.setSpeed( 300 );              // 30 rev/min (if stepsPerRev is set correctly)
  stepper1.setRampLen( stepsPerRev / 2); // Ramp length is 1/2 revolution
  stepper1.rotate(1);                    // start turning, 1=vorward, -1=backwards                    
}

void loop() {
  int pot = analogRead(A0);
  int speed=map(pot, 0, 1023, 10,7500); // 1 ... 750 RPM
  Serial.println(speed);
  stepper1.setSpeed( speed );
  delay(100);
}
1 Like

YOU ARE A LIFE SAVER !
It works wonderfully :slight_smile:

Glad I could help you. :grinning: