Go Down

Topic: Stepper motor, doesn't turn counter clockwise, wrong steps number indication (Read 11 times) previous topic - next topic

davidtraynor

Hi

here is the stepper.cpp file to go with the last post, remember to copy between the scissor lines. save this as stepper.cpp in your library
----------------------- Start of stepper.cpp ---------------------------------->
/*
 Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.4

 Original library     (0.1) by Tom Igoe.
 Two-wire modifications   (0.2) by Sebastian Gassner
 Combination version   (0.3) by Tom Igoe and David Mellis
 Bug fix for four-wire   (0.4) by Tom Igoe, bug fix from Noah Shibley
 Add Half Step mode      (0.5) by D Traynor

 Drives a unipolar or bipolar stepper motor using  2 wires or 4 wires

 The sequence for full step of control signals for 4 control wires is as follows:
 # Modified from the original 1010, 0110, 0101, 1001 - since my motor would not reverse

 Step C0 C1 C2 C3
    1  0  0  1  1
    2  1  0  0  1
    3  1  1  0  0
    4  0  1  1  0

 The sequence for halfstep for 4 control wires is as follows:
 # Added this 8 step sequence for halfstep control (v0.5)

 Step C0 C1 C2 C3
    1  1  0  0  1
    2  1  0  0  0
    3  1  1  0  0
    4  0  1  0  0
    5  0  1  1  0
    6  0  0  1  0
    7  0  0  1  1
    8  0  0  0  1

 The sequence of controls signals for 2 control wires is as follows
 (columns C1 and C2 from above):

 Step C0 C1
    1  0  1
    2  1  1
    3  1  0
    4  0  0

 The circuits can be found at

http://www.arduino.cc/en/Tutorial/Stepper
*/


#include "Arduino.h"
#include "Stepper.h"

/*two-wire constructor.
* Sets which wires should control the motor.
*/
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int mod_count)
{
 this->step_number = 0;      // which step the motor is on
 this->speed = 0;        // the motor speed, in revolutions per minute
 this->direction = 0;      // motor direction
 this->last_step_time = 0;    // time stamp in ms of the last step taken
 this->number_of_steps = number_of_steps;    // total number of steps for this motor
 this->mod_count = 4;      // default number of steps in a sequence (v0.5)

 // Arduino pins for the motor control connection:
 this->motor_pin_1 = motor_pin_1;
 this->motor_pin_2 = motor_pin_2;

 // setup the pins on the microcontroller:
 pinMode(this->motor_pin_1, OUTPUT);
 pinMode(this->motor_pin_2, OUTPUT);

 // modulo count is the No of control steps in a motor STEP sequence (v0.5)
 this->mod_count = mod_count;

 // When there are only 2 pins, set the other two to 0:
 this->motor_pin_3 = 0;
 this->motor_pin_4 = 0;

 // pin_count is used by the stepMotor() method:
 this->pin_count = 2;
}

/*   constructor for four-pin version at FULL step
*   Sets which wires should control the motor.
*   New parameter 'mod_count' to cater for halfstep sequence (v0.5)
*/

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4, int mod_count)
{
 this->step_number = 0;      // which step the motor is on
 this->speed = 0;        // the motor speed, in revolutions per minute
 this->direction = 0;      // motor direction
 this->last_step_time = 0;    // time stamp in ms of the last step taken
 this->number_of_steps = number_of_steps;    // total number of steps for this motor
 this->mod_count = 4;      // default number of steps  FULL STEP = 4 whilst HALF STEP = 8 (v0.5)

 // Arduino pins for the motor control connection:
 this->motor_pin_1 = motor_pin_1;
 this->motor_pin_2 = motor_pin_2;
 this->motor_pin_3 = motor_pin_3;
 this->motor_pin_4 = motor_pin_4;

 // modulo count is the No of control steps in a motor STEP
 this->mod_count = mod_count;

 // setup the pins on the microcontroller:
 pinMode(this->motor_pin_1, OUTPUT);
 pinMode(this->motor_pin_2, OUTPUT);
 pinMode(this->motor_pin_3, OUTPUT);
 pinMode(this->motor_pin_4, OUTPUT);

 // pin_count is used by the stepMotor() method:
 this->pin_count = 4;
}

/*
 Sets the speed in revs per minute
 Added a safeguard minimum delay of 2mS, may vary for other motors
*/
void Stepper::setSpeed(long whatSpeed)
{
 this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
 if (this->step_delay < 2) {
   this->step_delay = 2;    // if the delay is too small then the motor will stall (v0.5)
 }
}

