Built-in project · Arduino Uno R3

Remote stepper, a whole turn a press, on an Arduino Uno

An IR receiver on pin 12 and a 28BYJ-48 on its ULN2003 board, pins 8 to 11: >>| on the remote turns the shaft one whole turn, >|| turns it back. The whole build, an Arduino Uno and 3 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate About 25 minutes to build and run. Runs in your browser. Free, and no account needed.

The parts retail for about $35. On Mokxi they're free.

The circuit runs here once the page has loaded.

What you'll learn

  • Reading IR commands with the IRremote library
  • Stepper steps per turn on a 28BYJ-48
  • Named constants for remote button codes
  • Pin order quirks with the Stepper library
  • Difficulty: Intermediate
  • Time: About 25 minutes
  • Board: Arduino Uno R3
  • Parts: 5

How it works

An IR receiver on pin 12 decodes the remote. The >>| button, command 0x40, turns a 28BYJ-48 stepper a whole turn clockwise. The >|| button, command 0x43, turns it a whole turn back. A whole turn is 2048 steps.

The ULN2003 driver board is on pins 8 to 11. After each move, release turns the coil pins off. Held buttons are ignored, and presses that arrive while the motor is turning are thrown away when it finishes.

Parts list

5 parts, plus the jumper wires. They retail for about $35; on Mokxi they're free.

Wiring table

Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.

Part and pinConnects to
Infrared receiver, VS1838B pin OUTArduino Uno R3 pin 12
Stepper motor, 28BYJ-48 with ULN2003 pin IN4Arduino Uno R3 pin 11
Stepper motor, 28BYJ-48 with ULN2003 pin IN3Arduino Uno R3 pin 10
Stepper motor, 28BYJ-48 with ULN2003 pin IN2Arduino Uno R3 pin 9
Stepper motor, 28BYJ-48 with ULN2003 pin IN1Arduino Uno R3 pin 8
Stepper motor, 28BYJ-48 with ULN2003 pin VCCArduino Uno R3 pin 5V
Infrared receiver, VS1838B pin VCCArduino Uno R3 pin 5V
Stepper motor, 28BYJ-48 with ULN2003 pin GNDArduino Uno R3 pin GND
Infrared receiver, VS1838B pin GNDArduino Uno R3 pin GND
Infrared remote, 21 buttons pin IRInfrared receiver, VS1838B pin IR

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Remote stepper: two buttons on the IR remote turn a stepper a whole turn.
//
//   IR receiver   S (OUT) -> pin 12, - -> GND, + -> 5V
//   ULN2003 board IN1 -> pin 8, IN2 -> pin 9, IN3 -> pin 10, IN4 -> pin 11
//                 + -> 5V, - -> GND
//
// Press >>| (the remote's command 0x40) and the shaft turns one whole turn
// clockwise; press >|| (command 0x43) and it turns one whole turn back. The
// 28BYJ-48 takes 2048 steps for one turn of its output shaft.
//
// The Stepper library wants the pins in the order IN1, IN3, IN2, IN4: that
// is why the constructor below says 8, 10, 9, 11.

// The handset speaks NEC, so only that decoder is compiled in, as IRremote's
// own examples do to save flash.
#define DECODE_NEC
#include <IRremote.hpp>
#include <Stepper.h>

const int RECEIVER_PIN = 12;
const int STEPS_PER_TURN = 2048;
const uint8_t TURN_FORWARD = 0x40;
const uint8_t TURN_BACK = 0x43;

Stepper motor(STEPS_PER_TURN, 8, 10, 9, 11);

void release() {
  // Let the coils go after a move, so the driver stays cool.
  for (int pin = 8; pin <= 11; pin++) digitalWrite(pin, LOW);
}

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(RECEIVER_PIN, ENABLE_LED_FEEDBACK);
  motor.setSpeed(15);
  Serial.println("Mokxi Uno: remote stepper. >>| turns it forward, >|| back.");
}

