An Arduino Library To Control The 28BYJ-48 Stepper Motor - CodeProject
An Arduino Library To Control The 28BYJ-48 Stepper Motor - CodeProject
Motor
orouit, 20 Dec 2013 CPOL
This article shows how to create a simple C++ class library to properly control a 28BYJ‐48 stepper motor using its control board.
Introduction
I have recently discovered the Arduino board system. Although it has been out for quite some time I didn't know about this very
interesting system. The Raspberry Pi appears to be much more popular, but the Arduino really deserves to be known.
Its specification are way less impressive than the Raspberry PI, but its purpose is totally different. Those who studied electronics like
I did more than 25 years ago should find it very familiar and extremely interesting. The Arduino system is a micro‐controller
prototyping board that can be extended with the only limit of your imagination.
For $38 you can buy online a starter kit that contains many interesting components and solder‐less prototyping boards to build
many experiments. When I was a student I learned to program a Motorola CPU with I/O circuits on board called Motorola Kit D5.
This CPU board the size of a modern laptop was powered by a 6802 with few Kbytes of RAM and primitive operating system that
would let you enter assembly instruction in hexadecimal with small 25 keys keyboard using a 6 digits LED display.
The Arduino is a modern version of this Kit D5 and includes a lot of interesting on‐board features:
Of course it doesn't look that impressive if you compare it with the Raspberry PI but the purpose of such a board is not the same as
PI. The main purpose of that board is to interface with the outside world using the I/O pins.
The board can be programmed with a simple IDE connected via a USB port to a PC. Once the program installed in the board
memory it runs as an infinite loop. Libraries can be written in C++ and used to build more complex applications.
It took me quite some time to understand what was wrong and find the correct specs for the 28BYJ‐48 and its control board, then I
could understand why it was not working properly. You can find the correct specs there: Geetec Stepper Motor
The trick is the sequence that has to be followed when writing the input commands to the pins of the board. The Stepper class of
the Arduino library follows a sequence of 4 values of 4 bits but the 28BYJ‐48 requires a sequence of 8 values of 4 bits. One step of
the motor correspond to 1 value of the sequence. Those 8 values must be repeated in this order to turn the motor in one direction
and in the reverse order to turn the motor in the other direction.
This is what the code of the StepperMotor class does. This class is intended to work with this motor, it must be modified to
work with a different motor that would have a different control sequence.
In 1 In 2 In 3 In 4
0 0 0 1
0 0 1 1
0 0 1 0
0 1 1 0
0 1 0 0
1 1 0 0
1 0 0 0
1 0 0 1
This sequence will have the motor turn in counter clockwise direction, if you run this sequence in reverse order the motor will turn in
clockwise direction.
Another parameter is the speed of rotation. It is not clear from the specs what the capability of the motor is and its board, but after
a few experiments I found that operated fine with a 1 ms period. This means that you can change the state of the input pins every
ms. Above that frequency the board won't respond properly and the motor won't move.
class StepperMotor
{
public:
/**
* Constructor assigning the motor control PIN
*/
StepperMotor(byte motorPin1, byte motorPin2, byte motorPin3, byte motorPin4);
/**
* Sets the period to send the command quartet
*
* @param period Period in ms between to control quartets
*/
void setPeriod(int period);
/**
* Moves the motor of a given number of steps.
* Positive in a direction, Negative in the opposite
*
* @param numberOfSteps Number of steps to move
*/
void move(int numberOfSteps);
/**
* Stops the motor, setting all bits to LOW and raising the
* interrupt flag when interrupt is set to true
*
* @param interrupt If true it will stop the current sequence. When set to true
* this method is meant to be called from an interruption serving
* routine (ISR). When false it doesn't raise the interrupt flag, just
* set all the PIN to LOW. If not called from an interrupt routine, it
* prevents the motor from running.
*/
void stop(bool interrupt = false);
/**
* Reset the interrupt flag to false so the motor
* can be moved again
*/
void reset();
}
This simple class provides two main methods setPeriod and move. The method setPeriod is used to set the time in
milliseconds between two pulses sent to the motor to make in move in one or the other direction. The method move is used to
move the motor of a given number of steps in a direction given by the sign of the parameter.
The methods stop and reset can be used to stop and restart the motor from an interruption serving routine. The stop method
has a parameter to enable its use from a ISR, when true the method will stop the motor asynchronously using an internal flag.
The code of the StepperMotor is an Arduino library and need to be installed as .zip file from the Arduino IDE.
The following is an extract of the code of the class StepperMotor that shows how it works.
delay(period);
}
bool StepperMotor::moveOneStepForward()
{
if (!interrupt)
{
stepIdx = incrementStep(stepIdx);
moveOneStep(stepIdx);
}
return interrupt;
}
return interrupt;
}
The behavior of the stop method is very simple, if called while the method moveStepsForward is running it interrupts it as
moveOneStepForward returns true and breaks the loop, stopping the motor movement.
In the following examples the connections are the following: pins 1, 2, 3, 4 are connected to the pins 19, 18, 17 and 16 of the
Arduino board. The button is connected to the pin 2 of the Arduino which is set to INPUT_PULLUP so there is no need for a
resistor.
#include <StepperMotor.h>
/**
* This method is called on the interruption raised on the falling front of the PIN2
* The start flag is used to avoid rebound front. Interruptions are disabled inside the
* interrupt vector method.
* start is reset once it has been processed in the main loop()
*/
void buttonPressed()
{
if (!first)
{
if (!start)
{
forward = !forward;
start = true;
}
}
else
{
first = false;
}
}
void setup()
{
cli();
stepper.setPeriod(5);
pinMode(ITR_PIN, INPUT_PULLUP);
attachInterrupt(0, buttonPressed, FALL);
sei();
}
void loop()
{
if (start)
{
if (forward)
{
stepper.move(2048);
stepper.stop();
}
else
{
stepper.move(‐2048);
stepper.stop();
}
start = false;
}
}
The ISR method is called when the button is pressed on the falling edge of the pulse. However it appears that when started the
program always detects an interruption even if the button is not pressed. In order to avoid processing this interruption the flag
first is used to discard this interruption. There is another issue with catching interruptions on a button pressed and it's the
bouncing of the contact itself. In this simple example the flag start is used to avoid any bouncing pulse from the button.
I couldn't find a way to control that by software but a simple capacitor and some resistor would do the trick to avoid them. Because
of that the current code may some times have an erratic behavior when the button is pressed.
#include <StepperMotor.h>
#define _PIN1 19
#define _PIN2 18
#define _PIN3 17
#define _PIN4 16
#define ITR_PIN 2
#define ITR_NB 0
void buttonPressed()
{
static volatile boolean toggle = false;
if (!first)
{
if (toggle)
{
stepper.reset();
}
else
{
stepper.stop(true);
}
toggle = !toggle;
}
else
{
first = false;
}
}
void setup()
{
cli();
stepper.setPeriod(10);
pinMode(ITR_PIN, INPUT_PULLUP);
attachInterrupt(0, buttonPressed, FALLING);
sei();
}
void loop()
{
moveInterrupted = stepper.move(2048);
}
License
This article, along with any associated source code and files, is licensed under The Code Project Open License ﴾CPOL﴿
Share
I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I
preferred digital to analog.
I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.
For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when
things don't go right!
After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small
computers!
I've been back into business to design the licensing system for the enterprise solution for Consistel using a .NET smart card ﴾yes
they can run .NET CLR!﴿
I'm currently designing a micro‐payment solution using the NXP DESFire EV1 with the ACSO6 SAM of ACS. I can then add a full
proficient expertise on those systems and NFC payments.
This technology being under strict NDA by NXP I cannot publish any related article about it, however I can provide professional
consulting for it.
You can contact me for professional matter by using the forum or via my LinkedIn profile.
Controlling Floppy Drive Stepper Motor via How to Build a Heart Rate Monitor Using Zephyr
Parallel Port on the Arduino 101
Permalink | Advertise | Privacy | Terms of Use | Mobile Article Copyright 2013 by orouit
Select Language ▼
Web01 | 2.8.170510.2 | Last Updated 20 Dec 2013 Everything else Copyright © CodeProject, 1999‐2017