/*
 Moves the motor steps_to_move steps.  If the number is negative,
  the motor moves in the reverse direction.
  Had to change the step sequence to get my motor [28BYJ-48] to reverse in full step (v0.5)
*/
void Stepper::step(int steps_to_move)
{
 int steps_left = abs(steps_to_move);  // how many steps to take

 // determine direction based on whether steps_to_mode is + or -:
 if (steps_to_move > 0) {this->direction = 1;}
 if (steps_to_move < 0) {this->direction = 0;}


 // decrement the number of steps, moving one step each time:
 while(steps_left > 0) {
 // move only if the appropriate delay has passed:
 if (millis() - this->last_step_time >= this->step_delay) {
     // get the timeStamp of when you stepped:
     this->last_step_time = millis();
     // increment or decrement the step number,
     // depending on direction:
     if (this->direction == 1) {
       this->step_number++;
       if (this->step_number == this->number_of_steps) {
         this->step_number = 0;
       }
     }
     else {
       if (this->step_number == 0) {
         this->step_number = this->number_of_steps;
       }
       this->step_number--;
     }
     // decrement the steps left:
     steps_left--;
     // step the motor to step number 0, 1, 2, or 3:
     // or 4,5,6,7 for HALFSTEP mode (v0.5)
     stepMotor(this->step_number % this->mod_count);
   }
 }
}

/*
* Moves the motor forward or backwards.
*/
void Stepper::stepMotor(int thisStep)
{
 if (this->pin_count == 2) {       // 3 parts of the IF are mutually exclusive -> hence the addition of the ELSE
   switch (thisStep) {
     case 0: /* 01 */
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, HIGH);
     break;
     case 1: /* 11 */
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, HIGH);
     break;
     case 2: /* 10 */
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, LOW);
     break;
     case 3: /* 00 */
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, LOW);
     break;
   }
 } else if (this->pin_count == 4 && this->mod_count == 4) {    // (v0.5) allows distinction between full and half step
   switch (thisStep) {
     case 0:    // 0011
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, HIGH);
     digitalWrite(motor_pin_4, HIGH);
     break;
     case 1:    // 1001
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, HIGH);
     break;
     case 2:    // 1100
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, HIGH);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 3:    // 0110
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, HIGH);
     digitalWrite(motor_pin_3, HIGH);
     digitalWrite(motor_pin_4, LOW);
     break;
   }
 } else if (this->pin_count == 4 && this->mod_count == 8) {    //(v0.5)
   switch (thisStep) {
     case 0:    //1001
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, HIGH);
     break;
     case 1:    //1000
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 2:    //1100
     digitalWrite(motor_pin_1, HIGH);
     digitalWrite(motor_pin_2, HIGH);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 3:    //0100
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, HIGH);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 4:    //0110
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, HIGH);
     digitalWrite(motor_pin_3, HIGH);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 5:    //0010
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, HIGH);
     digitalWrite(motor_pin_4, LOW);
     break;
     case 6:    //0011
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, HIGH);
     digitalWrite(motor_pin_4, HIGH);
     break;
     case 7:    //0001
     digitalWrite(motor_pin_1, LOW);
     digitalWrite(motor_pin_2, LOW);
     digitalWrite(motor_pin_3, LOW);
     digitalWrite(motor_pin_4, HIGH);
     break;
   }
 }
}

/*
 version() returns the version of the library:
*/
int Stepper::version(void)
{
 return 5;
}
<------------------------ End of stepper.cpp ----------------------------------

Zaplady

Hi
From your picture, your stepper motor looks suspiciously like the 28BYJ-48 unipolar stepper motor I bought on ebay (as a package with a ULN2003). I had a similar problem with it not turning backwards with the example code for stepper_oneRevolution.

It may be that your problem (like mine) was because the wires on the motor were not in the expected order. I had to order my stepper pins as 8, 10, 9, 11 rather than 8,9,10,11 when creating the stepper instance. This enabled the motor to go backwards and forwards as expected. You could try other permutations to see which work for your stepper. (connect 8,9,10,11 to in1, in2, in3, in4 on the ULN)

For the speed/revolutions per minute issue I found combinations with speed * revolutions = about 2^13 (i.e.8192) would work as this is used to calculate the delay needed for the stepper to move. The most accurate one for my stepper was speed = 4 (used for setSpeed) and stepsPerRevolution = 2048 as my stepper moved at about 4 revs per minute.
:)

winkleink

The suggestions froin Zaplady and davidtraynor work for me with my cheap ebayed stepper motors.
Like Zaplady mine came with a ULN2003 driver board with LEDs.
These things can now get purchased for less than £2.00.
So, assuming complete accuracy and the funky cross over wiring isn't a problem then they look like a good tinkerer option.

As a side note. When I wired mine up first time and used the same sketch it went clockwise and anti-clockwise with no modifications. I then disconnected the driver and motor to test my second one and it would only go clockwise. Re-attached the original and it would only go clockwise as well.
So, strange behaviour but then for £2.00 each I expect some slight fun in getting them working.

Thank you Zaplady and david traynor.

Albert.

Go Up