Lesson 1.9: Stepper motor with a remote
This lesson brings two parts together: the infrared receiver from lesson 1.7 and a stepper motor. Press a key on the remote and the motor makes exactly one turn one way or the other.
Parts
- 1×Arduino Uno
- 1×Breadboard
- 1×Power supply module
- 1×28BYJ-48 stepper motor
- 1×ULN2003 driver
- 1×Infrared receiver and remote
- Jumper wires
Libraries
- Stepper — bundled with the IDE
- IRremote
How it works
A stepper motor has several coils around the rotor. Energising them in order moves the rotor one step at a time, so counting steps is measuring the angle, with no sensor at all.
The 28BYJ-48 makes 32 steps per turn of its internal shaft and has a gearbox of roughly 64:1, so the output shaft needs about 2048 steps per turn. The trade-off is speed: about 15 turns per minute at most.
Each coil draws more than a pin can supply, which is why the ULN2003 sits between the Arduino and the motor. And the motor gets its own supply: running it from the Arduino's 5V can cause resets.
Specifications
- Steps per turn
- 2048, with the gearbox
- Gear ratio
- ≈ 64:1
- Supply
- 5 V
- Top speed
- ≈ 15 rpm
Wiring
| Component | Connects to | Note |
|---|---|---|
| ULN2003, IN1 | Pin 8 | |
| ULN2003, IN2 | Pin 9 | |
| ULN2003, IN3 | Pin 10 | |
| ULN2003, IN4 | Pin 11 | |
| ULN2003, + | Power module 5V rail | |
| ULN2003, − | Power module GND rail | |
| Motor | ULN2003 white connector | |
| IR receiver, S | Pin 12 | |
| IR receiver, + and − | Arduino 5V and GND | |
| Arduino GND | Power module GND rail | Essential: without a common GND the signals have no reference |
Code
// One turn each way depending on the remote key.
#include <Stepper.h>
#include <IRremote.hpp>
const int STEPS_PER_REV = 2048; // one turn of the output shaft
const int IR_PIN = 12;
// Replace these with the codes you read in the receiver lesson.
const uint16_t KEY_CLOCKWISE = 0x46;
const uint16_t KEY_COUNTERCLOCKWISE = 0x15;
// IN1, IN3, IN2, IN4 order: the one the 28BYJ-48 needs.
Stepper stepper(STEPS_PER_REV, 8, 10, 9, 11);
void setup() {
stepper.setSpeed(10); // turns per minute
IrReceiver.begin(IR_PIN);
}
void release() {
// Cut the coil current so they don't heat up at rest.
for (int pin = 8; pin <= 11; pin++) digitalWrite(pin, LOW);
}
void loop() {
if (!IrReceiver.decode()) return;
uint16_t command = IrReceiver.decodedIRData.command;
bool repeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT;
IrReceiver.resume();
if (repeat) return;
if (command == KEY_CLOCKWISE) stepper.step(STEPS_PER_REV);
if (command == KEY_COUNTERCLOCKWISE) stepper.step(-STEPS_PER_REV);
release();
}What the code does
- Stepper stepper(2048, 8, 10, 9, 11); takes the pins in the order IN1, IN3, IN2, IN4. In natural order the motor vibrates without turning.
- setSpeed(10) is turns per minute of the output shaft. Above 15 the motor starts skipping steps.
- step() blocks the program until the turn is done: while it spins, the remote is ignored.
- release() switches the coils off at the end. Without it, the motor keeps drawing current and heating up even when it's still.
Step by step
- Seat the power module on the breadboard, its − on the blue line and its + on the red one, and select 5 V with the jumpers.
- Connect the motor to the ULN2003, and the ULN2003 to the Arduino and the module following the table.
- Join the Arduino's GND to the module's GND rail.
- Replace the two key codes in the sketch with your remote's.
- Plug the adapter into the module, upload the code and press the keys.
Result
One key makes a full turn one way and the other key the opposite way. While it turns, the driver's LEDs light up in sequence.
If it doesn't work
- If the motor vibrates but doesn't turn, the pin order in the code isn't IN1, IN3, IN2, IN4.
- If the driver's LEDs light but the motor doesn't move, check the white connector and the on/off jumper on the driver board.
- If it doesn't react to the keys, check their codes with the sketch from lesson 1.7.
- If the board resets as it turns, the motor is drawing from the Arduino's 5V: power it from the module.