Build a Chess-Playing Robot with Raspberry Pi | DIY Robotics for Kids

Build a Chess-Playing Robot with Raspberry Pi | DIY Robotics for Kids

Build a Chess-Playing Robot
with Raspberry Pi

A real AI chess engine inside a servo arm — it thinks, picks its move, and physically slides the piece across the board. You play, it plays back.

▶ YOU: e2→e4 🤖 ROBOT: e7→e5 ▶ YOU: g1→f3 🤖 ROBOT: b8→c6
🎓 Intermediate–Advanced ⏱ 6–8 Hours Build 🦾 4-Servo Robot Arm 🧠 Stockfish AI Engine 🐍 Python Code Included
Overview

How Does a Chess Robot Actually Work?

This robot has four main jobs happening one after another, like a relay race. You make your move and type it in; the AI works out the perfect counter-move; the robot arm swings over the right square; and the gripper picks up the piece and carries it across the board. Let's meet each layer:

👤
You type your move

You enter your move in standard chess notation (e.g. "e2e4") into the terminal — no camera needed for the main build.

🧠
Stockfish calculates the reply

Stockfish — the same AI engine used by World Chess Champions — runs on the Pi and picks the best counter-move in milliseconds.

🗺️
Coordinate mapping

Python converts the chess square name (like "e7") into exact servo angles for the arm to reach that spot on the board.

🦾
Servo arm moves the piece

Four servos work together — rotating the base, swinging the shoulder, bending the elbow, and opening/closing the gripper — to physically move the chess piece.

Real Chess Rules

Uses the python-chess library to track every legal move, castling, and checkmate.

🤖
Real AI Thinking

Stockfish adjusts difficulty from easy (ELO 800) to grandmaster level — set it anywhere you like.

🔧
Physical Servo Arm

Four SG90 servos form a simple 4-DOF arm that reaches every square on the board.

🔊
Voice Announcements

The Pi speaks the robot's move aloud using espeak so you always know what happened.

🎓 What you'll learn Robotic arm kinematics, servo motor control with PWM, chess AI integration, Python programming, Raspberry Pi GPIO, and coordinate mapping — all in one project!
Parts List

Materials You'll Need

🖥️ Computing & Brains

Raspberry Pi 4 (2GB+) or Pi 3B+
16GB microSD card (Class 10)
Official Pi power supply (5V 3A USB-C)
Monitor, keyboard, mouse (for setup)

🦾 Robot Arm Electronics

SG90 micro servo motor
PCA9685 16-channel servo driver board
5V 3A external power supply (for servos)
Breadboard
Jumper wires (male-to-male, male-to-female)

🏗️ Arm Frame & Board

Standard chess set (board + pieces)
Balsa wood or strong cardboard for arm
M2/M3 nuts, bolts, standoffs
Hot glue gun + glue sticks
Small neodymium magnet (optional gripper alt.)
Ruler, craft knife (adult help)
💡 Why the PCA9685 servo driver board? The Raspberry Pi can only generate hardware PWM on 2 pins, and it has no analog output at all. The PCA9685 is a cheap I²C board that controls up to 16 servos independently with perfect timing — it's the standard solution for Pi robot arms.
Build

Building the 4-Servo Robot Arm

Our arm has four joints, each controlled by one SG90 servo. Think of it like your own arm: the base rotates left/right (like twisting at the waist), the shoulder swings the whole arm forward/back, the elbow bends up/down, and the gripper squeezes to grab pieces.

BASE PLATFORM S1 ↔ Base Rotate S2 ↕ Shoulder S3 ↕ Elbow S4 ✊ Gripper Chess Board arm reaches board S1 Base S2 Shoulder S3 Elbow S4 Gripper

Step-by-Step Arm Assembly

