A robotic Connect 4 game where a MyCobot 280 robot arm plays against a human player. The system uses drop detection via LED strip photoresistors, automated puck dispensing with solenoids, and PascalPons's connect 4 solver for the AI.
the installation assumes you're using a RaspberryPi for the pc.
chmod +x setup.sh && ./setup.sh- go to
arduino_controllerand burn the code onto an arduino nano. the rest of the setup (connectors etc.) will be described in the DRIVE FOLDER under electronics.
serial_middleman.py- lets you inject commands to the arduino from the pc and vice versa, for testing.
┌───────────────────────────────────┐
│ PC MAIN CONTROLLER │
│ ┌────────────┬────────────┐ │
│ │ Robot │ Arduino │ │
│ │ Interface │ Interface │ │
│ └────────────┴────────────┘ │
└─────────────┬──────┬──────────────┘
│ │
USB Serial USB Serial
│ │
┌────────▼─┐ ┌───▼────────────┐
│ Robot │ │ Arduino │
│ Arm │ │ - LED Strip │
│ (via │ | - Solenoids │
│pymycobot)│ │ - Robot Pump |
└──────────┘ └────────────────┘
The system consists of three main controllers:
- PC Main Controller - Orchestrates gameplay, runs AI, manages state. Located at connect4_engine.
- Arduino Controller - Handles LED strip, solenoid puck release, drop detection sensors, pump activation
- MyCobot 280 Robot Arm - Picks pucks from stack and places them in columns (using arduino pump), delivers pucks to player at dropoff location.
classDiagram
class IArduino {
<<interface>>
+set_on_puck_dropped_callback()
+set_game_start_callback()
+reset()
}
class IRobot {
<<interface>>
+drop_piece(column, puck_no)
+give_player_puck(puck_no)
+reset()
}
class ArduinoCommunicator {
+read_loop()
+send_message()
}
class ArduinoDummy {
+puck_dropped_in_col()
}
class RobotCommunicator {
+drop_piece()
+give_player_puck()
%% Arm positions come from coords.json, calibrated via
%% scripts/calibrate_robot_locations.py before use
}
class RobotDummy
class AIPascalPons {
+choose_move(board)
%% Wraps c4solver binary via subprocess (stdin/stdout)
}
class Board {
+drop_piece()
+is_player_winner()
+is_draw()
}
class Connect4Game {
+game_start()
+piece_dropped_in_board()
+ai_turn()
+game_over()
}
IArduino <|-- ArduinoCommunicator : implements
IArduino <|-- ArduinoDummy : implements (mock)
IRobot <|-- RobotCommunicator : implements
IRobot <|-- RobotDummy : implements (mock)
Connect4Game --> IArduino : uses
Connect4Game --> IRobot : uses
Connect4Game --> Board : owns
Connect4Game --> AIPascalPons : owns
RobotCommunicator --> IArduino : uses (pump control)
Calibration note:
RobotCommunicatordrives arm movement purely by joint angles stored inangles.json. Before running the full game, runscripts/calibrate_robot_locations.pyto interactively adjust and save those positions — without this step the arm won't reach puck stacks or board columns accurately.
- Responsibilities: Orchestrate turns, check win/draw, trigger robot moves
- Event Handler:
on_player_drop(column)- called when Arduino detects puck - Flow: Player drops → Update board → Check win → Calculate AI move → Execute robot → Repeat
- Responsibilities: Store state, validate moves, detect wins
- Pure Logic: No hardware dependencies, easily testable
- API:
drop_piece(),is_valid_move(),check_win(),is_draw(),get_state()
- Algorithm: Minimax with alpha-beta pruning (fully solved game)
- Input: Board state as 2D array
- Output: scores describing which puck drop from last will place the winning puck. positive score for the current player's win, negative for opponent. (see article for details).
- Responsibilities: Serial communication, command sending, event callbacks
- Commands:
OPEN <col>,CLOSE,LED [ON/OFF/STROBE],RESET <BOARD_STATE> - Events:
DROP <col>(puck detected),START(user pressed btn),LOG <msg>(general logging) - Thread Model: Background listener thread for async event handling
- moves robot to specified locations calibrated from
system_tests\calibrate_robot_locations.py, using angle coords exclusively to make sure movements are deterministic.
- Purpose: Enable development/testing without physical hardware
- Classes:
MockArduino,MockRobot - note: not fully supported anymore since we started testing on the full robot.
- System initializes and robot moves to home position
- Robot gives yellow puck to player at pickup location
- Player drops puck in any column (detected by LED strip sensor)
- PC calculates best move and robot executes (picks red puck, drops in column)
- Robot returns and gives next yellow puck to player
- Repeat until someone wins, board is full or player long presses reset button.
- System displays winner via XXX??? and resets for new game