Stepper Motor speed controled by potentiometer / adding a speed change

Hi there,

I am a beginner in Arduino and need some help to do something that sounds simple but I can’t find the solution in my readings.

I am controlling a bi-polar stepper motor (Nema 17 / 17HS13-1204S) with a DRV8825 Driver and Arduino Nano.
The motor should run in continuous, the speed is controlled by a potentiometer. There is a button controlling the direction (FORWbutton = Forward), a STOP Button and a general ON button. Everything is working fine with the code I could write.

I would like to add a parameter that would make the motor run at half of the speed determined by the pot for 1 second when it start (when ONButton turns HIGH) , then at normal speed.

I have found some code doing that with fixed speeds but I can not figure out how to do this when the speed is determined by a pot.

Is there a simple way to do this?

Here is the code I have now :

const int stepPin = 3;
const int dirPin = 2;
const int sleepPin = 4; 
int customDelay,customDelayMapped; // Defines variables
const int FORWbuttonPin = 6;
int FORWbuttonState = 0;
const int ONbuttonPin = 7;
int ONbuttonState = 0;
const int STOPbuttonPin = 8;
int STOPbuttonState = 0;
 
void setup() {
  // Sets the two pins as Outputs
  pinMode(FORWbuttonPin, INPUT);
  pinMode(ONbuttonPin, INPUT);
  pinMode(STOPbuttonPin, INPUT);
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
  pinMode(sleepPin,OUTPUT);
  digitalWrite(dirPin,HIGH); //Enables the motor to move in a particular direction
}
void loop() {
  
  customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function
  // Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends
  
   FORWbuttonState = digitalRead(FORWbuttonPin);
  if (FORWbuttonState == HIGH)  {
    digitalWrite(dirPin, HIGH);
  } else {
    digitalWrite(dirPin, LOW);
  }
  STOPbuttonState = digitalRead(STOPbuttonPin);
  if (STOPbuttonState == HIGH)  {
    digitalWrite(sleepPin, LOW);
  } else {
    digitalWrite(sleepPin, HIGH);
  }
    ONbuttonState = digitalRead(ONbuttonPin);
  if (ONbuttonState == HIGH)  {
    digitalWrite(sleepPin, HIGH);
  } else {
    digitalWrite(sleepPin, LOW);
  }
  if (ONbuttonState == HIGH && STOPbuttonState == HIGH)   {
    digitalWrite(sleepPin, LOW);
  }
  
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(customDelayMapped);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(customDelayMapped);
}
// Function for reading the Potentiometer
int speedUp() {
  int customDelay = analogRead(A0); // Reads the potentiometer
  int newCustom = map(customDelay, 0, 1023, 5,300); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
  return newCustom;  
}

Hi Tookotook,

you can do this with the function millis()

millis() returns the milliseconds that have passed by since last power-on.

if you start the motor you store a snapshot if millis() in a variable of type unsigned long. It has to be variable-type unsigned long to make it work reliable.

as a raw sketch:

if button pressed
unsigned long millisAtButtonPress = millis();

Then you code an if-condition

if ( millis() - millisAtButtonPress < 1000) {
  DelayApplied = customDelayMapped * 2; // doubled delay => half speed
}
else {
  DelayApplied = customDelayMapped;
}

and use DelayApplied instead of customDelayMapped in the step-puls-creation.

it is good that yu have coded step-pulse-cration from scratch to understand how it works.

There is a library called AccelStepper that offers a lot of functions for a more comfortable stepper-control

and there is a library MobaTools that have stepper-motor-functions too

best regards Stefan

Hi Stefan,

It will take me some time to process your message (really beginner) but I know in which direction to search and that it’s possible, thanks !

I did read a bit about Accelstepper but I thought it would maybe be overkill for my simple project.

Hi tookotook,

if you describe what your little project is maybe an even better solution can be found.
AccellStepper and MobaTools offer user-adjustable acceleration / deceleration.
And MoBaTools offers functions for buttons, timers, pwm, servo, LED-fading

best regards Stefan

My project is simply to replace the motor of a film projector with a stepper motor that is able to run at low speeds with enough torque (the projector is used for film digitalization). The control buttons of the projector are connected to Arduino too to make it work like with the original motor.