1
Cut the arm segments. From balsa wood or stiff card, cut: a base block (7×7cm), a lower arm (14cm long), an upper arm (10cm long), and a small gripper mount (5cm). Sand edges smooth.
2
Mount Servo S1 (Base Rotate) flat on the base block, facing upward. Hot-glue it securely. The lower arm attaches to its output arm.
3
Mount Servo S2 (Shoulder) at the top of the lower arm. Its output arm connects to the bottom of the upper arm, letting it swing forward and backward.
4
Mount Servo S3 (Elbow) at the top of the upper arm. Attach the gripper mount to its output arm so it can tilt up and down.
5
Mount Servo S4 (Gripper) at the end of the gripper mount. Glue two small cardboard "fingers" to its output arm — when it rotates, the fingers pinch together to grab a chess piece.
6
Place the arm base next to (not on) the chess board so the arm can reach all 64 squares. The arm must be positioned at the corner of the board.
🧲 Magnet gripper alternative! Instead of a pinch gripper, glue a small neodymium magnet to the end of S3's arm, and glue metal bottle caps to the bottoms of your chess pieces. The magnet picks up pieces by sticking to the cap — simpler, and very satisfying!
Wiring

Wiring the Circuit

🔌 Key principle — separate power for servos! NEVER power servos directly from the Pi's 5V pin. Four servos together can draw 1–2A and will crash or damage the Pi. Always use an external 5V 3A supply for the PCA9685 board, sharing only the ground with the Pi.

Raspberry Pi → PCA9685 (I²C)

Raspberry Pi PinPCA9685 PinWire Colour
Pin 1 — 3.3VVCCRed
Pin 6 — GNDGNDBlack
Pin 3 — SDA (GPIO 2)SDABlue
Pin 5 — SCL (GPIO 3)SCLYellow

External Power → PCA9685

Power SupplyPCA9685 Terminal
+5VV+ (the servo power terminal, next to GND)
GNDGND (shared with Pi GND)

Servos → PCA9685 Channels

ServoFunctionPCA9685 Channel
S1Base RotateChannel 0
S2ShoulderChannel 1
S3ElbowChannel 2
S4GripperChannel 3

Quick-Reference Pin Map

GPIO 2
SDA → PCA9685
GPIO 3
SCL → PCA9685
3.3V
PCA9685 VCC
GND
PCA9685 + Ext. GND
CH 0
S1 Base
CH 1
S2 Shoulder
CH 2
S3 Elbow
CH 3
S4 Gripper
Setup

Setting Up Your Raspberry Pi

