Stepper motor-total no of rotations control

Hi,
I am using arduino uno to control bipolar stepper motor.
Following is the code I am using:

#include <Stepper.h>
Stepper stepper(200, 8, 9, 10, 11);
void setup()
{
// set the speed of the motor to 30 RPMs
stepper.setSpeed(30);
}
void loop()
{
stepper.step(200);
}

My stepper motor keeps on running at the given speed (30 RPM) and no.of steps per rotation (200) without stopping.I want to stop the motor after a particular no of rotation.,say 200. How can I achieve that?

The loop function runs repeatedly forever, so it is doing what you asked. Time to learn about if statements.

Yeah thanks mike! :)...I am aware of the 'if' statement..but what is the logic I must use here to implement it?..how to stop the motor after a certain no of rotations without using any hardware feedback?

You need a variable that keeps track of how many steps the motor has done (or has been asked to do).

For example if you say stepper.step(200); you would add 200 to the total.

When the motor has done as many steps as you want you would stop telling it to move.

...R

At start up you can do one-off actions by calling them from setup(), otherwise you'll need to use some sort of condition to trigger them, tested in loop().

I am new to Arduino Programming. Can someone give me the code to stop the motor after certain rotations? I am not able to comprehend what stepper.step() function does.Varying of stepper.step() function doesn't seem to have any effect on the motor functioning in the above program. When I gave the command stepper.step(10) in the above program it still kept on rotating for steps more than 10 (may be because of loop).

stepper.step sends a fixed number of steps to the motor to turn it. You repeatedly call this function so you never see it stop. So move that single instruction in the loop function into the setup function at the end.

Alternitave after the step command in loop follow it by

 while(1) ;

That will hold the code forever.

Thanks Mike :). I hope the following is what you meant. Now in the following code, the motor will stop after 200 steps right?
(since it is not inside the loop). My motor takes 200 steps for one complete rotation. So if I want two complete rotation,I must call Stepper.step(200) twice inside the setup(). Is this what you meant?

#include <Stepper.h>
Stepper stepper(200, 8, 9, 10, 11);
void setup()
{
// set the speed of the motor to 30 RPMs
stepper.setSpeed(30);
stepper.step(200);
}
void loop()
{
}

viz_90: So if I want two complete rotation,I must call Stepper.step(200) twice inside the setup(). I

Wouldn't it make more sense to call Stepper.step(400): ?

Or, more generally,

numRevs = 2;
numSteps = numRevs * 200;
Stepper.step(numSteps);

...R

Robin2:

viz_90: So if I want two complete rotation,I must call Stepper.step(200) twice inside the setup(). I

Wouldn't it make more sense to call Stepper.step(400): ?

Or, more generally,

numRevs = 2;
numSteps = numRevs * 200;
Stepper.step(numSteps);

...R

But the motor which I am using has maximum steps of only 200 per revolution. Beyond that I cant use default stepper.step() function. I have to code it separately for micro-stepping which increases the complexity of the code

below Void Loop

void loop() { stepper.step(200); }

this is calling for the motor to take 200 steps, end, then start at the beginning, take 200 steps, end, start from the beginning.....

