2PyBot is a self-balancing wheeled robot built around the ESP32 microcontroller. It uses stepper motors for precise actuation, a 6-axis IMU fused with a Mahony AHRS filter for orientation estimation, and an ESP-NOW wireless link to a custom joystick transmitter. A Python desktop dashboard provides real-time telemetry and live PID tuning over Bluetooth.
2PyBot/
├── firmware/
│ ├── BaseLink/ # Robot (receiver) firmware
│ │ ├── BaseLink.ino
│ │ ├── config.h
│ │ ├── imu_sensor.h / .cpp
│ │ ├── stepper_control.h / .cpp
│ │ ├── pid_controller.h
│ │ ├── espnow_comm.h
│ │ ├── serial_tuner.h
│ │ ├── system_architecture.md # Inline architecture reference
│ │ └── tuner.html # Web Bluetooth PID tuner
│ └── Controller/ # Joystick transmitter firmware
│ └── Controller.ino
├── gui/ # Desktop control & telemetry software
│ └── robot_controller_ui.py
├── hardware/ # PCB schematics and BOM (KiCad)
├── models/ # 3D CAD files (STEP / GLB)
├── assets/ # Media: demo videos, photos, renders
├── docs/
│ ├── BaseLink/ # Robot-side technical documentation
│ │ ├── System_Architecture.md
│ │ ├── PID_Theory_and_Math.md
│ │ ├── Config_and_Tuning_Guide.md
│ │ ├── Troubleshooting_Guide.md
│ │ ├── Program_Flow_State_Machine.md
│ │ └── Project_History.md
│ └── Controller/ # Transmitter-side documentation
│ └── System_Architecture.md
└── README.md
The main control loop runs at 200 Hz (dt = 5 ms). On each tick:
- The IMU (ISM6HG256x) is read and fused through a Mahony AHRS filter to produce a drift-corrected pitch angle.
- A Balance PID controller computes a target stepper speed proportional to the deviation from the equilibrium angle.
- An optional Heading PID loop corrects yaw drift using magnetometer feedback (QMC5883L).
Motor stepping is handled entirely in a 20 kHz hardware timer ISR, independent of the main loop. This produces jitter-free, precise pulses to the TMC2208 stepper drivers without relying on delay() or blocking calls. Bresenham-style accumulators are used to generate non-integer step rates accurately.
The Controller firmware runs on a second ESP32 fitted with a joystick and buttons. It transmits a structured packet over ESP-NOW at low latency to the robot. The packet encodes a target pitch offset (in degrees), allowing the robot's control law to translate operator intent directly into a lean angle.
The robot streams telemetry packets over Bluetooth serial. Two interfaces are provided for interaction:
robot_controller_ui.py- A Python desktop dashboard for real-time telemetry plots and control input.tuner.html- A browser-based Web Bluetooth interface for on-the-fly PID constant adjustment.
| File | Role |
|---|---|
BaseLink.ino |
Main entry point; loop timing and state orchestration |
config.h |
All tunable constants: PID gains, pin assignments, motor specs |
imu_sensor.h / .cpp |
IMU initialization, DMP/raw read, Mahony filter integration |
stepper_control.h / .cpp |
ISR-driven step generation, velocity ramping, direction control |
pid_controller.h |
Generic PID template used by balance and heading loops |
espnow_comm.h |
ESP-NOW peer registration, packet parsing, and callback handler |
serial_tuner.h |
Bluetooth serial command parser for live PID adjustment |
gui/robot_controller_ui.py |
Python telemetry dashboard (PySerial + Matplotlib) |
firmware/BaseLink/tuner.html |
Web Bluetooth PID tuner, no installation required |
All technical write-ups are in docs/.
| Document | Description |
|---|---|
| System Architecture | Control loop design, module interactions, and data flow |
| PID Theory and Math | Derivation and implementation of the balance and heading loops |
| Config and Tuning Guide | Step-by-step instructions for calibrating and tuning gains |
| Program Flow & State Machine | Boot sequence, operational states, and fault handling |
| Troubleshooting Guide | Diagnosis of common issues: oscillation, drift, crashes |
| Project History | Revision log and design evolution |
| Controller Architecture | Transmitter packet structure and joystick mapping |
- Open
firmware/BaseLink/BaseLink.inoin the Arduino IDE. - Review
config.hand set pin assignments and motor parameters for your hardware. - Install required libraries (see
config.hheader comments for the full list). - Flash to the robot ESP32.
- Open
firmware/Controller/Controller.ino. - Set the robot's MAC address in the ESP-NOW peer configuration.
- Flash to the transmitter ESP32.
cd gui
pip install pyserial matplotlib
python robot_controller_ui.pyPair the robot over Bluetooth before launching the dashboard. The COM port can be configured at the top of the script.
PCB design files (KiCad) and the bill of materials are located in hardware/. 3D printable chassis files are in models/.
Key components:
- ESP32 (×2 — robot and transmitter)
- TMC2208 stepper motor drivers (×2)
- NEMA 17 stepper motors (×2)
- ISM6HG256x IMU breakout (Custom PCB)
- QMC5883L magnetometer
- MP1584 Buck Converter (12V-5V)
- 3S Li-Ion Battery
- XT-60 Male-Female Pair
- Slide Switch
- Standoffs, Screws
- Zero PCB
- Nema17 Motor Bracket
- Robot Wheels (Big diameter is better)
Demo footage and build photos are in assets/.
| Asset | Description |
|---|---|
| Demo Video | Robot balancing and driving under remote control |
| Build Photo | Assembled hardware with electronics visible |
| Dashboard Screenshot | Python telemetry dashboard during a live session |
Self-balancing robotics project — open for reference and research use.