Web-based remote control panel for debugging PCA9685 servo drivers on robots.
Project description
PCA9685 Debug Panel
Web-based remote control panel for debugging PCA9685 servo drivers on robots.
⚠️ Security Notice: This tool exposes a web server with no authentication. Only run it on a trusted local network (e.g., your robot's Wi‑Fi). Do not expose it to the public internet.
Description
A lightweight web panel (similar to FTC Dashboard) that runs on your robot and lets you control PCA9685-driven servos from any browser over Wi‑Fi. Supports per-channel angle control with calibration, live device status monitoring, and workspace save/load — so you can tune and debug servos without touching code.
Why? Adjusting servo angles on a robot usually means SSH + manual scripts. This panel gives you a visual UI in the browser with sliders, real-time feedback, and configuration persistence across restarts.
Installing / Getting started
Prerequisites
- Python 3.10+
- A Raspberry Pi (or similar) with I²C enabled and connected to PCA9685, or any machine for UI-only development (mock mode)
Quick setup
Using Pip
# Install from PyPI
pip install pca9685-debugging-panel
# Start the server
pca9685-panel --host 0.0.0.0 --port 8080
Then open http://<robot-ip>:8080 in your browser.
From source
git clone https://github.com/xiaokai-lyk/PCA9685-debugging-panel.git
cd PCA9685-debugging-panel
uv sync
python main.py
On first launch a config.json file is created automatically with default values (I²C address 0x40, 50 Hz, 600–2400 µs pulse range).
Running on a desktop (no hardware)
Use the --mock flag to skip hardware initialisation entirely — all APIs work, the UI is fully interactive, and no real hardware is required for frontend development:
pca9685-panel --mock
Developing
Project structure
PCA9685-debugging-panel/
├── backend/
│ ├── app.py # FastAPI entry point (REST + SSE)
│ ├── pca9685.py # PCA9685 driver (real hardware + optional mock mode)
│ ├── config_store.py # JSON configuration persistence
│ └── schemas.py # Pydantic request/response models
├── frontend/
│ ├── index.html # Single-page UI
│ ├── app.js # SSE connection, REST calls, state management
│ └── styles.css # Dark theme, responsive grid
├── config.json # Auto-generated runtime configuration
├── main.py # Convenience launcher
├── plan.md # Architecture & design decisions
└── pyproject.toml # Project metadata & dependencies
API overview
| Method | Path | Description |
|---|---|---|
GET |
/api/status |
Device status, frequency, I²C address |
GET |
/api/servo/channels |
All 16 channel states |
POST |
/api/servo/set |
Set angle ({channel, angle}) or duty ({channel, duty}) |
POST |
/api/servo/name |
Rename a channel {channel, name} |
POST |
/api/servo/calibrate |
Set angle ↔ pulse calibration |
POST |
/api/pca9685/frequency |
Set PWM frequency {frequency_hz} |
POST |
/api/pca9685/pulse_range |
Set default pulse range |
GET |
/api/workspace/export |
Download full configuration as JSON |
POST |
/api/workspace/import |
Upload & apply a workspace JSON |
GET |
/api/events |
SSE stream for device status pushes |
Interactive docs available at http://<host>:8080/docs (Swagger UI).
Features
- 16-channel servo grid — angle slider / duty-cycle slider per channel, with live pulse-width display
- Per-channel calibration — map your own angle‑to‑pulse ranges for each servo
- Real-time status — device online/offline indicator with heartbeat via SSE
- Frequency control — adjustable 40–400 Hz PWM frequency
- Workspace save/load — export the full configuration (calibration, names, settings) as a JSON file; import it later or on a different robot
- Restart persistence —
config.jsonsurvives reboots so your last setup is restored automatically - Mock mode — run with
--mockflag for UI development & testing without hardware - Dark theme — responsive layout, works on desktop and mobile browsers
Configuration
config.json (auto-managed)
| Key | Type | Default | Description |
|---|---|---|---|
i2c_address |
int |
64 (0x40) |
I²C address of the PCA9685 |
frequency_hz |
float |
50.0 |
PWM frequency (40–400 Hz) |
min_pulse_us |
float |
600.0 |
Default minimum pulse width in µs |
max_pulse_us |
float |
2400.0 |
Default maximum pulse width in µs |
channels |
object |
{} |
Per-channel calibration, name, and last output |
This file is written automatically when settings change — no manual editing needed.
Workspace file (user-managed)
Exported via the UI or GET /api/workspace/export. Contains the same fields plus full per-channel data (calibration, names, current positions). Can be imported on another machine to replicate a setup.
Troubleshooting
Device stays offline — "Hardware init failed: No module named 'RPi'"
This may happen when you are NOT using Raspberry Pi OS.
The Adafruit Blinka library cannot find the GPIO driver for your Raspberry Pi.
# Recommended
pip install rpi-lgpio
# For older OS (not recommended, may involve the compilation of C extensions)
pip install RPi.GPIO
Offline — Hardware init faile2d: No I2C device at address: 0x40
Your PCA9685 might be at a different address. Scan the bus:
sudo apt-get install i2c-tools
i2cdetect -y 1
If it's all -- in the result, please check if the device connection is correct. Make sure the connection is correct and then re-scan.
Then update the address in config.json or via the Settings modal in the UI.
Contributing
If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are welcome.
For major changes, open an issue first to discuss what you would like to change.
Links
- Repository: https://github.com/xiaokai-lyk/PCA9685-debugging-panel
- Issue tracker: https://github.com/xiaokai-lyk/PCA9685-debugging-panel/issues
- Related projects:
Licensing
The code in this project is licensed under the Apache License, Version 2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pca9685_debugging_panel-0.1.0.tar.gz.
File metadata
- Download URL: pca9685_debugging_panel-0.1.0.tar.gz
- Upload date:
- Size: 83.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
593c000664921467ce82926031f9efac7e0fd6daac3ea2c6601db978f6b89437
|
|
| MD5 |
b3c9edc87bebcc41bc6e050b64165f5f
|
|
| BLAKE2b-256 |
5a2a22b93327f1d426d6d80dbdbaad9510fa8ba291cd355df00a3e8e050b31ab
|
File details
Details for the file pca9685_debugging_panel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pca9685_debugging_panel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50ce26b18c61e3736ee109506c9737fe5d9ae2e7dc3c81fddc328dc734de9247
|
|
| MD5 |
c2277fa29091ae32f553d2e7f502a20f
|
|
| BLAKE2b-256 |
ed79e6b2c18ca032a8b4e57624471d51e083919203d2285172ebd8e11ddb065e
|