FluxBench.AIShared project · read-only

Stepper Photo Turntable

ESP32 DevKit (WROOM-32)·Arduino C++·Updated Jul 27, 2026·by FluxBench TeamIncludes Lab + Schematic

A motorized photo turntable: a 28BYJ-48 geared stepper motor (driven through a ULN2003 board with the classic Arduino Stepper library) rotates a platform in precise 45-degree moves at 12 RPM, pausing after each move so a camera could take a shot. A 128x64 OLED shows the platform angle in big digits plus the direction (CW / CCW), and the button on GPIO 4 reverses the direction. Watch the red shaft marker on the bench motor rotate with every move.

sketch.ino
// Stepper Photo Turntable - a 28BYJ-48 geared stepper turns a small platform
// in precise 45-degree moves so a camera can shoot a product from every side.
// The classic Arduino Stepper library drives the motor through a ULN2003 board.
// Press the button on the bench to reverse direction. Watch the red shaft
// marker on the motor rotate with every move.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Stepper.h>

#define STEPS_PER_REV 2048   // 28BYJ-48 with its gearbox
#define DIR_PIN 4            // push button: reverse direction

Adafruit_SSD1306 display(128, 64, &Wire, -1);
// 28BYJ-48 quirk: coil order is IN1, IN3, IN2, IN4 -> GPIO 14, 26, 27, 25
Stepper motor(STEPS_PER_REV, 14, 26, 27, 25);

long pos = 0;
int dir = 1;

void setup() {
  Serial.begin(115200);
  pinMode(DIR_PIN, INPUT_PULLUP);
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();
  motor.setSpeed(12);   // 12 RPM - one full turn takes 5 seconds
  Serial.println("Turntable ready - press the button to reverse");
}

void loop() {
  if (digitalRead(DIR_PIN) == LOW) {
    dir = -dir;
    Serial.println("Direction reversed!");
    delay(300);   // simple debounce
  }

  motor.step(dir * 256);   // 45 degrees per move (blocking, ~0.6 s)
  pos = pos + dir * 256;

  long wrapped = ((pos % STEPS_PER_REV) + STEPS_PER_REV) % STEPS_PER_REV;
  int angle = (int)(wrapped * 360 / STEPS_PER_REV);

  const char* word = "CW";
  if (dir < 0) word = "CCW";

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print("PHOTO TURNTABLE");
  display.setTextSize(3);
  display.setCursor(0, 14);
  display.print(angle);
  display.setTextSize(1);
  display.print(" deg");
  display.setCursor(0, 44);
  display.print(word);
  display.print("  12 RPM");
  display.setCursor(0, 54);
  display.print("Btn = reverse");
  display.display();

  Serial.print("angle=");
  Serial.print(angle);
  Serial.print(" deg  ");
  Serial.println(word);
  delay(600);   // pause so the camera can take a shot
}

Built with FluxBench.AI — the AI workbench for embedded projects.