Search models, users, collections, and posts

Dual Stepper Differential Bevel Gear Mechanism

Print Profile(1)

All
X1 Carbon
P1P
X1E
H2D Pro
H2C
H2D
P2S
P1S
X1
A1
A1 mini
H2S
X2D
A2L

0.2mm layer, 2 walls, 15% infill
0.2mm layer, 2 walls, 15% infill
Designer
1.6 h
2 plates

Open in Bambu Studio
Boost
15
39
0
0
16
6
Released 

Description

This project is a compact, fully 3D-printable dual-stepper differential gear system designed to be controlled by a microcontroller.

The mechanism uses two 28BYJ-48 stepper motor units mounted on a shared axis, driving a central bevel gear assembly. By controlling the motors independently, you can precisely manipulate the output motion.

🎮 Microcontroller Control (ESP32 Example)

This system is designed to be paired with a microcontroller such as an ESP32 DevKit V1, using a joystick or other input device.

With simple control logic:

  • Push joystick forward → both motors move together
  • Push left/right → motors rotate in opposite directions
  • Diagonal movement → blended motion

This creates a smooth and intuitive control system ideal for interactive projects.

⚙️ How It Works

The mechanism acts as a mechanical mixer:

  • 🔁 Same motor direction → rotational output
  • 🔄 Opposite directions → differential motion
  • 🎯 Balanced input → stable center (no movement)

This makes it useful for applications where controlled rotation without translation is required.

🧱 Design Features

  • Fully 3D-printable
  • Compact and modular layout
  • Smooth bevel gear interaction
  • Designed for common hobby electronics
  • Easy integration with microcontrollers (ESP32 / Arduino)

🚀 Use Cases

  • Turret or pan control systems
  • Robotics joints
  • Camera mounts
  • Interactive displays
  • STEM / engineering demonstrations
     

    Code can easily be customized in your favourite AI model.  

🔌 ESP32 Pin Mapping (D# style)

🕹️ Joystick

FunctionESP32 GPIOBoard Label
X-axisGPIO 34D34
Y-axisGPIO 35D35
VCC3.3V3V3
GNDGNDGND

⚙️ Stepper Motor A (Left)

  • ULN2003 IN
ESP32 GPIOBoard Label
IN1GPIO 14D14
IN2GPIO 27D27
IN3GPIO 26D26
IN4GPIO 25D25

⚙️ Stepper Motor B (Right)

ULN2003 INESP32 GPIOBoard Label
IN1GPIO 33D33
IN2GPIO 32D32
IN3GPIO 18D18
IN4GPIO 19D19

🔋 Power

ComponentConnection
ESP32USB or 5V pin
ULN2003 boards5V external supply recommended
All GNDsMUST be connected together

⚠️ Important Notes 

GPIO 34 & 35 are input-only → perfect for joystick

Do NOT power motors from ESP32 5V pin

Use external 5V for stepper drivers

Common ground is required

🧠 Quick Summary (for users)

D34 / D35 → joystick

D14–27 → motor A

D33–19 → motor B

 

Here is the sample code to copy and paste in Arduino IDE app:

 

#include <AccelStepper.h>

// ---- Motor pins ----
#define M1_IN1 14
#define M1_IN2 27
#define M1_IN3 26
#define M1_IN4 25

#define M2_IN1 33
#define M2_IN2 32
#define M2_IN3 18
#define M2_IN4 19

// ---- Joystick ----
#define JOY_X 34
#define JOY_Y 35

AccelStepper stepperA(AccelStepper::HALF4WIRE, M1_IN1, M1_IN3, M1_IN2, M1_IN4);
AccelStepper stepperB(AccelStepper::HALF4WIRE, M2_IN1, M2_IN3, M2_IN2, M2_IN4);

// ---- tuning ----
float maxSpeed = 800;
float smoothing = 0.15;

// deadzones tuned for ESP32 stability
float inputDeadzone = 0.20;
float zeroLock = 0.18;

// smoothing state
float smoothX = 0;
float smoothY = 0;

// ---------------- FILTERED ADC READ ----------------
float readFiltered(int pin) {
 long sum = 0;
 for (int i = 0; i < 5; i++) {
   sum += analogRead(pin);
 }
 return sum / 5.0;
}

// ---------------- NORMALIZED AXIS ----------------
float readAxis(int pin) {
 float val = readFiltered(pin);

 // center around ~2048
 val = (val - 2048.0) / 2048.0;

 // input deadzone
 if (abs(val) < inputDeadzone) return 0;

 return val;
}

void setup() {
 analogReadResolution(12);

 stepperA.setMaxSpeed(maxSpeed);
 stepperB.setMaxSpeed(maxSpeed);
}

void loop() {

 // ---- read joystick ----
 float x = readAxis(JOY_X);
 float y = readAxis(JOY_Y);

 // ---- smoothing ----
 smoothX += smoothing * (x - smoothX);
 smoothY += smoothing * (y - smoothY);

 // ---- mix ----
 float motorA = smoothY + smoothX;
 float motorB = smoothY - smoothX;

 // ---- TRUE ZERO LOCK (prevents drift) ----
 if (abs(smoothX) < zeroLock && abs(smoothY) < zeroLock) {
   motorA = 0;
   motorB = 0;
 }

 // ---- normalize ----
 float maxVal = max(abs(motorA), abs(motorB));
 if (maxVal > 1.0) {
   motorA /= maxVal;
   motorB /= maxVal;
 }

 // ---- drive ----
 stepperA.setSpeed(motorA * maxSpeed);
 stepperB.setSpeed(motorB * maxSpeed);

 stepperA.runSpeed();
 stepperB.runSpeed();
}

Comment & Rating (0)

(0/1000)

License

This user content is licensed under a Standard Digital File License.

You shall not share, sub-license, sell, rent, host, transfer, or distribute in any way the digital or 3D printed versions of this object, nor any other derivative work of this object in its digital or physical format (including - but not limited to - remixes of this object, and hosting on other digital platforms). The objects may not be used without permission in any way whatsoever in which you charge money, or collect fees.