Build Your Own
Robot Dog
That Really Walks!
A four-legged mini robot powered by Raspberry Pi — it trots, sits, wags, and obeys your Python commands! 🐾⚡
🐾 How Does a Robot Dog Walk?
Walking on four legs is actually a fascinating engineering problem! Each leg has two servo motors — one at the shoulder (moves leg forward/back) and one at the knee (bends the leg up/down). By coordinating all four legs in the right sequence, the robot trots forward smoothly.
DOF = Degree of Freedom. Each leg has 2 joints (shoulder + knee) controlled by one servo each.
Front-Left & Rear-Right move together, then Front-Right & Rear-Left — just like a real dog trotting!
Controls all 8 servos via I²C — Raspberry Pi sends commands to one chip, chip drives all servos.
Python on the Pi calculates leg angles and sends precise timing signals to each servo in sequence.
🛒 Parts Shopping List
All available on Amazon India, Robu.in, or RoboElements. Budget: approximately ₹3,800:
Circuit Diagram
Key rule: Raspberry Pi and servos use completely separate power supplies. Servos draw too much current — sharing power would crash the Pi!
🔧 Step-by-Step Build Guide
Work through every step in order. Assemble the frame first, then wire, then code.
Flash Raspberry Pi OS Lite (64-bit) on your 32GB SD card using the Raspberry Pi Imager tool. Boot it up, connect to Wi-Fi, then open a terminal and install the required Python libraries:
TERMINALsudo apt-get update && sudo apt-get upgrade -y # Enable I2C interface sudo raspi-config # → Interface Options → I2C → Enable → Reboot # Install Python libraries pip3 install adafruit-circuitpython-pca9685 \ adafruit-circuitpython-motor \ board busio luma.oled pillow # Verify I2C devices found (should see 0x40 PCA9685 + 0x3C OLED) sudo i2cdetect -y 1
i2cdetect you should see addresses 0x40 (PCA9685) and 0x3C (OLED) in the grid. If they're missing, recheck your SDA/SCL wiring!
Assemble the frame following these mounting positions:
- Body plate: The main platform. Mount the Raspberry Pi and PCA9685 on top
- Shoulder servos: 4 servos mount at the corners of the body plate, pointing down. Their horns attach to the upper leg segments
- Knee servos: 4 servos mount mid-leg, connecting the upper and lower leg segments
- Leg length: Upper leg ~5 cm, lower leg ~6 cm for best walking geometry
- Feet: Small rubber caps or 3D-printed paw pads for grip
Run this script before assembling legs — it centers every servo at 90° so you can attach legs in the correct neutral position:
calibrate_servos.pyimport board, busio from adafruit_pca9685 import PCA9685 from adafruit_motor import servo import time i2c = busio.I2C(board.SCL, board.SDA) pca = PCA9685(i2c) pca.frequency = 50 # Create servo objects for all 8 channels servos = [ servo.Servo(pca.channels[i], min_pulse=500, max_pulse=2500) for i in range(8) ] print("Setting all 8 servos to 90° (neutral position)...") for s in servos: s.angle = 90 time.sleep(0.05) print("All servos centered! Attach legs pointing straight down.") print("Press Ctrl+C when done.") try: while True: time.sleep(1) except KeyboardInterrupt: pca.deinit() print("Done! Now bolt the legs in place.")
This is the complete Python brain — it controls the trot gait, sit, stand, and wag-tail behaviours:
robot_dog.pyimport board, busio, time from adafruit_pca9685 import PCA9685 from adafruit_motor import servo # ── Hardware init ──────────────────────────────── i2c = busio.I2C(board.SCL, board.SDA) pca = PCA9685(i2c) pca.frequency = 50 # 8 servos: channels 0-7 # Even channels = shoulder, Odd = knee # 0,1=FL 2,3=FR 4,5=RL 6,7=RR servos = [ servo.Servo(pca.channels[i], min_pulse=500, max_pulse=2500) for i in range(8) ] # ── Angle helper ───────────────────────────────── # ch: 0-7, angle: 0-180 def set_servo(ch, angle): angle = max(0, min(180, angle)) servos[ch].angle = angle # Move all 8 servos at once from current position dict def pose(angles, duration=0.3): # angles = [FL_sh, FL_kn, FR_sh, FR_kn, # RL_sh, RL_kn, RR_sh, RR_kn] for i, ang in enumerate(angles): set_servo(i, ang) time.sleep(duration) # ── Preset poses ───────────────────────────────── NEUTRAL = [90,90, 90,90, 90,90, 90,90] SIT = [90,90, 90,90, 60,130, 60,130] # rear legs bent STAND = [90,70, 90,70, 90,70, 90,70] # all knees straight # ── Trot gait (diagonal pairs) ─────────────────── # Pair A: FL + RR step forward while FR + RL support # Pair B: FR + RL step forward while FL + RR support STEP_FWD = 25 # how many degrees shoulders swing LIFT = 30 # how much knee lifts leg off ground def trot_step_A(): # Pair A (FL+RR) lifts and steps forward # Pair B (FR+RL) stays grounded and pushes back pose([ 90-STEP_FWD, 90-LIFT, # FL: swing fwd + lift 90+STEP_FWD, 90, # FR: push back, grounded 90+STEP_FWD, 90, # RL: push back, grounded 90-STEP_FWD, 90-LIFT # RR: swing fwd + lift ], 0.18) pose([ # lower pair A feet 90-STEP_FWD, 90, 90+STEP_FWD, 90, 90+STEP_FWD, 90, 90-STEP_FWD, 90 ], 0.1) def trot_step_B(): # Pair B (FR+RL) lifts and steps forward pose([ 90-STEP_FWD, 90, # FL: push back 90+STEP_FWD, 90-LIFT, # FR: swing fwd + lift 90-STEP_FWD, 90-LIFT, # RL: swing fwd + lift 90+STEP_FWD, 90 # RR: push back ], 0.18) pose([ # lower pair B feet 90-STEP_FWD, 90, 90+STEP_FWD, 90, 90-STEP_FWD, 90, 90+STEP_FWD, 90 ], 0.1) def walk_forward(steps=4): pose(STAND, 0.3) for _ in range(steps): trot_step_A() trot_step_B() pose(NEUTRAL, 0.3) def sit_down(): pose(SIT, 0.5) print("🐾 Sitting!") def wag_tail(wags=4): # Simulate tail wag by wiggling rear-right shoulder for _ in range(wags): set_servo(6, 70); time.sleep(0.15) set_servo(6, 110); time.sleep(0.15) set_servo(6, 90) print("🐾 Tail wagging!") # ── Main behaviour sequence ─────────────────────── if __name__ == "__main__": print("🤖 Robot Dog Starting!") pose(NEUTRAL, 1.0) # start in neutral try: while True: print("▶ Walking forward...") walk_forward(steps=6) time.sleep(0.5) print("▶ Sitting...") sit_down() time.sleep(1.0) print("▶ Wagging tail...") wag_tail(5) time.sleep(0.5) pose(NEUTRAL, 0.5) time.sleep(1.0) except KeyboardInterrupt: pose(NEUTRAL, 0.5) pca.deinit() print("🐾 Robot Dog stopped. Goodbye!")
robot_dog.py and run with python3 robot_dog.py. Your dog will walk, sit, and wag in a loop! Press Ctrl+C to stop gracefully and return to neutral.
STEP_FWD (try 20–35) and LIFT (try 20–40) to find the smoothest walk for your chassis dimensions!
Add this code to show the current behaviour on the OLED screen mounted on the dog's back — so you can see what it's doing from a distance:
oled_status.pyfrom luma.core.interface.serial import i2c from luma.oled.device import ssd1306 from luma.core.render import canvas from PIL import ImageFont serial = i2c(port=1, address=0x3C) oled = ssd1306(serial, width=128, height=64) def show_status(mode, step=0): with canvas(oled) as draw: draw.text((2, 4), "🐾 Robot Dog", fill="white") draw.text((2, 22), f"Mode: {mode}", fill="white") draw.text((2, 40), f"Step: {step}", fill="white") # Call show_status("TROT", step) inside walk_forward() # Call show_status("SIT") inside sit_down() # Call show_status("WAG") inside wag_tail()
🛠️ Troubleshooting Guide
Quadruped robots are complex — here are the most common problems and how to fix them:
| 🔴 Problem | 🟡 Likely Cause | ✅ Fix |
|---|---|---|
| PCA9685 not found on I²C | I²C not enabled or wiring wrong | Run raspi-config → Interface Options → enable I²C. Recheck SDA→GPIO2 and SCL→GPIO3 |
| Servos jitter constantly | Power supply under-voltage | Confirm LiPo → buck converter outputs exactly 6V. Cheap 18650 cells may sag under load |
| Dog falls over while walking | Leg geometry / servo angles wrong | Reduce STEP_FWD to 15° first. Ensure centre of gravity is between the four feet |
| One leg moves differently | That servo was attached at wrong angle | Re-run calibrate_servos.py, detach that leg's horn, and reattach pointing straight down at 90° |
| Pi reboots during movement | Servos drawing current through Pi's 5V rail | Servo V+ must come from the buck converter, NOT the Pi's GPIO 5V pin. Check V+ wiring on PCA9685 |
| Walk looks jerky not smooth | Pose duration too short | Increase duration in pose() calls from 0.18 to 0.25 seconds for smoother transitions |
| OLED shows nothing | I²C address mismatch | Run sudo i2cdetect -y 1 — if OLED shows as 0x3D, change address in the code |
🚀 Level Up Your Robot Dog!
Once your dog walks, these upgrades turn it into a truly impressive robot:
Add a Pi Camera to the head — stream video from the dog's point of view to your phone!
Add a USB microphone — say "sit", "walk", "wag" and the dog obeys using speech_recognition!
Control your dog from a phone web browser using a Flask web server running on the Pi!
Add a small USB speaker — play bark.mp3 and growl.mp3 sounds at the right moments!
Add an HC-SR04 ultrasonic sensor on the nose — the dog stops and turns before hitting walls!
Connect a Bluetooth PS4/Xbox controller to the Pi for manual real-time gait control!
❓ Frequently Asked Questions
Arduino is great for simple servo control, but for a walking gait you need precise timing across 8 servos simultaneously. Raspberry Pi runs Python with proper threading support, can add a camera, run Wi-Fi, host a web server, and do speech recognition — all things Arduino can't do on its own.
Eight MG90S metal-gear servos under load can draw 2–4 Amperes combined. The Raspberry Pi's power supply is rated for ~3A just for itself. Mixing them would cause the Pi to brownout and reboot during movement. Always use a dedicated battery for servos!
Absolutely! Search "Mini Quadruped Robot Dog STL" on Thingiverse or Printables — there are free designs sized for MG90S servos. Print in PLA at 40% infill for a good strength-to-weight ratio. Printing takes about 6–8 hours for a full chassis.
Great next challenge! For turning right, make the left-side legs take larger steps forward than the right-side legs. For sharp turns, swing one side forward while the other side walks backward — called a "spin turn." Adjust the STEP_FWD value per side in the trot functions.
One of the best possible choices! A walking quadruped robot immediately impresses any audience. Be ready to explain the trot gait pattern, inverse kinematics (angle calculations for leg positions), and why diagonal pairs move together. The real Boston Dynamics story about Spot is a great hook to open with!
This happens when servos from different batches have slightly different mechanical zero positions. Fix by adding small individual offset values per servo in the code — for example, if CH2 drives slightly left, change its neutral from 90 to 93. Tune each servo's offset until the dog walks straight.

Comments
Post a Comment