How to Build a Split-Flap Clock Digit with ESP32
A 3D-printed mechanical digit with stepper motion and magnetic homing
Updated

Build one working split-flap digit module: the mechanical unit that flips through numbers in a retro clock. The electronics are deliberately simple: an ESP32 sends four step signals to a ULN2003 driver, the driver moves a 28BYJ-48 geared stepper, and a KY-035 Hall sensor plus a small magnet gives the wheel a repeatable home position after boot.
The printed mechanism does most of the visible work. Your job is to make the wheel move one flap at a time, recover its zero position, and expose the calibration values you will need before scaling up to a multi-digit clock.
For the first build, keep it to one digit. Once homing and flap spacing are reliable, you can duplicate the module and give each digit its own motor driver and Hall sensor input.
Watch the build here on YouTube.
Wiring diagram
Wiring diagram
Components needed
| Component | Type | Qty | Buy |
|---|---|---|---|
| ULN2003 stepper driver board | actuator | 1 | €1.90 |
| 28BYJ-48 stepper motor | actuator | 1 | |
| KY-035 Hall effect sensor | sensor | 1 | €33.90 |
| 10 x 3 mm magnet | other | 1 | |
| 3D-printed split-flap digit module | other | 1 |
Prices and availability are indicative and may have been updated by the supplier. Schematik may earn a commission from purchases made through affiliate links.
Assembly
Assemble the printed flap wheel
Press the wheel parts onto the shaft, clamp the digit flaps in order, and fit the right-side cap and small gear. Use the M2 inserts and 8 mm M2 screws so the wheel stays square but can still rotate freely.
- Keep the flap cards in numeric order before closing the wheel.
- Turn the wheel by hand before adding the motor. Any scraping here will become missed steps later.
Mount the sensor and stepper
Install the KY-035 Hall sensor with the short M2 screws, then mount the 28BYJ-48 stepper motor with M3 screws. Place the 10 x 3 mm magnet so it passes close to the Hall sensor once per revolution.
- Leave a small air gap between magnet and sensor. It should trigger reliably without touching.
- Mark the home flap with tape during calibration so you can see when the code and mechanism agree.
- Unplug power before adjusting the magnet near the sensor or motor wiring.
Wire the driver and Hall sensor
Connect ESP32 GPIO 16, 17, 18 and 19 to ULN2003 IN1-IN4. Power the ULN2003 motor side from 5 V, share GND with the ESP32, and connect the Hall sensor AO pin to GPIO 34 with VCC on 3V3.
- Use an external 5 V supply for the stepper if USB power sags or the motor chatters.
- GPIO 34 is input-only, which is fine for the analog Hall sensor.
- Do not power the 28BYJ-48 directly from ESP32 GPIO pins. Use the ULN2003 driver board.
Upload and calibrate one digit
Upload the sketch, open Serial Monitor at 115200 baud, and let the wheel home against the Hall sensor. If the displayed digit lands between flaps, adjust STEPS_PER_FLAP slightly until each move centres the next number.
- Start with one digit unit before chaining multiple modules into a full clock.
- If homing never completes, print the raw analogRead(HALL_PIN) value and tune HOME_THRESHOLD.
Pin assignments
| Pin | Connection | Type |
|---|---|---|
| GPIO 16 | uln2003-stepper-driver-1 IN1 | DIGITAL |
| GPIO 17 | uln2003-stepper-driver-1 IN2 | DIGITAL |
| GPIO 18 | uln2003-stepper-driver-1 IN3 | DIGITAL |
| GPIO 19 | uln2003-stepper-driver-1 IN4 | DIGITAL |
| 5V | uln2003-stepper-driver-1 5V | POWER |
| GND | uln2003-stepper-driver-1 GND | GROUND |
| 3V3 | ky-035-hall-sensor-1 VCC | POWER |
| GND | ky-035-hall-sensor-1 GND | GROUND |
| GPIO 34 | ky-035-hall-sensor-1 AO | ANALOG |
Code
#include <Arduino.h>
#include <Stepper.h>
#define STEPS_PER_REV 2048
#define MOTOR_IN1 16
#define MOTOR_IN2 17
#define MOTOR_IN3 18
#define MOTOR_IN4 19
#define HALL_PIN 34
#define HOME_THRESHOLD 1800
#define FLAP_COUNT 10
#define STEPS_PER_FLAP 205
Stepper flapMotor(STEPS_PER_REV, MOTOR_IN1, MOTOR_IN3, MOTOR_IN2, MOTOR_IN4);
int currentDigit = 0;
bool magnetDetected() {
return analogRead(HALL_PIN) < HOME_THRESHOLD;
}
void stepForward(int steps) {
flapMotor.step(steps);
delay(80);
}
void homeWheel() {
Serial.println("Homing split-flap wheel...");
for (int i = 0; i < STEPS_PER_REV + 300; i += 4) {
if (magnetDetected()) {
currentDigit = 0;
Serial.println("Home magnet found");
return;
}
stepForward(4);
}
Serial.println("Home magnet not found. Check sensor alignment.");
}
void showDigit(int targetDigit) {
targetDigit = constrain(targetDigit, 0, FLAP_COUNT - 1);
int delta = (targetDigit - currentDigit + FLAP_COUNT) % FLAP_COUNT;
stepForward(delta * STEPS_PER_FLAP);
currentDigit = targetDigit;
Serial.printf("Showing digit %d\n", currentDigit);
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
pinMode(HALL_PIN, INPUT);
flapMotor.setSpeed(12);
delay(500);
homeWheel();
}
void loop() {
for (int digit = 0; digit < FLAP_COUNT; digit++) {
showDigit(digit);
delay(1200);
}
}
// Run this and build other cool things at schematik.ioReady to build this?
Open this project in Schematik to get the full wiring diagram, pin assignments, and deployable code for the Split-Flap Clock Digit.
Open in Schematik →