Go Down

Topic: Stepper motorcontrol with variable rotation speed  (Read 320 times) previous topic - next topic

kosbu

Hi all,

I use the stepper library to set the rotation speed of a stepper motor set by a potentiometer connected to the analogue pin A0. I also use a rotary encoder to read motor's rotation speed.
I realized though, a full rotation of the stepper motor is needed before any change in the actual motor speed happens. for example, if I run the stepper at 1 rpm, I can change my potentiometer value several times in one minute but the motor will not change its speed. This is a problem for me as I need to run the stepper motor at very low speeds.

Is there any other way or library that will help me to achieve a more frequent speed update at low speeds?

I am no such an expert programmer so please have mercy :)

Code: [Select]

#include <Stepper.h>

const int phaseB = 2;
const int phaseA = 3;
int valuePhaseB = 0;
volatile long pulses = 0;
unsigned long timeO = 0;
unsigned long timeF = 0;
float encoderSpeed = 0;
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
// for your motor


// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 7, 6);

int stepCount = 0;  // number of steps the motor has taken

void setup() {
 Serial.begin(9600);
  pinMode(phaseA, INPUT);   // configure the I.0 as a INPUTS
  pinMode(phaseB, INPUT);
  attachInterrupt(digitalPinToInterrupt(phaseA), detectPulses, RISING);    // enable external interrupt with a rising edge of PhaseA
  timeO = millis();   // Initialize initial time
}

void loop() {
  // read the sensor value:
  int sensorReading = analogRead(A0);
  // map it to a range from 1080 to 1:
  int motorSpeed = map(sensorReading, 0, 1023, 1080,1);
  // set the motor speed:
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution);
  }

  timeF = millis();     // Geting the final time to get the speed
    encoderSpeed = ((float)pulses/360.0) / ((float)(timeF - timeO) / (60000.0));
    Serial.print("Speed: ");
    Serial.print(encoderSpeed);     // Printing speed value
    Serial.println(" rev/min");
    pulses = 0;    // Initialize pulses to count again
    timeO = millis();    // Initialize initial time again
}


void detectPulses() {
  if (digitalRead(phaseB) == LOW) { //Confirm if we are turning on CW direction.
    pulses++;    // Adding pulses
  }
  else { //Confirm if we are turning on CCW direction.
    pulses--;    // Substraing pulses
  }
}


Any help would be much appreciated.


Robin2

The way the Stepper library works it blocks the Arduino until the move completes.

If you change you code so that it moves one step at a time and your program controls the interval between steps (which is what governs the speed) then you can check the potentiometer after every step.

You may also wish to look at the AccelStepper library which is much more comprehensive and allows non-blocking movement.


I don't understand why you are using an encoder to detect the speed. Your program should already know the speed from the interval between step pulses.


...R
Stepper Motor Basics
Simple Stepper Code
Two or three hours spent thinking and reading documentation solves most programming problems.

kosbu

Hello Robin2,

Thank you very much for your replay.

I will try the step by step solution but it doesn't sound very efficient. I changed the steps per revolution variable to 50 and that gave me speed check and set every 50  steps but I could notice extra vibration on the motor,  probably because the library halts the motor when other stuff is executed. I don't really like this.

I tried to use accelStepper but I don't know how to make use of the non-blocking movement.
If I understand well some people manage to use the PWM hardware to achieve what I want but I can't find any example about it.

The code is just a first attempt to make all the hardware work together. The final application will be a winder active tensioner. the stepper motor will have to follow the speed of another motor red through the encoder. Some final adjustments then will be done to the speed according to the potentiometer's position.


Robin2

I will try the step by step solution but it doesn't sound very efficient.
There is nothing less efficient about it. The calculations have to be either in your code or in the library code.

Quote
I changed the steps per revolution variable to 50 and that gave me speed check and set every 50  steps but I could notice extra vibration on the motor,  probably because the library halts the motor when other stuff is executed. I don't really like this.
It suspect you are correct about the hesitations after every 50 steps. But if you do it step by step that won't be noticeable.

Quote
I tried to use accelStepper but I don't know how to make use of the non-blocking movement.
Without seeing the code you tried I can't help

Quote
If I understand well some people manage to use the PWM hardware to achieve what I want but I can't find any example about it.
I doubt very much that it is necessary or useful to use the PWM hardware.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

luni64

Quote
The code is just a first attempt to make all the hardware work together. The final application will be a winder active tensioner. the stepper motor will have to follow the speed of another motor red through the encoder. Some final adjustments then will be done to the speed according to the potentiometer's position.
Thats an interesting problem. Instead of measuring the speed of the master motor and then setting the speed of the slave motor I would basically monitor the encoder and generate a step / dir pulse for the slave whenever the encoder value changes by 1.
More realistically: The number of master-encoder values per rev probably doesn't match the number of slave steps per rev.  => You need to multiply the encoder value by a factor and issue a stp/dir signal whenever the rounded mulitplied encoder value changes by 1 or -1.

--
Example (just an idea, not tested)
Encoder: 5000 pulses per rev
Stepper: 1600 pulses per rev

1) Monitor encoder and multiply the current encoder value by 1600/5000 = 0.32
2) if the new, mulitplied value differs by more than 1 from the old value, genereate a step
--
If you want to fine adjust the  slave speed you can adust the factor. If you set it to say 1.1*0.32 = 0.352 the speed of the  slave motor would be 10% slower than that of the master motor.
Fast Stepper library? -> https://luni64.github.io/TeensyStep/

Go Up