void loop() {
  if (!IrReceiver.decode()) return;
  bool repeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT;
  uint8_t command = IrReceiver.decodedIRData.command;
  IrReceiver.resume();
  if (repeat) return;
  if (command == TURN_FORWARD) {
    Serial.println("one turn clockwise");
    motor.step(STEPS_PER_TURN);
    release();
  } else if (command == TURN_BACK) {
    Serial.println("one turn back");
    motor.step(-STEPS_PER_TURN);
    release();
  } else {
    Serial.print("button 0x");
    Serial.print(command, HEX);
    Serial.println(" does nothing here");
  }
  // Any presses that came in while the motor turned are old news.
  IrReceiver.resume();
}

Code walkthrough

The key functions of the sketch, and what each one does.

release sketch.ino

Sets pins 8 to 11 LOW after a move, so the coils are not left energized and the driver does not get hot.

void release() {
  // Let the coils go after a move, so the driver stays cool.
  for (int pin = 8; pin <= 11; pin++) digitalWrite(pin, LOW);
}

setup sketch.ino

Opens serial, starts the receiver on pin 12 with LED feedback and sets the motor to 15 rpm. It prints which buttons turn the shaft forward and back.

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(RECEIVER_PIN, ENABLE_LED_FEEDBACK);
  motor.setSpeed(15);
  Serial.println("Mokxi Uno: remote stepper. >>| turns it forward, >|| back.");
}

loop sketch.ino

Gets a decoded IR code if one is ready, ignoring repeats. TURN_FORWARD steps STEPS_PER_TURN forward and TURN_BACK steps the same amount back, each followed by release. Other buttons print their code. A final IrReceiver.resume drops presses made mid-move.

void loop() {
  if (!IrReceiver.decode()) return;
  bool repeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT;
  uint8_t command = IrReceiver.decodedIRData.command;
  IrReceiver.resume();
  if (repeat) return;
  if (command == TURN_FORWARD) {
    Serial.println("one turn clockwise");
    motor.step(STEPS_PER_TURN);
    release();
  } else if (command == TURN_BACK) {
    Serial.println("one turn back");
    motor.step(-STEPS_PER_TURN);
    release();
  } else {
    Serial.print("button 0x");
    Serial.print(command, HEX);
    Serial.println(" does nothing here");
  }
  // Any presses that came in while the motor turned are old news.
  IrReceiver.resume();
}

Troubleshooting

The usual mistakes with this circuit, and the fix for each.

  • The motor hums and does not turn This project
    The Stepper constructor needs 8, 10, 9, 11, meaning IN1, IN3, IN2, IN4. Keep it that way.
  • A button does nothing This project
    Check the serial monitor for the code it prints. Your remote's codes must match TURN_FORWARD and TURN_BACK.
  • A turn takes a long time This project
    A whole turn is 2048 steps at 15 rpm, so it takes a few seconds. That is expected.
  • The motor buzzes or shakes and does not turn. The coil pins IN1 to IN4 are in the wrong order for the library. Stepper motor
    For Arduino's Stepper library on a 28BYJ-48, create it with pins 8, 10, 9, 11 (IN1, IN3, IN2, IN4). Or use AccelStepper with HALF4WIRE and the same pin order.
  • It stalls or skips when spun fast or powered from the Arduino 5 V pin. It also draws more than a USB port may give. Stepper motor
    Power the ULN2003 board from a separate 5 V supply and join the grounds. Run it slowly, about 10 to 15 RPM, and ramp up speed gradually.
  • No signal is seen, or the module gets hot, because the three legs are in the wrong order. Infrared receiver
    On the VS1838B, with the dome facing you, the legs are usually OUT, GND, VCC from left to right. Check your module's marking before powering it. Supply is 2.7 to 5.5 V.
  • A plain LED blinking at the receiver is never detected. Infrared receiver
    The receiver only responds to light modulated at about 38 kHz. Send with a library such as IRremote, which makes the carrier. OUT idles high and goes low during a burst, so decode that inverted signal.
  • Button codes come out wrong or do not match another sketch. Infrared remote
    Remotes differ. Print the raw codes for your buttons first, then compare against those values. A repeat while you hold a button is a special repeat code, not a new press.

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.