PCA9685 Debug Panel
Web-based remote control panel for debugging PCA9685 servo drivers on robots.
⚠️ Security Notice: By default, this tool starts with no authentication. For shared networks, use
--auth-token <token>to require a shared secret for write operations (POST/DELETE). The token is sent over unencrypted HTTP and has no brute-force protection — use on trusted networks only. Never expose the panel to the public internet.
Vedio Demonstration
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
From GitHub Releases
Each release includes a pre-built .whl file as an attachment. Download it and install directly:
pip install pca9685_debugging_panel-0.2.0-py3-none-any.whl
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
Protecting write operations
To require a shared secret token for all write operations (POST/DELETE), use the --auth-token flag:
pca9685-panel --auth-token my-secret-token
The browser will show a login overlay; enter the same token to unlock the panel. Read operations (status, channel polling, SSE events) remain public so you can still monitor the device without authentication.
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 |
POST |
/api/output/global |
Master switch: enable/disable all channels {enabled} |
POST |
/api/output/channel |
Enable/disable a single channel {channel, enabled} |
GET |
/api/workspace/export |
Download full configuration as JSON |
POST |
/api/workspace/import |
Upload & apply a workspace JSON |
POST |
/api/config/clear |
Reset all config to factory defaults |
GET |
/api/actions |
List all saved action records |
POST |
/api/actions/record |
Save current positions as a named action {name} |
POST |
/api/actions/{index}/play |
Replay a saved action (restore all channel positions) |
DELETE |
/api/actions/{index} |
Delete a saved action |
POST |
/api/actions/{index}/rename |
Rename a saved action {name} |
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.
Release files for pca9685-debugging-panel 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pca9685_debugging_panel-0.2.1.tar.gz | 95.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pca9685_debugging_panel-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 136.5 kB
Release files / pca9685_debugging_panel-0.2.1.tar.gz
| Download URL | pca9685_debugging_panel-0.2.1.tar.gz |
|---|---|
| Size | 95.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a83967035c9a2b73c36cf58e1b4db6057506ad6097dd4a9e2980d272dd649348
|
|
BLAKE2b-256 checksum How to use checksums |
7fb1e8e983cfb77d38df29a4e6030ece38386ef1c78a1fb4df554e745aeb7f27
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","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}
|
Release files / pca9685_debugging_panel-0.2.1-py3-none-any.whl
| Download URL | pca9685_debugging_panel-0.2.1-py3-none-any.whl |
|---|---|
| Size | 41.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a8873c58d8e3b9742fd8371bd18d8fb38ba35fc1bcdd44a18551be6f5d8fa709
|
|
BLAKE2b-256 checksum How to use checksums |
49cb595a01eb73cfb61a6d8476d8ab954b10dc04e78fee5ad6652a20f63696c6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","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}
|