Add portal web simulator, SPI bridges, and Pico firmware updates.
Bring the five-panel hex portal online with a browser 3D/schematic preview, Pi SPI backends, and renamed multi-panel Pico UDP firmware. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
103
README.md
103
README.md
@@ -1,38 +1,86 @@
|
||||
# portal
|
||||
|
||||
WS2812 LED control for Raspberry Pi 5 and Pico panel adapters.
|
||||
Hexagonal LED portal: five WS2812 matrix panels on Pico UDP adapters, plus a bare floor.
|
||||
|
||||
Reference: [photo of the physical portal](https://technical.kiwi/images/portal/IMG_20241029_220222.jpg) — upright flat-top hex arch, dark frame, red LED grids on each face.
|
||||
|
||||
```
|
||||
___[2]___
|
||||
/ \
|
||||
[1] [3]
|
||||
| |
|
||||
[0] [4]
|
||||
\___________/
|
||||
floor
|
||||
```
|
||||
|
||||
WS2812 control for Raspberry Pi 5 (orchestrator) and Pico panel adapters.
|
||||
|
||||
## Panel IPs
|
||||
|
||||
Five panels on `10.1.1.10`–`10.1.1.14` (panel 0 → `.10`, panel 4 → `.14`). Examples drive **all 5** by default.
|
||||
Five Pico panels on `10.1.1.10`–`10.1.1.14`. Examples drive **all 5** by default.
|
||||
|
||||
## Panel sizes
|
||||
|
||||
Panels are **9 rows** tall; width varies by panel. Edit `PANEL_WIDTH_BY_INDEX` in `leds/array_config.py`:
|
||||
|
||||
| Panel | IP | Size | LEDs | Flash |
|
||||
|-------|-----|------|------|-------|
|
||||
| 0 | 10.1.1.10 | 9×39 | 351 | `make deploy PANEL_ID=0 NUM_LEDS=351` |
|
||||
| 1 | 10.1.1.11 | 9×45 | 405 | `make deploy PANEL_ID=1 NUM_LEDS=405` |
|
||||
| 2 | 10.1.1.12 | 9×45 | 405 | `make deploy PANEL_ID=2 NUM_LEDS=405` |
|
||||
| 3 | 10.1.1.13 | 9×45 | 405 | `make deploy PANEL_ID=3 NUM_LEDS=405` |
|
||||
| 4 | 10.1.1.14 | 9×39? | 351 | `make deploy PANEL_ID=4 NUM_LEDS=351` |
|
||||
| Panel | Face | IP | Size | LEDs | Firmware |
|
||||
|-------|------|-----|------|------|----------|
|
||||
| 0 | bottom-left | 10.1.1.10 | 9×39 | 351 | `make deploy PANEL_ID=0` |
|
||||
| 1 | top-left | 10.1.1.11 | 9×45 | 405 | `make deploy PANEL_ID=1` |
|
||||
| 2 | **top** | 10.1.1.12 | 9×45 | 405 | `make deploy PANEL_ID=2` |
|
||||
| 3 | top-right | 10.1.1.13 | 9×45 | 405 | `make deploy PANEL_ID=3` |
|
||||
| 4 | bottom-right | 10.1.1.14 | 9×39? | 351 | `make deploy PANEL_ID=4` |
|
||||
|
||||
Panels **0→1→2→3→4** run clockwise from bottom-left (`PORTAL_PANEL_ORDER_CLOCKWISE` in `leds/array_config.py`).
|
||||
|
||||
Panel 4 may be **38 or 39** wide — find the exact width:
|
||||
|
||||
```bash
|
||||
make deploy PANEL_ID=4 NUM_LEDS=387 # 43 cols max for probe
|
||||
make deploy PANEL_ID=4
|
||||
pipenv run python examples/panel_sync_test.py --test width --panel-index 4
|
||||
```
|
||||
|
||||
Last column that lights → set `PANEL_WIDTH_BY_INDEX[4]` in `leds/array_config.py` to **column + 1**, then re-flash with `NUM_LEDS=width×9` (342 for 38, 351 for 39).
|
||||
Last column that lights → set `PANEL_WIDTH_BY_INDEX[4]` in `leds/array_config.py` to **column + 1** (342 LEDs for 38, 351 for 39). Firmware takes pixel count from each UDP frame — no re-flash for width changes.
|
||||
|
||||
Animations render at each panel's own width automatically.
|
||||
|
||||
## Examples
|
||||
|
||||
### Portal web simulator
|
||||
|
||||
Preview all five panels in the browser (3D interior view + flat layout map). Uses the same Python animations as the hardware.
|
||||
|
||||
```bash
|
||||
pipenv install fastapi "uvicorn[standard]"
|
||||
pipenv run python examples/portal_simulator.py
|
||||
# open http://localhost:8765/
|
||||
```
|
||||
|
||||
Dev mode (default): **uvicorn reload** for Python changes, **browser auto-reload** when `web/` files change. Disable with `--no-reload` or `--no-browser-reload`.
|
||||
|
||||
Options: `--host 0.0.0.0 --port 8765` to view from another device on the network.
|
||||
|
||||
Open via the simulator URL (`http://…:8765/`) — do not open `index.html` directly from the filesystem (`file://`), or module imports will fail.
|
||||
|
||||
Frontend uses **Web Components** and ES modules under `web/js/`:
|
||||
|
||||
| Module | Role |
|
||||
|--------|------|
|
||||
| `<portal-app>` | Root layout, frame streaming |
|
||||
| `<portal-controls>` | Sidebar settings |
|
||||
| `<portal-viewport>` | Three.js 3D scene |
|
||||
| `<portal-schematic>` | Flat layout map |
|
||||
| `<portal-panel>` | Single LED matrix canvas |
|
||||
|
||||
### Pico panel (UDP)
|
||||
|
||||
WS2812 defaults: **GP28** (strip 0) and **GP27** (strip 1). Override over UDP:
|
||||
|
||||
```bash
|
||||
pipenv run python examples/panel_color_test.py --panel-index 0 --pins 28:405,27:351
|
||||
```
|
||||
|
||||
| Command | What it does |
|
||||
|---------|----------------|
|
||||
| `pipenv run python examples/panel_rgb_cycle.py` | Red / green / blue on all 5 panels |
|
||||
@@ -50,17 +98,40 @@ Single panel only:
|
||||
pipenv run python examples/panel_animations.py --panel-index 1 # 9×45 @ 10.1.1.11
|
||||
```
|
||||
|
||||
### Pi direct (SPI on GPIO 10)
|
||||
### Pi SPI (bench / single matrix)
|
||||
|
||||
Optional local SPI tests via [`rpi5-ws2812`](https://github.com/niklasr22/rpi5-ws2812) on GPIO 10 — not used for the five portal panels.
|
||||
|
||||
405 LEDs need a ~10 KiB SPI frame. Default `spidev` bufsiz (4096) only updates ~169 LEDs — run once:
|
||||
|
||||
```bash
|
||||
pipenv run python examples/setup_spi_bufsiz.py --install # sudo
|
||||
```
|
||||
|
||||
| Command | What it does |
|
||||
|---------|----------------|
|
||||
| `pipenv run python examples/animations.py` | All animations on matrix |
|
||||
| `pipenv run python examples/spi_rgb_test.py` | Red / green / blue over SPI |
|
||||
| `pipenv run python examples/spi_panel_test.py` | Corners, rows, chase — verify all LEDs |
|
||||
| `pipenv run python examples/animations.py` | All animations on local matrix |
|
||||
| `pipenv run python examples/matrix_demo.py` | Rainbow only |
|
||||
| `pipenv run python examples/led_demo.py` | Dual-strip chase + rainbow |
|
||||
|
||||
### Firmware
|
||||
Colors use logical **RGB** everywhere (`(255,0,0)` = red). Pico firmware remaps to **GRB** on the wire; Pi SPI uses the same swap when needed. The web simulator stays logical RGB.
|
||||
|
||||
```python
|
||||
# MicroPython on Pico — this is the reference:
|
||||
np.fill((255, 0, 0)); np.write() # red
|
||||
```
|
||||
|
||||
```bash
|
||||
make deploy PANEL_ID=0 NUM_LEDS=351
|
||||
make monitor
|
||||
pipenv run python examples/panel_rgb_cycle.py # same colors over UDP
|
||||
```
|
||||
|
||||
### Firmware
|
||||
|
||||
Pico SDK sources live under `firmware/pico/` (see that README for the UDP protocol).
|
||||
|
||||
```bash
|
||||
make deploy PANEL_ID=0
|
||||
make reset && make monitor
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user