Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

42 Bots

Hobby robotics and electronics with Arduino and Raspberry Pi

28BYJ-48 Stepper Motor with ULN2003 driver and


Arduino Uno
By Stan | March 1, 2014 53 Comments

First, lets see the little steppers in action! Our main character, StepperBot, is “instructed” to move in a square
path on my co븟�ee table, making 90 degree turns at the corners. Turning exactly at the right time and by the
right angle is critical avoid falling o븟� and crashing on the 쓊oor in an embarrassing pile of messy wires.

StepperBot: 28BYJ-48 Stepper Motors, UNL2003 driver and Arduino Uno

The robot has no sensors for positioning, orientation, or a way to detect the edges of the table. Movement is
controlled only by the number of pre-de읥�ned steps in each direction hard-coded in the sketch. The motors are
running at approximately 8 volts DC and 15 RPM in this example. One thing that you cannot tell from the video
is how quiet these little steppers run: StepperBot is very stealthy! Eventually, small errors add up over time
and the bot falls o븟� the table, but it typically runs for 10-15 minutes, before that: good enough for me!

What is so special about steppers


A stepper motor can move in accurate, 읥�xed angle increments known as steps. For practical purposes, a
stepper motor is a bit like a servo: you can tell it to move to a pre-de읥�ned position and can count on getting
fairly consistent results with multiple repetitions. Servos though, are usually limited to a 0-180 degree range,
while a stepper motor can rotate continuously, similar to a regular DC motor. The advantage of steppers over
DC motors is that you can achieve much higher precision and control over the movement. The downside of
using steppers is that they are a bit more complex to control than servos and DC motors.

The 28BYJ-48 Stepper Motor Datasheet

The 28BYJ-48 is a small, cheap, 5 volt geared stepping motors. These stepping motors are apparently widely
used to control things like automated blinds, A/C units and are mass produced. Due to the gear reduction
ratio of *approximately* 64:1 it o븟�ers
decent torque for its size at speeds of
about 15 rotations per minute (RPM). With
some software “trickery” to accelerate
gradually and a higher voltage power
source (I tested them with 12 volts DC) I
was able to get about 25+ RPM. These
little steppers can be purchased together
with a small breakout board for the
Arduino compatible ULN2003 stepper
motor driver for less than $5. Quite a
bargain, compared to the price of a geared
DC motor, a DC motor controller and a
wheel encoder! The low cost and small size
makes the 28BYJ-48 an ideal option for
small robotic applications, and an excellent
introduction to stepper motor control with
Arduino. Here are the detailed specs of
the 28BYJ-48 stepper motor.

Motor Type Unipolar stepper motor

Connection Type 5 Wire Connection (to the motor controller)

Voltage 5-12 Volts DC

Frequency 100 Hz

Step mode Half-step mode recommended (8 step control signal sequence)

Step angle Half-step mode: 8 step control signal sequence (recommended) 5.625 degrees per step /
64 steps per one revolution of the internal motor shaftFull Step mode: 4 step control
signal sequence 11.25 degrees per step / 32 steps per one revolution of the internal

motor shaft

Gear ratio Manufacturer speci읥�es 64:1. Some patient and diligent people on the Arduino forums have

disassembled the gear train of these little motors and determined that the exact gear ratio

is in fact 63.68395:1. My observations con읥�rm their 읥�ndings. These means that in the

recommended half-step mode we will have:64 steps per motor rotation x 63.684 gear ratio

= 4076 steps per full revolution (approximately).

Wiring to the A (Blue), B (Pink), C (Yellow), D (Orange), E (Red, Mid-Point)

ULN2003 controller

Weight 30g

The motor has 4 coils of wire that are powered in a sequence to make the magnetic motor shaft spin. When
using the full-step method, 2 of the 4 coils are powered at each step. The default stepper library that comes
pre-installed with the Arduino IDE uses this method. The 28BYH-48 datasheet speci읥�es that the preferred
method for driving this stepper is using the half-step method, where we 읥�rst power coil 1 only, then coil 1 and
2 together, then coil 2 only and so on…With 4 coils, this means 8 di븟�erent signals, like in the table below.

Wiring the ULN2003 stepper motor driver to Arduino Uno

The ULN2003 stepper motor driver board allows you to easily control the 28BYJ-48 stepper motor from a
microcontroller, like the Arduino Uno. One side of the board side has a 5 wire socket where the cable from the
stepper motor hooks up and 4 LEDs to indicate which coil is currently powered. The motor cable only goes in
one way, which always helps. On the side you have a motor on / o븟� jumper (keep it on to enable
power to the stepper). The two pins below the 4 resistors, is where you provide power to the
stepper. Note that powering the stepper from the 5 V rail of the Arduino is not recommended.
A separate 5-12 V 1 Amp power supply or battery pack should be used, as the motor may drain
more current than the microcontroller
can handle and could potentially
damage it. In the middle of the board we
have the ULN2003 chip. At the bottom are
the 4 control inputs that should be
connected to four Arduino digital pins.

Hooking it up to the Arduino