It’s aleardy working with the simple code I have. The only problem is that sometime the motor get stucked when starting with the speed set too high (not enough torque I guess). I have to set a lower speed with the pot and then go back to the desired speed to make it work. That’s why I tought having an automatic start at half the speed could improve the system. A kind of really basic acceleration.

That’s why you need acceleration and deceleration. That will solve your problem. It’s definitely not overkill for your project. And its more simple to drive a stepper with a library than doing it by yourself.
And it is certainly gentler on the film to work with acceleration.

I researched a bit about Accelstepper but couldn’t find much about acceleration when a motor runs continuous. Most of the examples I found where from position to position.

I couldn’t experiment yet with the function millis(), I burned my Arduino yesterday mixing the 12V and 5V… I’m waiting for a new one.

You could take a look at MobaTools. It’s a little bit easier to handle, because you don’t have to bother with step generation in your sketch. This is done in the background. You can start and stop the motor at any time, and starting and stopping is done with acceleration and deceleration without anyhting you have to do for this ( beside telling it once that it should use a ramp to start and stop )

And I don’t understand how your buttons work. Are that buttons or switches? And if it are buttons, what is the state if they are not pressed? HIGH or LOW?

Regards, Franz-Peter

Sorry for the confusion, it’s switches not buttons. They stay HIGH when switched.

How do they work? Why do you need one for ‘start’ and one for ‘stop’ ? If they are switches you should ony need one: If its off the motor stands still, and if it’s on it runs.

There is a multi-switch controlling the direction and the stop in the projector, this switch is moving some mechanical parts at the same time. The position of those mechanical parts is not the same when the film is moving Forward and Backward, that’s why I integrate this multi-switch.

There is a general switch too ON/OFF (actually ON, 18fps, 24fps originally) that I want to use because easier to access when I work with the projector.

If you want to have a look, you can see the multi-switch on the right of this pictures :
https://van-eck.net/img/itable/images/film_13_T502%20Automatic%20Duoplay_1563969200434.jpg

without getting too complicated, it may be worth considering more slowly reducing customDelayMapped to the desired rate at startup in order to give the mechanism time to reach operating speed.

set customDelay to a large value and decrement by some amount each cycle until the desired rate is reached

Thanks for your input, could you develop a bit please? Do you mean doing this with an acceleration library?

when starting, customDelayMapped can be set to a relatively high value, driving the motor slowly. in loop(), after each step, that value can be reduced if it is not at some target value, the value read in speedUp()

ok, I got the idea.

With my poor skills, I tried to code it, should it look more or less like this ?


   FORWbuttonState = digitalRead(FORWbuttonPin);
  if (FORWbuttonState == HIGH)  {
    digitalWrite(dirPin, HIGH);
    customDelayMapped = 100
  } else {
    digitalWrite(dirPin, LOW);
  }

  if (customDelayMapped != speedUp())
  customDelayMapped++

I think using a library is in any case less complicated than doing it yourself in the sketch.

And what ist the sleepPin? I suppose, if you start/stop the motor by switching the sleepPin you will never get an acceleration/deceleration.
Please give a little bit information about your stepper and stepper driver.

don’t you want to decrement the value to increase speed

doesn’t the sketch need to determine a speed, or does the library determine the speed as well?

Oh yes, of course… it should be customDelayMapped–

It’s a bi-polar stepper motor (Nema 17 / 17HS13-1204S) with a DRV8825 Driver and Arduino Nano. I configured it in 1/4 steps mode. Yes, I use the sleepPin, I thought it would be the safest solution. Is that a problem ?

It’s a very hard method to stop the motor. This pin is not ment to stop the motor, but to set the device in power saving mode. Usually you stop a stepper motor by not creating steppulses. And this is the only possible method if you want to achive acceleration and deceleration.
You can additionally use the enable pin to switch off power to the motor if it is not turning. It will not get so hot then.

Another Question: In this line:

  int newCustom = map(customDelay, 0, 1023, 5,300); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)

Comment and code does not fit. Do you really want to have a delay of 5µs for your step creation? I suppose thats too fast. The comment says something different.