void loop()
{
     numRevs = 2;
     numSteps = numRevs * 200;
     Stepper.step(numSteps);

this will look at numRevs and multiply that by 200

then move the stepper that many steps, 400 in total, or 2 full rotations if the motor is in full step mode then....

end, look at the numRevs, multiply that by 200, move the motor 200 steps, end, look at numRevs.....

add a switch. then add an IF statement to test if the switch is high or low. or add a button that would run the number of steps and then reset.

at some point you will need to tell numSteps a specific value that you set from elsewhere.

viz_90: But the motor which I am using has maximum steps of only 200 per revolution. Beyond that I cant use default stepper.step() function. I have to code it separately for micro-stepping which increases the complexity of the code

I don't understand what you are trying to say here.

The example I have given is of course trivially simple and real code will need to be more complex. But simple code is always the best way to understand the principles.

Staying with the simple code, if you know how many microsteps there are per step you can modify my example like this

numRevs = 2;
numMIcroSteps = 8;
numSteps = numRevs * 200 * numMicroSteps;
Stepper.step(numSteps);

The trick with any non-trivial programming project is to think of it as a series of small pieces each of which is easy to understand and debug.

For example you might have a function in your code which figures out how many steps are needed for the next move and save that value in a variable. Then a separate function would read the value from that variable and make the motor move through the appropriate number of steps. The little snippet of code, above, is almost all you would need in the motor-move function.

The great thing about the Arduino system is that you can easily write a short piece of code to test an idea and see what happens. If it is not doing what you expect try to figure out what is causing it to do what it is actually doing rather than trying to figure out what it is not doing.

I suggest you do that here and then post your code so we have something concrete to comment on.

...R

viz_90: But the motor which I am using has maximum steps of only 200 per revolution. Beyond that I cant use default stepper.step() function. I have to code it separately for micro-stepping which increases the complexity of the code

I take this to mean you are not looking in the void loop but in the initialization area before void setup.

void loop ()
{
if(x==0){
   numSteps = 400;
   Stepper.step(numSteps);
   x=1;
}

now, figure out how to change that 400

I have written the following code.
Here the input for no of rotation and direction of rotation is given by user. I am not sure if this program is correct. Kindly correct if there is any mistakes.

Void setup()
{
serial.begin(9600);
stepper.setspeed(30);
}

Void loop()
{
if (serial.available>=2)
{
int rotations=serial.read(); //reads the no of rotation input from terminal
int direction=serial.read(); //reads the direction of rotation ‘1’ for clockwise, ‘2’ for anti clockwise

if(direction==1)
{
for(i=1;i<=rotations;i++)
{
stepper.step(200);
}
}

if(direction==2)
{
for(i=1;i<=rotations;i++)
{
stepper.step(-200);
}
}
}

Kindly correct if there is any mistakes.

Well for a start it is not in code tags, only you can correct that. Read the how to use the forum sticky post.

It helps if at least you have tried to compile the code:-

if (serial.available>=2)  
// should be
if (serial.available() >=2)

Next you do not get numbers from a serial read you get ASCII characters so lines like

for(i=1;i<=rotations;i++)

are not going to work. Even if they did you are only reading one byte and that is a single digit 1 to 9.

The basic idea is right but you do not understand how the serial read works.

Hi Mike!..Thanks for pointing out that serial read() returns ASCII characters. I am not in Lab right now. So I couldn’t compile to find that bracket is missing in Serial.available(). Here is my updated code. Will this solve the problem of ASCII to Integer conversion?

Void setup()
{
serial.begin(9600);
stepper.setspeed(30);
}

Void loop()
{

char buffer1={’’,’’,’’}; \ 3 byte buffer for no of rotation
char buffer2={’’}; \ 1 byte buffer for direction

if (serial.available())
{
serial.readbyteUntil(’\n’,buffer1, 3); \receives 3 byte for no of rotation
serial.readbyteUntil(’\n’,buffer2, 1); \receives 1 byte for direction
int rotations=atoi(buffer1); //converts ASCII To Integer
int direction=atoi(buffer2); //converts ASCII To Integer
if(direction==1)
{
for(i=1;i<=rotations;i++)
{
stepper.step(200);
}
}

if(direction==2)
{
for(i=1;i<=rotations;i++)
{
stepper.step(-200);
}
}
}

Will this solve the problem of ASCII to Integer conversion?

No and you have to start posting code correctly from now on.

Your buffers are not big enough, they have to be able to cope with the terminating characters as well as any junk at the start. Like you will get if the terminal sends a LF and CR.

Use

char buffer1[ 8 ] ; 
char buffer2[ 4 ] ;

To be on the safe side.
I would output the numbers you get back to the serial port just to be on the safe side.

Void setup()
{ 
serial.begin(9600);
stepper.setspeed(30);
}

Void loop()
{

char buffer1[ 8];  \\  buffer for no of rotation
char buffer2[ 4];        \\ buffer for direction

if (serial.available())  
{
serial.readbyteUntil('\n',buffer1, 3); \\receives 3 byte for no of rotation
serial.readbyteUntil('\n',buffer2, 1); \\receives 1 byte for direction
int rotations=atoi(buffer1); //converts ASCII To Integer
int direction=atoi(buffer2); //converts ASCII To Integer
if(direction==1)
{
for(i=1;i<=rotations;i++)
{
stepper.step(200);
}
}

if(direction==2)
{
for(i=1;i<=rotations;i++)
{
stepper.step(-200);
}
}
}

Thanks mike. I will try out this code.

Hi!! Thank you everyone for the help. I am able to control the no of rotation and direction of the motor. :slight_smile:

Following is the code I wrote

#include <Stepper.h>
Stepper stepper(200, 8, 9, 10, 11);
void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
  stepper.setSpeed(30);
  Serial.print(" \n enter no of rotations and No 1 for CW Rotation and 2 for ACW rotation " );
}

void loop()
{
char buffer1[ 8];  //  buffer for no of rotation
char buffer2[ 4];  // buffer for direction
//Serial.print(" \n enter no of rotations and direction " );
//delay(3000);
while(Serial.available() ==0){}

if (Serial.available()>3) 
{
Serial.readBytesUntil('\n',buffer1, 3); //receives 3 byte for no of rotation
Serial.readBytesUntil('\n',buffer2, 1); //receives 1 byte for direction
int rotations=atoi(buffer1); //converts ASCII To Integer
int directions=atoi(buffer2); //converts ASCII To Integer
Serial.print("\n ascii_rotations = " );
Serial.println(buffer1);
Serial.print("integer_rotations = ");
Serial.println(rotations);
Serial.print("ascii_directions = " );
Serial.println(buffer2);
Serial.print("integer_directions = ");
Serial.println(directions);

if(directions==1)
{
  for(int i=1;i<=rotations;i++)
{
stepper.step(200);
delay(1000);
}
}
if(directions==2)
{
  for(int i=1;i<=rotations;i++)
{
stepper.step(-200);
delay(1000);
}
}
}
}

One thing I couldn’t grab is the ASCII output of the variable I entered. Everytime I enter a value in keyboard, the equivalent ASCII value in outputs is strange.Following are some of the keyboard values and corresponding ASCII outputs.

value entered In keyboard: 005 (rotations) and 2 (direction)
Terminal output:
ascii_rotations: 005
integer_rotations:5
ascii_directions:2Y
integer_directions:2

value entered In keyboard: 009 (rotations) and 1 (direction)
Terminal output:
ascii_rotations: 009Y
integer_rotations:9
ascii_directions:1 Y009Y
integer_directions:1

value entered In keyboard: 110 (rotations) and 5 (direction)
Terminal output:
ascii_rotations: 110Y
integer_rotations:110
ascii_directions:5  Y110Y
integer_directions:5

In the above program when I used the command

while(Serial.available() <=3){}

instead of

while(Serial.available() ==0){}

My integer values of rotation was always a ‘7’ appended with whatever Number I entered in the keyboard. Eg: when I entered ‘010’ for rotation in keyboard my integer output for rotation is 107. Similarly ‘1107’ for ‘110’ and so on.

can someone help me understand what is happening here?