Connect the ULN2003 driver IN1, IN2, IN3 and IN4 to digital pin 3, 4, 5 and 6 respectively on the
Arduino Uno. Connect the positive lead from a decent 5-12V battery pack to the “+” pin of the
ULN2003 driver and the ground to the “-” pin. Make sure that the “on/o븟�” jumper next to the “-”
pin is on. If you power the Arduino from a di븟�erent battery pack, connect the grounds together.

Arduino stepper code and the AccelStepper library

The default stepper library that comes pre-installed with the Arduino IDE supports the full-step method only
and has limited features. It does not run the 28BYJ-48 motors very e‫ﺽ‬ciently and getting two of them running
at the same time for a di븟�erential drive robot is a bit more di‫ﺽ‬cult. I came across example sketch by 4tronix
that used the half-step method with no additional libraries. Their code worked well and I was able to modify it,
so that I can run two steppers at the same time. Still, I was only able to get my stepper motor spinning fairly
slow and it was getting quite warm, for some reason. Additionally, that sample code uses delays for the steps
and that will cause some issues when we start adding more complex functions in the loop and hook up various
sensors. Then I came across the AccelStepper library. It runs the 28BYJ-48 steppers very e‫ﺽ‬ciently
(they never go as hot as with the other options I tried) and also supports acceleration (which
allows the stepper to get to a higher speed). The library uses non blocking code for the steps
and has quite a few other nice features. After some messing around with the documentation
and the examples I got everything up and running. Below is the code that will slowly accelerate
the 28BYJ-48 in one direction, then decelerate to a stop and accelerate in the opposite
direction. Naturally, make sure you download and install the AccelStepper library 읥�rst!

#include <AccelStepper.h>
#define HALFSTEP 8
// Motor pin definitions
#define motorPin1 3 // IN1 on the ULN2003 driver 1
#define motorPin2 4 // IN2 on the ULN2003 driver 1
#define motorPin3 5 // IN3 on the ULN2003 driver 1
#define motorPin4 6 // IN4 on the ULN2003 driver 1

// Initialize with pin sequence IN1‐IN3‐IN2‐IN4 for using the AccelStepper with 28BYJ‐48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);

void setup() {
stepper1.setMaxSpeed(1000.0);
stepper1.setAcceleration(100.0);
stepper1.setSpeed(200);
stepper1.moveTo(20000);

}//‐‐(end setup )‐‐‐

void loop() {

//Change direction when the stepper reaches the target position


if (stepper1.distanceToGo() == 0) {
stepper1.moveTo(‐stepper1.currentPosition());
}
stepper1.run();
}

The code above will not push this motor to its limit. You can experiment with the acceleration and speed
settings to see what is the best you can squeeze out. Note that for nigher speeds, you will likely need a higher
voltage DC source. If you got your stepper running, here is the code that the StepperBot from the video above
is running. You will need to adjust the speed, as well as the “turnSteps” and “lineSteps” variables based on your
base and wheel sizes, if you want to have your bot moving in a square path.

#include <AccelStepper.h>
#define HALFSTEP 8

// motor pins
#define motorPin1 3 // IN1 on the ULN2003 driver 1
#define motorPin2 4 // IN2 on the ULN2003 driver 1
#define motorPin3 5 // IN3 on the ULN2003 driver 1
#define motorPin4 6 // IN4 on the ULN2003 driver 1

#define motorPin5 8 // IN1 on the ULN2003 driver 2


#define motorPin6 9 // IN2 on the ULN2003 driver 2
#define motorPin7 10 // IN3 on the ULN2003 driver 2
#define motorPin8 11 // IN4 on the ULN2003 driver 2

// Initialize with pin sequence IN1‐IN3‐IN2‐IN4 for using the AccelStepper with 28BYJ‐48
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
AccelStepper stepper2(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);

// variables
int turnSteps = 2100; // number of steps for a 90 degree turn
int lineSteps = ‐6600; //number of steps to drive straight
int stepperSpeed = 1000; //speed of the stepper (steps per second)
int steps1 = 0; // keep track of the step count for motor 1
int steps2 = 0; // keep track of the step count for motor 2

boolean turn1 = false; //keep track if we are turning or going straight next
boolean turn2 = false; //keep track if we are turning or going straight next

void setup() {
delay(3000); //sime time to put the robot down after swithing it on

stepper1.setMaxSpeed(2000.0);
stepper1.move(1); // I found this necessary
stepper1.setSpeed(stepperSpeed);

stepper2.setMaxSpeed(2000.0);
stepper2.move(‐1); // I found this necessary
stepper2.setSpeed(stepperSpeed);

}
void loop() {

if (steps1 == 0) {
int target = 0;
if (turn1 == true) {
target = turnSteps;
}

else {
target = lineSteps;
}

stepper1.move(target);
stepper1.setSpeed(stepperSpeed);
turn1 = !turn1;
}

if (steps2 == 0) {
int target = 0;
if (turn2 == true) {
target = turnSteps;
}

else {
target = ‐lineSteps;
}

stepper2.move(target);
stepper2.setSpeed(stepperSpeed);
turn2 = !turn2;
}

steps1 = stepper1.distanceToGo();
steps2 = stepper2.distanceToGo();

stepper1.runSpeedToPosition();
stepper2.runSpeedToPosition();
}

You might also like