1
Flash Raspberry Pi OS. Download Raspberry Pi Imager from raspberrypi.com/software, choose "Raspberry Pi OS (64-bit)", and flash your microSD card. Set up your Wi-Fi password in the imager's settings.
2
Enable I²C. Open a terminal and run sudo raspi-config → Interface Options → I2C → Enable. Then reboot.
3
Confirm I²C is working. Run sudo i2cdetect -y 1 — you should see a device at address 0x40 (that's the PCA9685).
4
Update the system. Run: sudo apt update && sudo apt upgrade -y
Software

Installing the Chess Software

Open a terminal on the Pi and run these commands one by one:

# 1. Install Stockfish chess engine
sudo apt install stockfish espeak -y

# 2. Install Python libraries
pip3 install python-chess adafruit-circuitpython-pca9685 adafruit-circuitpython-motor

# 3. Confirm Stockfish is installed
which stockfish
# Should print: /usr/games/stockfish

# 4. Test the chess library quickly
python3 -c "import chess; print('python-chess OK ✓')"

# 5. Test the servo library
python3 -c "import board, busio; print('I2C libraries OK ✓')"
✅ All three tests should print "OK" before moving on. If you see "ModuleNotFoundError", try pip3 install [module-name] again and check your internet connection.
Code

The Full Python Code

Save this as chess_robot.py on your Pi desktop. Read the comments — every section explains exactly what it does!

#!/usr/bin/env python3
# ═══════════════════════════════════════════════════════════
#  ♟  CHESS ROBOT — Raspberry Pi + Stockfish + Servo Arm
#  Author: Your Name Here!
#  How it works:
#    1. You type your move (e.g. "e2e4")
#    2. Stockfish picks the best reply
#    3. The servo arm physically moves the piece
# ═══════════════════════════════════════════════════════════

import chess
import chess.engine
import time
import os
import board
import busio
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo as Servo

# ── SERVO SETUP ──────────────────────────────────────────
i2c = busio.I2C(board.SCL, board.SDA)
pca = PCA9685(i2c)
pca.frequency = 50  # Standard servo frequency: 50Hz

# Create 4 servo objects, one per channel
servo_base     = Servo.Servo(pca.channels[0], min_pulse=500, max_pulse=2400)
servo_shoulder = Servo.Servo(pca.channels[1], min_pulse=500, max_pulse=2400)
servo_elbow    = Servo.Servo(pca.channels[2], min_pulse=500, max_pulse=2400)
servo_gripper  = Servo.Servo(pca.channels[3], min_pulse=500, max_pulse=2400)

# Gripper angles
GRIP_OPEN  = 30   # degrees — open enough to fit around a piece
GRIP_CLOSE = 90   # degrees — closed / holding piece
HOVER_ELBOW = 45 # safe height to travel between squares
DOWN_ELBOW  = 20 # low enough to pick up / drop piece

# ── SQUARE → SERVO ANGLE MAP ─────────────────────────────
# Each chess square (a1 to h8) maps to (base_angle, shoulder_angle)
# These are EXAMPLE values — you MUST calibrate for your board position!
# See the Calibration section for how to tune these.

FILES = 'abcdefgh'
RANKS = '12345678'

def square_to_angles(square_name):
    """Convert a square like 'e4' to (base_angle, shoulder_angle)"""
    file_index = FILES.index(square_name[0])  # a=0 … h=7
    rank_index = int(square_name[1]) - 1         # 1=0 … 8=7

    # Linear interpolation across the board
    # BASE angle sweeps across files (columns): a=20° … h=160°
    # SHOULDER angle sweeps across ranks (rows): 1=60° … 8=120°
    base_angle     = 20 + file_index * (140 / 7)
    shoulder_angle = 60 + rank_index * (60  / 7)
    return round(base_angle), round(shoulder_angle)

# ── LOW-LEVEL SERVO HELPERS ──────────────────────────────

def move_servo_smooth(servo_obj, target, step=3, delay=0.02):
    """Smoothly move a servo to target angle to avoid jerking"""
    current = servo_obj.angle or 90
    direction = 1 if target > current else -1
    for angle in range(int(current), int(target), direction * step):
        servo_obj.angle = angle
        time.sleep(delay)
    servo_obj.angle = target

def arm_home():
    """Move arm to safe resting position"""
    servo_elbow.angle    = HOVER_ELBOW
    servo_base.angle     = 90
    servo_shoulder.angle = 90
    servo_gripper.angle  = GRIP_OPEN
    time.sleep(0.5)

def pick_up_piece(square_name):
    """Move arm over a square, lower, grab, lift back up"""
    base_a, shoulder_a = square_to_angles(square_name)

    print(f"  → Moving to {square_name} ({base_a}°, {shoulder_a}°)")

    # 1. Hover above the square
    servo_elbow.angle = HOVER_ELBOW
    move_servo_smooth(servo_base,     base_a)
    move_servo_smooth(servo_shoulder, shoulder_a)
    time.sleep(0.4)

    # 2. Open gripper and lower
    servo_gripper.angle = GRIP_OPEN
    servo_elbow.angle   = DOWN_ELBOW
    time.sleep(0.4)

    # 3. Close gripper to grab piece
    servo_gripper.angle = GRIP_CLOSE
    time.sleep(0.3)

    # 4. Lift back up
    servo_elbow.angle = HOVER_ELBOW
    time.sleep(0.3)

def place_piece(square_name):
    """Move arm over target square and release piece"""
    base_a, shoulder_a = square_to_angles(square_name)

    print(f"  → Placing on {square_name} ({base_a}°, {shoulder_a}°)")

    # 1. Hover above target
    move_servo_smooth(servo_base,     base_a)
    move_servo_smooth(servo_shoulder, shoulder_a)
    time.sleep(0.4)

    # 2. Lower
    servo_elbow.angle = DOWN_ELBOW
    time.sleep(0.4)

    # 3. Open gripper — piece drops
    servo_gripper.angle = GRIP_OPEN
    time.sleep(0.3)

    # 4. Lift and go home
    servo_elbow.angle = HOVER_ELBOW
    time.sleep(0.3)

def execute_arm_move(move_uci):
    """Full pick-and-place for a UCI move like 'e7e5'"""
    from_sq = move_uci[:2]  # e.g. 'e7'
    to_sq   = move_uci[2:4]  # e.g. 'e5'
    print(f"\n🦾 Arm moving piece: {from_sq} → {to_sq}")
    pick_up_piece(from_sq)
    place_piece(to_sq)
    arm_home()

# ── VOICE ANNOUNCEMENT ───────────────────────────────────
def speak(text):
    os.system(f'espeak "{text}" 2>/dev/null &')

# ── MAIN GAME LOOP ───────────────────────────────────────
def main():
    board_state = chess.Board()
    engine = chess.engine.SimpleEngine.popen_uci("/usr/games/stockfish")

    # Set difficulty (lower = easier for beginners!)
    engine.configure({"Skill Level": 5})  # 0=beginner, 20=grandmaster

    print("\n╔══════════════════════════════════╗")
    print(  "║  ♟  CHESS ROBOT — Ready to play! ║")
    print(  "╚══════════════════════════════════╝")
    print("Enter moves in UCI format, e.g: e2e4")
    print("Type 'quit' to end the game.\n")
    speak("Chess robot ready. Make your move.")
    arm_home()

    while not board_state.is_game_over():
        print(board_state)
        print(f"\nMove {board_state.fullmove_number} — Your turn (White)")

        # Get player input
        user_input = input("Your move: ").strip().lower()
        if user_input == 'quit':
            speak("Good game! Goodbye.")
            break

        # Validate player move
        try:
            player_move = chess.Move.from_uci(user_input)
            if player_move not in board_state.legal_moves:
                print("⚠️  Illegal move! Try again.")
                continue
        except ValueError:
            print("⚠️  Invalid format. Use format like: e2e4")
            continue

        board_state.push(player_move)
        print(f"✅ Your move: {user_input}")

        if board_state.is_game_over():
            break

        # Stockfish calculates best reply
        result = engine.play(board_state, chess.engine.Limit(time=2.0))
        robot_move = result.move
        board_state.push(robot_move)

        move_str = robot_move.uci()
        from_sq = move_str[:2].upper()
        to_sq   = move_str[2:4].upper()
        print(f"\n🤖 Robot plays: {from_sq} → {to_sq}")
        speak(f"Robot moves {from_sq} to {to_sq}")

        # Physically move the piece on the board!
        execute_arm_move(move_str)

    # Game over
    result = board_state.result()
    print(f"\n🏁 Game over! Result: {result}")
    if result == "1-0":   speak("White wins! Well played human.")
    elif result == "0-1": speak("Black wins! I am victorious!")
    else:                  speak("It is a draw! What a close game.")
    engine.quit()
    pca.deinit()

if __name__ == '__main__':
    main()
📋 Run the robot: Open a terminal on the Pi and type: python3 chess_robot.py Then type your first move like e2e4 and press Enter. Watch the arm move!
Calibration

Calibrating the Arm to Your Board

Every build is slightly different in position and size, so you'll need to tune the servo angles for your exact board. Use this calibration helper script:

#!/usr/bin/env python3
# calibrate.py — Move each servo manually to find correct angles

import board, busio
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo as Servo

i2c = busio.I2C(board.SCL, board.SDA)
pca = PCA9685(i2c)
pca.frequency = 50

servos = [Servo.Servo(pca.channels[i], min_pulse=500, max_pulse=2400) for i in range(4)]
names  = ["Base", "Shoulder", "Elbow", "Gripper"]

print("CALIBRATION MODE — Enter servo number (0-3) and angle (0-180)")
print("Examples: '0 90'  '1 45'  '2 60'")
while True:
    line = input("servo angle > ")
    try:
        s, a = map(int, line.split())
        servos[s].angle = a
        print(f"  {names[s]} → {a}°")
    except:
        print("Try again. Format: servo_num angle")
1
Run python3 calibrate.py and type 0 90 to move the base to 90°. Point the arm toward the a1 corner of the board.
2
Find the angle for each corner. Move to a1, h1, a8, and h8 — note the base and shoulder angles for each corner and update the square_to_angles() function's min/max values.
3
Calibrate the elbow height. Find the elbow angle where the gripper just skims the piece tops, and set DOWN_ELBOW to that value in the main code.
4
Test the gripper. Set GRIP_OPEN to just wide enough for a pawn, and GRIP_CLOSE to snug — not so tight it cracks the piece!
Play

Playing Your First Game

How to enter moves (UCI notation)

UCI (Universal Chess Interface) notation is simply: from-square + to-square. The piece you're moving doesn't matter — you just name the squares.

Classic Opening MoveWhat You TypeWhat It Means
King's Pawn Openinge2e4Pawn from e2 to e4
Queen's Pawn Openingd2d4Pawn from d2 to d4
Knight to f3g1f3Knight from g1 to f3
Bishop to c4f1c4Bishop from f1 to c4
Pawn promotion to queene7e8qPawn to e8, promote to Queen
🎯 Set the difficulty! In the code, find engine.configure({"Skill Level": 5}). Change 5 to anything from 0 (very easy — great for beginners!) up to 20 (grandmaster level — very hard!). Try level 3 for your first game.
a8
b8
c8
d8
e8
f8
g8
h8
a7
b7
c7
d7
e7
f7
g7
h7
e4⭐
a2
b2
c2
d2
e2
f2
g2
h2
a1
b1
c1
d1
e1
f1
g1
h1

⭐ = where e2e4 lands. Every square has a letter (a–h) + number (1–8).

Upgrades

Awesome Upgrades to Try Next

📷
Camera Board Detection

Add a Pi Camera + OpenCV to detect your physical pieces automatically — no typing moves!

🖥️
LCD Move Display

Connect a small OLED screen to show the robot's last move and the current game score.

🎙️
Voice Input

Use speech_recognition and a USB mic to say "e2 to e4" instead of typing.

💡
LED Square Highlights

Put NeoPixel LEDs under each square — light up the piece the robot just moved!

⏱️
Chess Clock

Add a 7-segment display as a real chess clock counting down time for each player.

📱
Phone Remote

Build a simple Flask web server on the Pi so you can enter moves from a phone browser.

♟ You just combined AI, robotics, and chess into one machine.
That's the kind of project engineers spend careers building — and you built yours at home. Keep experimenting! 🤖

Comments

Product Cards
Buddy Bot eBook
⭐ New 2026 Release
Build Your
Own Robot!
3D design, wiring &
Arduino coding.
Young inventors love it!
🖨️
3D Print
All parts
Wire it
Circuit guide
💻
Code it
Arduino IDE
🤖
Watch it
Walk & react
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Website Offer
₹499 300
🌍 International: $5 USD
One-time · Instant digital delivery
🔒 Secured by Razorpay · Your data is safe
📄 Download Free Sample Copy
🔒 Secured by Razorpay · Your data is safe
🍓
Raspberry Pi Pico Mastery
21 Projects
⚡ Launch Price — 80% OFF
Learn Pico
Build 21 Projects!
MicroPython · Wokwi
IoT · Certificate
Perfect for beginners!
🖥️
Wokwi
No hardware
🐍
MicroPy
From zero
🔨
21 Projects
IoT + sensors
📄
Certificate
Verified cert
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Launch Offer
₹999 200 80% OFF
🌍 International: $5 USD
One-time · Lifetime access · No subscription
🔒 Secured by Razorpay · UPI · Cards · NetBanking
🎉

You're in!

Payment successful! Your Buddy Bot eBook is ready. Time to build!

📖 Access Your eBook Now
🎉

Enrolled!

Payment successful! Lifetime access to all 21 Pico Projects is yours!

🍓 Go to My Course