A 2-DOF-per-leg quadruped controller for Arduino Uno using a PCA9685 16-channel servo driver.
This firmware uses:
- Inverse kinematics (IK) for each leg
- A phase-shifted walking gait
- Servo safety clamping + saturation reporting
- Startup posture initialization + emergency stop from Serial
- MPU-6050 IMU integration with Mahony AHRS orientation estimation
- Arduino Uno
- PCA9685 servo driver (I2C)
- 8 servo motors (Hip + Knee for each leg)
- External 5V servo power supply (recommended)
Leg order used in code:
LEG_BL= 0 (Back Left)LEG_FL= 1 (Front Left)LEG_BR= 2 (Back Right)LEG_FR= 3 (Front Right)
PCA9685 channels (src/globals.cpp):
- Back Left: Hip
0, Knee1 - Front Left: Hip
4, Knee5 - Back Right: Hip
8, Knee9 - Front Right: Hip
12, Knee13
- PCA9685 default address in code:
0x40 - PWM frequency:
50 Hz - Serial monitor baud:
115200
platformio.ini is configured for:
platform = atmelavrboard = unoframework = arduino
- Open this folder in VS Code.
- Install PlatformIO IDE extension.
- Build from PlatformIO panel.
- Upload to the Uno.
- Open Serial Monitor at
115200.
pio run
pio run -t upload
pio device monitor -b 115200Serial commands:
- Send
sorSto trigger emergency stop.
Emergency stop behavior:
- Gait loop halts
- Legs move to neutral IK posture
- Saturation statistics are printed
The codebase is split by responsibility:
src/main.cpp- System startup and main control loop
- I2C device check and gait scheduler
src/globals.cpp- Global state and leg configuration table
src/hardware.cpp- I2C detection + angle-to-PWM tick conversion
src/ik.cpp- 2-link inverse kinematics + reachability checks
src/servo_control.cpp- IK-to-servo mapping, mirroring, clamp, saturation tracking
src/gait.cpp- Swing/stance trajectory generation for each leg
src/safety.cpp- Servo initialization, emergency stop, saturation reports
src/imu.cpp- MPU-6050 readout, startup gyro calibration, Mahony AHRS, Euler angle state API
Headers are under include/.
Primary tuning parameters are in include/config.h:
- Leg geometry
UPPER_LEG_LENGTHLOWER_LEG_LENGTH
- Gait motion
STEP_LENGTHSTEP_HEIGHTGAIT_CYCLE_DURATION(defined insrc/globals.cpp)
- Control timing
CONTROL_DT
- Workspace target
X_OFFSETY_GROUND
- Mechanical mapping
HIP_FRAME_ROTATIONlegs[]mechanical offsets (hipMechOffset,kneeMechOffset)
Safety mechanisms currently implemented:
- IK reachability test (with singularity margin)
- Servo angle clamp to
[0, 180] - Saturation event counters per leg/joint
- Initialization mode disables saturation counting during startup posture
- Initialize Serial and I2C
- Detect PCA9685 at
0x40 - Set PWM frequency to
50 Hz - Move all legs to neutral standing posture
- Start gait loop
- Power servos from a dedicated supply; do not power multiple servos from Uno 5V.
- Keep grounds common between Uno and servo power supply.
- If you see frequent saturation warnings, retune offsets and/or gait targets.
- IMU implementation expects MPU-6050 at I2C address
0x68and performs startup gyro calibration over initial samples while the robot is held still.
QUADRUPED/
include/
config.h
robot_types.h
globals.h
hardware.h
ik.h
servo_control.h
gait.h
safety.h
imu.h
src/
main.cpp
globals.cpp
hardware.cpp
ik.cpp
servo_control.cpp
gait.cpp
safety.cpp
imu.cpp
platformio.ini