---
title: "wheel_controller_pid_roboclaw"
url: "https://maker.wiznet.io/Grace_Koo/projects/wheel-controller-pid-roboclaw/"
markdown_url: "https://maker.wiznet.io/Grace_Koo/projects/wheel-controller-pid-roboclaw/md"
type: "UCC: User Created Content"
author: "AkifAkar"
author_url: "https://github.com/AkifAkar/wheel_controller_pid_roboclaw"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "AkifAkar"
original_url: "https://github.com/AkifAkar/wheel_controller_pid_roboclaw"
published: "2026-04-30"
language: "en"
likes: 0
views: 277
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# wheel_controller_pid_roboclaw

> https://github.com/AkifAkar/wheel_controller_pid_roboclaw

Original author: AkifAkar (source: https://github.com/AkifAkar/wheel_controller_pid_roboclaw)

## Article

## 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:

```plaintext
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

1. **Boot** — W5500 network init, RoboClaw UART init, Protothread scheduler start

2. **Receive** — UDP JSON command arrives → parsed → motor target value updated

3. **Control** — Target change detected → RoboClaw PID command sent

4. **Monitor** — Encoder and battery voltage sampled periodically

5. **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) |

---

> **Project:** [github.com/AkifAkar/wheel_controller_pid_roboclaw](https://github.com/AkifAkar/wheel_controller_pid_roboclaw)

---

Source: https://maker.wiznet.io/Grace_Koo/projects/wheel-controller-pid-roboclaw/
