From 3c38d1729b98a79f9474d3a5098cfe768e6c0642 Mon Sep 17 00:00:00 2001 From: ekozlenko Date: Tue, 26 Nov 2013 09:08:40 -0500 Subject: [PATCH 1/3] Update stepper library: High-speed stepping mod and timer rollover fix When using the stepper library with a 1.8 degrees per step motor, and at high angular speeds, the current Stepper library leads to really loud and jittery rotation. This is due to the fact that the timing is calculated in milliseconds, and the delay length between steps is only 2.5 milliseconds when trying to spin at 120 rpm. Since only integer math is performed, you end up actually bouncing between different step delays, and thus speeds, from step to step instead of giving the motor a constant input. Which causes the motor to freak out. Changing the library to calculate the step delays in micros() solves that problem for any speed you can reasonably demand from your stepper motor. The down side is that the micros() counter rolls over every hour or so, and any move you perform after that point will hang your code. Easy fix for that is to add an || micros() - this->last_step_time < 0 to the while loop if statement in Stepper.cpp. --- libraries/Stepper/stepper.cpp | 222 ++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 libraries/Stepper/stepper.cpp diff --git a/libraries/Stepper/stepper.cpp b/libraries/Stepper/stepper.cpp new file mode 100644 index 00000000000..e5c34d29501 --- /dev/null +++ b/libraries/Stepper/stepper.cpp @@ -0,0 +1,222 @@ +/* + 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 + High-speed stepping mod and timer rollover fix (0.5) by Eugene Kozlenko + + Drives a unipolar or bipolar stepper motor using 2 wires or 4 wires + + When wiring multiple stepper motors to a microcontroller, + you quickly run out of output pins, with each motor requiring 4 connections. + + By making use of the fact that at any time two of the four motor + coils are the inverse of the other two, the number of + control connections can be reduced from 4 to 2. + + A slightly modified circuit around a Darlington transistor array or an L293 H-bridge + connects to only 2 microcontroler pins, inverts the signals received, + and delivers the 4 (2 plus 2 inverted ones) output signals required + for driving a stepper motor. Similarly the Arduino motor shields 2 direction pins + may be used. + + The sequence of control signals for 4 control wires is as follows: + + Step C0 C1 C2 C3 + 1 1 0 1 0 + 2 0 1 1 0 + 3 0 1 0 1 + 4 1 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) +{ + 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 us of the last step taken + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // 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); + + // 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 + * Sets which wires should control the motor. + */ + +Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4) +{ + 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 us of the last step taken + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // 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; + + // 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 + +*/ +void Stepper::setSpeed(long whatSpeed) +{ + this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed; +} + +/* + Moves the motor steps_to_move steps. If the number is negative, + the motor moves in the reverse direction. + */ +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 (micros() - this->last_step_time >= this->step_delay || micros() - this->last_step_time < 0) { + // get the timeStamp of when you stepped: + this->last_step_time = micros(); + // 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: + stepMotor(this->step_number % 4); + } + } +} + +/* + * Moves the motor forward or backwards. + */ +void Stepper::stepMotor(int thisStep) +{ + if (this->pin_count == 2) { + 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; + } + } + if (this->pin_count == 4) { + switch (thisStep) { + case 0: // 1010 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + break; + case 1: // 0110 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + break; + case 2: //0101 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + break; + case 3: //1001 + digitalWrite(motor_pin_1, HIGH); + 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; +} From e2a53429521c011b220a9e8b8141d95e3ece4b03 Mon Sep 17 00:00:00 2001 From: ekozlenko Date: Mon, 2 Dec 2013 13:15:13 -0500 Subject: [PATCH 2/3] Fixed mixed sign math --- libraries/Stepper/Stepper.cpp | 220 ---------------------------------- 1 file changed, 220 deletions(-) delete mode 100644 libraries/Stepper/Stepper.cpp diff --git a/libraries/Stepper/Stepper.cpp b/libraries/Stepper/Stepper.cpp deleted file mode 100644 index 5d6b5e53664..00000000000 --- a/libraries/Stepper/Stepper.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - 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 - - Drives a unipolar or bipolar stepper motor using 2 wires or 4 wires - - When wiring multiple stepper motors to a microcontroller, - you quickly run out of output pins, with each motor requiring 4 connections. - - By making use of the fact that at any time two of the four motor - coils are the inverse of the other two, the number of - control connections can be reduced from 4 to 2. - - A slightly modified circuit around a Darlington transistor array or an L293 H-bridge - connects to only 2 microcontroler pins, inverts the signals received, - and delivers the 4 (2 plus 2 inverted ones) output signals required - for driving a stepper motor. - - The sequence of control signals for 4 control wires is as follows: - - Step C0 C1 C2 C3 - 1 1 0 1 0 - 2 0 1 1 0 - 3 0 1 0 1 - 4 1 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) -{ - 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 - - // 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); - - // 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 - * Sets which wires should control the motor. - */ - -Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, int motor_pin_3, int motor_pin_4) -{ - 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 - - // 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; - - // 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 - -*/ -void Stepper::setSpeed(long whatSpeed) -{ - this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed; -} - -/* - Moves the motor steps_to_move steps. If the number is negative, - the motor moves in the reverse direction. - */ -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: - stepMotor(this->step_number % 4); - } - } -} - -/* - * Moves the motor forward or backwards. - */ -void Stepper::stepMotor(int thisStep) -{ - if (this->pin_count == 2) { - 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; - } - } - if (this->pin_count == 4) { - switch (thisStep) { - case 0: // 1010 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - break; - case 1: // 0110 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - break; - case 2: //0101 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, HIGH); - break; - case 3: //1001 - digitalWrite(motor_pin_1, HIGH); - 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 4; -} From 5c087ef7efaf02943383922d1835c8f4738cd05e Mon Sep 17 00:00:00 2001 From: ekozlenko Date: Mon, 2 Dec 2013 13:18:06 -0500 Subject: [PATCH 3/3] Fixed unsigned var and version note --- libraries/Stepper/Stepper.h | 10 ++++++---- libraries/Stepper/stepper.cpp | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/Stepper/Stepper.h b/libraries/Stepper/Stepper.h index 4094aee9077..a52800a7fe8 100644 --- a/libraries/Stepper/Stepper.h +++ b/libraries/Stepper/Stepper.h @@ -1,10 +1,11 @@ /* - Stepper.h - - Stepper library for Wiring/Arduino - Version 0.4 + Stepper.h - - Stepper library for Wiring/Arduino - Version 0.5 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 + High-speed stepping mod and timer rollover fix (0.5) by Eugene Kozlenko Drives a unipolar or bipolar stepper motor using 2 wires or 4 wires @@ -18,7 +19,8 @@ A slightly modified circuit around a Darlington transistor array or an L293 H-bridge connects to only 2 microcontroler pins, inverts the signals received, and delivers the 4 (2 plus 2 inverted ones) output signals required - for driving a stepper motor. + for driving a stepper motor. Similarly the Arduino motor shields 2 direction pins + may be used. The sequence of control signals for 4 control wires is as follows: @@ -65,7 +67,7 @@ class Stepper { int direction; // Direction of rotation int speed; // Speed in RPMs - unsigned long step_delay; // delay between steps, in ms, based on speed + unsigned long step_delay; // delay between steps, in us, based on speed int number_of_steps; // total number of steps this motor can take int pin_count; // whether you're driving the motor with 2 or 4 pins int step_number; // which step the motor is on @@ -76,7 +78,7 @@ class Stepper { int motor_pin_3; int motor_pin_4; - long last_step_time; // time stamp in ms of when the last step was taken + unsigned long last_step_time; // time stamp in us of when the last step was taken }; #endif diff --git a/libraries/Stepper/stepper.cpp b/libraries/Stepper/stepper.cpp index e5c34d29501..e64cb1649a3 100644 --- a/libraries/Stepper/stepper.cpp +++ b/libraries/Stepper/stepper.cpp @@ -1,5 +1,5 @@ /* - Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.4 + Stepper.cpp - - Stepper library for Wiring/Arduino - Version 0.5 Original library (0.1) by Tom Igoe. Two-wire modifications (0.2) by Sebastian Gassner @@ -133,7 +133,7 @@ void Stepper::step(int steps_to_move) // decrement the number of steps, moving one step each time: while(steps_left > 0) { // move only if the appropriate delay has passed: - if (micros() - this->last_step_time >= this->step_delay || micros() - this->last_step_time < 0) { + if (micros() - this->last_step_time >= this->step_delay || micros() < this->last_step_time) { // get the timeStamp of when you stepped: this->last_step_time = micros(); // increment or decrement the step number,