Interfacing of 28BYJ Stepper Driver with Arduino.
What is so special about steppers?
A stepper motor can move in accurate, fixed 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-defined 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 offers 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)
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
Step angle sequence 11.25 degrees per step / 32 steps per one revolution of the internal motor shaft
Manufacturer specifies 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 confirm their findings. These means that in the
recommended half-step mode we will have:64 steps per motor rotation x 63.684 gear ratio =
Gear ratio 4076 steps per full revolution (approximately).
Wiring to the
ULN2003
controller A (Blue), B (Pink), C (Yellow), D (Orange), E (Red, Mid- Point)
Weight 30g
Material Required:
Material Quantity
Arduino Uno 1
Stepper Driver 1
Jumper cables 6
Stepper Motor 1
Pinout Diagram:
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 specifies that the preferred method for driving this stepper is using the half-step method, where we first power coil 1 only, then coil 1 and 2 together, then coil 2 only and so on…With 4 coils, this means 8 different signals, like in the table below.
Circuit Diagram:
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 / off 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/off” jumper next to the “-” pin is on. If you power the Arduino from a different 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 efficiently and getting two of them running at the same time for a differential drive robot is a bit more difficult. 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 efficiently (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 first!
#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 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();
}
Tested Programming Code:
#define IN1 3
#define IN2 4
#define IN3 5
#define IN4 6
int Steps = 4096; //4096 or 768
int cstep = 0;
void setup()
{
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void loop()
{
for(int x=0;x<Steps;x++)
{
step1();
//delay(1);
delayMicroseconds(2500);
}
Serial.println("Boom!!");
delay(1000);
}
void step1()
{
//stepp
switch(cstep)
{
case 0:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
case 1:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
break;
case 2:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 3:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 4:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 5:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 6:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 7:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
default:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
}
cstep=cstep+1;
if(cstep==8)
{cstep=0;}
}
Precautions:
1. Double check the connections before powering on the circuit.
2. Don’t use loose jumper cables.
3. Check whether proper board is selected from Arduino IDE.
4. Ensure proper placement of sensor for correct working.
5. Don’t lose hope if Motor does not runs properly for the first time, try again.
Conclusion:
You can successfully interface Stepper motor with the driver and use it to control different type of moving applications.