wheel_controller_pid_roboclaw
https://github.com/AkifAkar/wheel_controller_pid_roboclaw
Ethernet-Controlled Wheel Module with W5500 and RoboClaw — wheel_controller_pid_roboclaw
What Is This Project?
wheel_controller_pid_roboclaw is an embedded firmware for a network-controlled wheel module, combining a Raspberry Pi Pico (RP2040), WIZnet W5500 Ethernet controller, and a RoboClaw motor driver.
The core idea is simple: instead of connecting motors to a central controller, each wheel becomes an independent network node with its own IP address. A host system sends UDP commands, and each wheel responds with its own status — encoder position, battery voltage, and current target values.
Typical applications include AGVs (Automated Guided Vehicles), distributed robot platforms, and any system where independent per-wheel control over a network is needed.
Role of the W5500
In this project, the W5500 handles all network communication between the wheel module and the outside world.
The RP2040 does not have built-in wired Ethernet. The W5500 connects via SPI and offloads the entire TCP/IP stack in hardware, so the MCU only needs to deal with socket-level operations. The project uses WIZnet's official ioLibrary_Driver directly, integrated as a submodule under lib/ioLibrary_Driver.
Each wheel module is assigned a unique IP and MAC address. These are not hardcoded per file — they are configured per build target in CMakeLists.txt, so compiling for a different wheel automatically produces a binary with different network settings.
Communication flow:
- Inbound: UDP packets carrying JSON commands (target angle, speed, etc.) → parsed → motor target updated
- Outbound: Periodic UDP packets reporting encoder position, target value, and battery voltage
Software Architecture
The firmware is organized around four loosely coupled responsibilities:
main.c
├── Network layer W5500 init, UDP send/receive (ioLibrary_Driver)
├── Motor layer RoboClaw UART commands, PID position/speed control
├── Sensor layer Encoder reads, battery voltage measurement
└── Protothreads (pt) Lightweight cooperative multithreading
lib/ioLibrary_Driver — WIZnet's official W5500 driver, handling SPI communication and socket management.
lib/Basicmicro — C wrapper for the RoboClaw motor driver, covering velocity commands, position PID, encoder reads, and stop commands.
lib/pt — Protothreads library for cooperative multitasking. Each function (motor control, encoder polling, battery measurement, UDP I/O) runs as a separate logical thread without an RTOS, keeping the firmware lightweight.
CMakeLists.txt — Per-wheel build automation. IP address, MAC address, encoder range, and direction inversion are all set at compile time. Each wheel gets its own binary from a single codebase.
Operational Flow
- Boot — W5500 network init, RoboClaw UART init, Protothread scheduler start
- Receive — UDP JSON command arrives → parsed → motor target value updated
- Control — Target change detected → RoboClaw PID command sent
- Monitor — Encoder and battery voltage sampled periodically
- Report — Current state broadcast via UDP on a fixed interval
Potential Applications
The architecture treats each wheel as an independent, addressable network node — making it applicable wherever distributed motor control over Ethernet is useful.
🤖 AGV / Mobile Robots
Each wheel module runs its own firmware instance with a unique IP. A central controller sends target values over UDP; each wheel handles its own PID loop locally. If one wheel fails, it can be swapped and reflashed without touching the rest of the system.
🏭 Industrial Automation
Conveyor systems, sorting machines, or any multi-axis setup could benefit from this decentralized approach. Instead of routing all motor signals back to one controller, each axis is a self-contained Ethernet node — easier to wire, easier to scale.
🚗 Autonomous Vehicles / Smart Platforms
Four-wheel or multi-wheel drive platforms (like rover-type robots) can assign one firmware instance per wheel. The host can send per-wheel velocity or position targets independently, enabling differential steering or complex motion profiles.
🔬 Research & Prototyping
The codebase is intentionally minimal — Protothreads instead of a full RTOS, UDP instead of a heavy protocol stack. This makes it a clean starting point for robotics research or university projects that need networked motor control without much boilerplate.
🏗️ ODM / OEM Products
The CMake-based per-wheel configuration (IP, MAC, encoder range, direction) means the same codebase can be built into multiple SKUs. Deploying a new wheel variant is a build config change, not a code change — suitable for small-batch production runs.
FAQ
Q. Why UDP instead of TCP?
UDP is used for low-latency command delivery. Motor control is time-sensitive, and the overhead of TCP connection management is unnecessary when the host and wheel modules are on the same local network. Lost packets are tolerable; latency spikes are not.
Q. Why W5500 instead of Wi-Fi?
The W5500 provides a wired, deterministic network connection. In environments with motor noise, metal enclosures, or interference-heavy conditions, wired Ethernet is more reliable than Wi-Fi. The W5500 also offloads the TCP/IP stack in hardware, reducing MCU load.
Q. Can this run more than two wheels at the same time?
Yes. Each wheel is an independent network node. The host can communicate with as many wheels as needed, as long as each has a unique IP and MAC — which are set per build target in CMakeLists.txt.
Q. Does this require an RTOS?
No. The firmware uses Protothreads, a lightweight cooperative multithreading library that runs on bare metal. This keeps memory usage low and avoids RTOS scheduling overhead, which is well-suited for the RP2040's constraints.
Q. Can the W5500 be replaced with another WIZnet chip?
Potentially. The project uses WIZnet's official ioLibrary_Driver, which also supports W5100S and other chips in the WIZnet family. Swapping the chip would primarily require changes to the driver initialization and SPI configuration.
Q. Is the JSON command format documented?
The command structure (target angle, speed, etc.) is defined in the firmware source. It is not yet formally documented in the repository, but the parsing logic in main.c serves as the reference.
Tech Stack Summary
| Item | Details |
|---|---|
| MCU | Raspberry Pi Pico (RP2040) |
| Ethernet | WIZnet W5500 (HW TCP/IP, SPI) |
| Ethernet Driver | WIZnet official ioLibrary_Driver |
| Network Protocol | UDP (JSON command/status) |
| Motor Driver | RoboClaw (UART, PID position/speed) |
| Multitasking | Protothreads (cooperative, no RTOS) |
| Build System | CMake (per-wheel IP/MAC/config automation) |
| Language | C (pico-sdk) |
