diff --git a/libraries/Stepper/examples/stepper_oneRevolution_28BYJ48_ULN2003/stepper_oneRevolution_28BYJ48_ULN2003.ino b/libraries/Stepper/examples/stepper_oneRevolution_28BYJ48_ULN2003/stepper_oneRevolution_28BYJ48_ULN2003.ino new file mode 100644 index 00000000000..7c2d6ba4eca --- /dev/null +++ b/libraries/Stepper/examples/stepper_oneRevolution_28BYJ48_ULN2003/stepper_oneRevolution_28BYJ48_ULN2003.ino @@ -0,0 +1,71 @@ +/* + Stepper Motor Control - one revolution + + This program drives a unipolar or bipolar stepper motor. + The motor is attached to digital pins 8 - 11 of the Arduino. + + The motor should revolve one revolution in one direction, then + one revolution in the other direction. + + + Created 11 Mar. 2007 + Modified 30 Nov. 2009 + by Tom Igoe + + Example adapted for the combination of Motor 28BYJ-48 and driver ULN2003 + see http://www.amazon.de/gp/product/B00ATA5MFE?keywords=ULN2003%2028BYJ48 + Modified 05 Dec. 2015 + by Stanislav Kniazev + + */ + +#include +// Motor 28BYJ-48 has 4096 steps per one revolution +const int stepsPerRevolution = 4096; // change this to fit the number of steps per revolution for your motor + +/* Custom phase matrix for driver ULN2003. + * The sequence of control signals for 8 phases, 4 control wires is as follows: + * Step C0 C1 C2 C3 + * 1 0 0 0 1 + * 2 0 0 1 1 + * 3 0 0 1 0 + * 4 0 1 1 0 + * 5 0 1 0 0 + * 6 1 1 0 0 + * 7 1 0 0 0 + * 8 1 0 0 1 + */ +const unsigned char phasesMatrix[8] PROGMEM = { + 0b0001, + 0b0011, + 0b0010, + 0b0110, + 0b0100, + 0b1100, + 0b1000, + 0b1001 + }; + +//initialize the stepper library on pins 8 through 11, phasesMatrix, pin_count, phase_count: +Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11, (unsigned char*)phasesMatrix, 8); + +void setup() { + // 17 is the maximum for counterclockwise revolution of motor 28BYJ-48 + // set the speed at 17 rpm: + myStepper.setSpeed(17); + // initialize the serial port: + Serial.begin(9600); +} + +void loop() { + // step one revolution in one direction: + Serial.println("clockwise"); + myStepper.step(stepsPerRevolution); + delay(500); + + // step one revolution in the other direction: + Serial.println("counterclockwise"); + myStepper.step(-stepsPerRevolution); + delay(500); +} + diff --git a/libraries/Stepper/src/Stepper.cpp b/libraries/Stepper/src/Stepper.cpp index 1f76295d05b..751624baa09 100644 --- a/libraries/Stepper/src/Stepper.cpp +++ b/libraries/Stepper/src/Stepper.cpp @@ -1,13 +1,19 @@ /* - * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.0 + * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.1 * - * 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 by Eugene Kozlenko - * Timer rollover fix by Eugene Kozlenko - * Five phase five wire (1.1.0) by Ryan Orendorff + * 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 by Eugene Kozlenko + * Timer rollover fix by Eugene Kozlen + * Five phase five wire (1.1.0) by Ryan Orendorff + * Generic driver support (see example + * stepper_oneRevolution_ULN2003), + * constructors harmonization by + * introducing the initMotor method, + * optimization of method stepMotor by + * introducing the phasesMatrix array (1.1.1) by Stanislav Kniazev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -82,91 +88,102 @@ * two-wire constructor. * Sets which wires should control the motor. */ -Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2) +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1) { - this->step_number = 0; // which step the motor is on - 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 others to 0: - this->motor_pin_3 = 0; - this->motor_pin_4 = 0; - this->motor_pin_5 = 0; - - // pin_count is used by the stepMotor() method: - this->pin_count = 2; + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + 0, 0, 0, 2, (unsigned char*)phasesMatrix2, 4); } - /* * 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) +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3) { - this->step_number = 0; // which step the motor is on - 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); - - // When there are 4 pins, set the others to 0: - this->motor_pin_5 = 0; - - // pin_count is used by the stepMotor() method: - this->pin_count = 4; + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + motor_pin_2, motor_pin_3, + 0, 4, (unsigned char*)phasesMatrix4, 4); } /* * constructor for five phase motor with five wires * 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, - int motor_pin_5) +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, 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->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 + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + motor_pin_2, motor_pin_3, + motor_pin_4, 5, (unsigned char*)phasesMatrix5, 10); +} - // 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; - this->motor_pin_5 = motor_pin_5; +/* + * universal constructor for motors with only one wire + * Sets which wires should control the motor, pointer to the phases matrix, number of pins and phases. + */ +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, + unsigned char *phasesMatrix, int phase_count) +{ + initMotor(number_of_steps, motor_pin_0, 0, + 0, 0, + 0, 1, + phasesMatrix,phase_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); - pinMode(this->motor_pin_5, OUTPUT); +/* + * universal constructor for motors with two wires + * Sets which wires should control the motor, pointer to the phases matrix, number of pins and phases. + */ +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + unsigned char *phasesMatrix, int phase_count) +{ + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + 0, 0, + 0, 2, + phasesMatrix,phase_count); +} - // pin_count is used by the stepMotor() method: - this->pin_count = 5; +/* + * universal constructor for motors with three wires + * Sets which wires should control the motor, pointer to the phases matrix, number of pins and phases. + */ +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, unsigned char *phasesMatrix, int phase_count) +{ + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + motor_pin_2, 0, + 0, 3, + phasesMatrix,phase_count); +} + +/* + * universal constructor for motors with four wires + * Sets which wires should control the motor, pointer to the phases matrix, number of pins and phases. + */ +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3, + unsigned char *phasesMatrix, int phase_count) +{ + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + motor_pin_2, motor_pin_3, + 0, 4, + phasesMatrix,phase_count); +} + +/* + * universal constructor for motors with five wires + * Sets which wires should control the motor, pointer to the phases matrix, number of pins and phases. + */ +Stepper::Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3, int motor_pin_4, + unsigned char *phasesMatrix, int phase_count) +{ + initMotor(number_of_steps, motor_pin_0, motor_pin_1, + motor_pin_2, motor_pin_3, + motor_pin_4, 5, + phasesMatrix,phase_count); } /* @@ -185,11 +202,6 @@ 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) { @@ -201,10 +213,10 @@ void Stepper::step(int steps_to_move) this->last_step_time = now; // increment or decrement the step number, // depending on direction: - if (this->direction == 1) + if (steps_to_move >= 0) { this->step_number++; - if (this->step_number == this->number_of_steps) { + if (this->step_number >= this->number_of_steps) { this->step_number = 0; } } @@ -215,13 +227,10 @@ void Stepper::step(int steps_to_move) } this->step_number--; } + // step the motor to step number 0, 1, ..., {3 or 9} + stepMotor(this->step_number % phase_count); // decrement the steps left: steps_left--; - // step the motor to step number 0, 1, ..., {3 or 10} - if (this->pin_count == 5) - stepMotor(this->step_number % 10); - else - stepMotor(this->step_number % 4); } } } @@ -229,130 +238,39 @@ void Stepper::step(int steps_to_move) /* * Moves the motor forward or backwards. */ -void Stepper::stepMotor(int thisStep) +void Stepper::stepMotor(unsigned char thisPhase) { - 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; - } + unsigned char phase = pgm_read_byte_near(phasesMatrix + thisPhase); + unsigned char running_one = 1; + for (char i = pin_count - 1; i >= 0; i--, running_one <<= 1){ + digitalWrite(motor_pin[i], (phase & running_one)); } +} - if (this->pin_count == 5) { - switch (thisStep) { - case 0: // 01101 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - digitalWrite(motor_pin_5, HIGH); - break; - case 1: // 01001 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, LOW); - digitalWrite(motor_pin_5, HIGH); - break; - case 2: // 01011 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, HIGH); - digitalWrite(motor_pin_5, HIGH); - break; - case 3: // 01010 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, HIGH); - digitalWrite(motor_pin_5, LOW); - break; - case 4: // 11010 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, HIGH); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, HIGH); - digitalWrite(motor_pin_5, LOW); - break; - case 5: // 10010 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, LOW); - digitalWrite(motor_pin_4, HIGH); - digitalWrite(motor_pin_5, LOW); - break; - case 6: // 10110 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, HIGH); - digitalWrite(motor_pin_5, LOW); - break; - case 7: // 10100 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - digitalWrite(motor_pin_5, LOW); - break; - case 8: // 10101 - digitalWrite(motor_pin_1, HIGH); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - digitalWrite(motor_pin_5, HIGH); - break; - case 9: // 00101 - digitalWrite(motor_pin_1, LOW); - digitalWrite(motor_pin_2, LOW); - digitalWrite(motor_pin_3, HIGH); - digitalWrite(motor_pin_4, LOW); - digitalWrite(motor_pin_5, HIGH); - break; - } +/* + * Initialize the motor + */ +void Stepper::initMotor(unsigned number_of_steps, unsigned char motor_pin_0, unsigned char motor_pin_1, + unsigned char motor_pin_2, unsigned char motor_pin_3, + unsigned char motor_pin_4, unsigned char pin_count, + unsigned char *phasesMatrix,unsigned char phase_count) +{ + this->step_number = 0; // which step the motor is on + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // pin_count is used by the stepMotor() method: + this->pin_count = pin_count; + // phase_count is used by the step() method: + this->phase_count = phase_count; + // phasesMatrix is used by the stepMotor() method: + this->phasesMatrix = phasesMatrix; + this->motor_pin[0] = motor_pin_0; + 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; + for (unsigned char i = 0; i < this->pin_count; i++){ + pinMode(this->motor_pin[i], OUTPUT); // setup the pins on the microcontroller } } diff --git a/libraries/Stepper/src/Stepper.h b/libraries/Stepper/src/Stepper.h index 2e68979a1b1..6f62a52f001 100644 --- a/libraries/Stepper/src/Stepper.h +++ b/libraries/Stepper/src/Stepper.h @@ -1,13 +1,19 @@ /* - * Stepper.h - Stepper library for Wiring/Arduino - Version 1.1.0 - * - * 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 by Eugene Kozlenko - * Timer rollover fix by Eugene Kozlenko - * Five phase five wire (1.1.0) by Ryan Orendorff + * Stepper.h - Stepper library for Wiring/Arduino - Version 1.1.1 + * + * 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 by Eugene Kozlenko + * Timer rollover fix by Eugene Kozlen + * Five phase five wire (1.1.0) by Ryan Orendorff + * Generic driver support (see example + * stepper_oneRevolution_ULN2003), + * constructors harmonization by + * introducing the initMotor method, + * optimization of method stepMotor by + * introducing the phasesMatrix array (1.1.1) by Stanislav Kniazev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -79,16 +85,60 @@ #ifndef Stepper_h #define Stepper_h +#include + + //Default phases matrix for 2 control wires is as follows + const unsigned char phasesMatrix2[4] PROGMEM = { + 0b01, + 0b11, + 0b10, + 0b00 + }; + + //Default phases matrix for 4 control wires is as follows + const unsigned char phasesMatrix4[4] PROGMEM = { + 0b1010, + 0b0110, + 0b0101, + 0b1001 + }; + + //Default phases matrix for 5 control wires is as follows + const unsigned char phasesMatrix5[10] PROGMEM = { + 0b01101, + 0b01001, + 0b01011, + 0b01010, + 0b11010, + 0b10010, + 0b10110, + 0b10100, + 0b10101, + 0b00101 + }; + // library interface description class Stepper { public: // constructors: - Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2); - Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, - int motor_pin_3, int motor_pin_4); - Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, - int motor_pin_3, int motor_pin_4, - int motor_pin_5); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3, + int motor_pin_4); + Stepper(unsigned number_of_steps, int motor_pin_0, + unsigned char *phasesMatrix, int phase_count); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + unsigned char *phasesMatrix, int phase_count); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, unsigned char *phasesMatrix, int phase_count); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3, + unsigned char *phasesMatrix, int phase_count); + Stepper(unsigned number_of_steps, int motor_pin_0, int motor_pin_1, + int motor_pin_2, int motor_pin_3, int motor_pin_4, + unsigned char *phasesMatrix, int phase_count); // speed setter method: void setSpeed(long whatSpeed); @@ -99,21 +149,21 @@ class Stepper { int version(void); private: - void stepMotor(int this_step); + void stepMotor(unsigned char thisPhase); + void initMotor(unsigned number_of_steps, unsigned char motor_pin_0, unsigned char motor_pin_1, + unsigned char motor_pin_2, unsigned char motor_pin_3, + unsigned char motor_pin_4, unsigned char pin_count, + unsigned char *phasesMatrix,unsigned char phase_count); - int direction; // Direction of rotation unsigned long step_delay; // delay between steps, in ms, based on speed - int number_of_steps; // total number of steps this motor can take - int pin_count; // how many pins are in use. - int step_number; // which step the motor is on + unsigned number_of_steps; // total number of steps this motor can take + unsigned char pin_count; // how many pins are in use. + unsigned char phase_count; // how many phases are in use. + unsigned char *phasesMatrix; // pointer to the phases Matrix + unsigned step_number; // which step the motor is on // motor pin numbers: - int motor_pin_1; - int motor_pin_2; - int motor_pin_3; - int motor_pin_4; - int motor_pin_5; // Only 5 phase motor - + unsigned char motor_pin[5]; // Maximum 5 control signals unsigned long last_step_time; // time stamp in us of when the last step was taken };