You are on page 1of 9

An Arduino Library to Control the 28BYJ-48 Stepper

Motor
orouit, 20 Dec 2013 CPOL

4.48 ﴾14 votes﴿

This article shows how to create a simple C++ class library to properly control a 28BYJ‐48 stepper motor using its control board.

StepperMotor library ‐ 2.3 KB


Demo reverse on interruption ‐ 601 B
Demo stop or start on interruption ‐ 885 B

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.

Some specs can be found there: http://www.old‐computers.com/museum/computer.asp?c=504&st=1

The Arduino is a modern version of this Kit D5 and includes a lot of interesting on‐board features:

12 digital configurable I/O Pin, 6 of them configurable as PWM output


6 10 bits ADC input I/O that can be configured as digital output as well
2 in‐board timers
32K of NVRAM
1K of SRAM
2K of EEPROM
RISC instruction set

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.

Controlling a Stepper Motor


In this article I'll show you how to write a simple class to control a stepper motor, the one provided with the starter kit I bought, its
reference is 28BYJ‐48. The Arduino comes with an installed Stepper class in its libraries but this class doesn't work properly with
this motor. There are two problems with this class when it drives the 28BYJ‐48:
It takes 2048 steps to do a 360deg revolution while the specs of the 28BYJ‐48 states that it would take 4096 steps
When sending a negative value to the step() method the motor continues to turn in the same direction!

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.

The sequence of quartets to send to the 28BYJ‐48 is the following:

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.

void StepperMotor::stop(bool stop)


{
if (stop)
{
interrupt = true;
}
for (byte idx = 0; idx < PHASE_NUMBER; ++idx)
{
digitalWrite(motorPins[idx], LOW);
}
}

void StepperMotor::moveOneStep(byte seqIdx)


{
for (byte idx = 0; idx < PHASE_NUMBER; ++idx)
{
digitalWrite(motorPins[idx], stepSequence[seqIdx][idx]);
}

delay(period);
}

bool StepperMotor::moveOneStepForward()
{
if (!interrupt)
{
stepIdx = incrementStep(stepIdx);
moveOneStep(stepIdx);
}

return interrupt;
}

bool StepperMotor::moveStepsForward(int steps)


{
for(int n = 0; n < steps; n++)
{
if (moveOneStepForward())
{
break;
}
}

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.

Demo application: Reversing the rotation every time a button


is pressed
The first demo application is using a button to start the rotation of the motor for a given number of steps, then a second click on
the button starts the motor in the opposite direction and so on.

#include <StepperMotor.h>

// 4 pins of the stepper motor board


#define _PIN1 19
#define _PIN2 18
#define _PIN3 17
#define _PIN4 16

// Interruption on PIN2, push‐button connected to pull‐up


#define ITR_PIN 2
#define ITR_NB 0

volatile boolean forward = false;


volatile boolean start = false;
volatile boolean first = true;

StepperMotor stepper(_PIN1, _PIN2, _PIN3, _PIN4);

/**
* 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.

Demo application: Stopping or starting the motor on a button


pressed interruption
The second example is demonstrating the ability to stop the motor while the method move is running. Every time the button is
pressed it stops or starts the motor depending on its current state. The interruption routine is suffering some time of the bouncing
of the button which causes one press of the button to generate several falling edges that are caught by the interruption line of the
chip.

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 DELAY 2000

#define _PIN1 19
#define _PIN2 18
#define _PIN3 17
#define _PIN4 16

#define ITR_PIN 2
#define ITR_NB 0

volatile bool first = true;


volatile bool moveInterrupted = false;

StepperMotor stepper(_PIN1, _PIN2, _PIN3, _PIN4);

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);
}

Conclusion and Point of Interest


Those little experiments with the Arduino took me back 25 years ago a bit like a time machine! There is plenty of code and
electronic circuits out there that use the Arduino boards, and have barely scratched the surface of this amazing little circuit. I have
always preferred to use a computer to interact with the external world, unfortunately my job has been more on the software side
although I have never forgotten what I originally studied, CPU boards connected to electronic components. I hope this simple article
will plant the seed of learning more on how to interface a computer with the real world!

License
This article, along with any associated source code and files, is licensed under The Code Project Open License ﴾CPOL﴿

Share

About the Author


orouit
Architect Connect In Private
Singapore

Software Architect, COM, .NET and Smartcard based security specialist.

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.

You may also be interested in...


The Hybrid Cloud Watering System in Python

Windows 8 Directly Driving Stepper Motor Smart Stove Top in Python

Controlling Floppy Drive Stepper Motor via How to Build a Heart Rate Monitor Using Zephyr
Parallel Port on the Arduino 101

Comments and Discussions


7 messages have been posted for this article Visit https://www.codeproject.com/Articles/699986/An‐Arduino‐Library‐to‐
Control‐the‐BYJ‐Stepper to post and view comments on this article, or click here to get a print view with messages.

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

You might also like