Files
Adrian A. Baumann 8bdae1da9b Update docs and firmware for ESPHome bridge migration
- Replace gauge.py (MicroPython) references with gaugecontroller.yaml (ESPHome)
- Update CLAUDE.md and README.md to document ESPHome-native API integration
- Update LED wiring docs for separate main/indicator strips (D22/D36)
- Refactor Arduino firmware to drive two WS2812 strips independently
- Add per-gauge physical offset caching for main and indicator LEDs
- Frame-limit breathe effect (16ms) to reduce unnecessary strip refreshes
2026-04-29 19:03:22 +02:00

112 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Upload
Main firmware lives in `Gaugecontroller/Gaugecontroller.ino`. Requires the **FastLED** library (`arduino-cli lib install FastLED`). Use the Arduino IDE or `arduino-cli`:
The ESP32 bridge runs ESPHome; the config is in `gaugecontroller.yaml`.
```bash
# Compile (replace board/port as needed)
arduino-cli compile --fqbn arduino:avr:mega Gaugecontroller
# Upload
arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:avr:mega Gaugecontroller
```
Current default serial setup: `CMD_PORT` and `DEBUG_PORT` both point to `Serial1` at 38400 baud.
## Switching serial ports (debug → production)
Two `#define`s at the top of `Gaugecontroller.ino` control where commands and debug output go:
```cpp
#define CMD_PORT Serial1 // command channel (host sends SET, HOME, etc.)
#define DEBUG_PORT Serial1 // diagnostic prints (homing, boot messages)
```
**Current default:** both point to `Serial1`, so command and debug traffic share Mega pins TX1=18 / RX1=19 at 38400 baud.
**USB-only debug setup:** point both defines back at `Serial` if you want to talk to the sketch over the Arduino USB port instead:
```cpp
#define CMD_PORT Serial
#define DEBUG_PORT Serial
```
At that point the matching `begin()` call in `setup()` also needs to use the same baud rate you expect on the host side.
**Split command/debug ports:** if `CMD_PORT` and `DEBUG_PORT` do not point to the same serial port, `setup()` must initialise both. Right now it only calls:
```cpp
DEBUG_PORT.begin(38400);
```
If you split them, add a second `CMD_PORT.begin(...)` call.
Arduino Mega hardware UARTs for reference:
| Port | TX pin | RX pin |
|---------|--------|--------|
| Serial1 | 18 | 19 |
| Serial2 | 16 | 17 |
| Serial3 | 14 | 15 |
## Architecture
The sketch controls `GAUGE_COUNT` stepper-motor gauges using a trapezoidal velocity profile and a simple text serial protocol.
### Key data structures
- `GaugePins` — hardware pin mapping per gauge (dir, step, enable, active-high/low polarity flags, `ledOrder` string). Declared `constexpr` so `TOTAL_LEDS` can be computed from it at compile time. Configured in the `gaugePins[]` array at the top.
- `Gauge` — per-gauge runtime state: position, target, velocity, accel, homing state machine, sweep mode.
### Motion control (`updateGauge`)
Each call to `updateGauge(id)` in `loop()` computes `dt` since last call and updates velocity using a braking-distance check to produce smooth trapezoidal motion. Steps are accumulated as floating-point and emitted via `doStep` when the accumulator crosses ±1.
### Homing sequence (`updateHoming`)
State machine: `HS_START → HS_BACKING → HS_SETTLE → HS_DONE → HS_IDLE`.
Backs up `homingBackoffSteps` at `homingSpeed`, waits 100 ms settle, then declares `currentPos = 0`. No physical end-stop is used; homing is purely time/step-count based.
### Sweep mode
When `sweepEnabled`, `updateSweepTarget` bounces `targetPos` between `minPos` and `maxPos` autonomously.
### LED strip
Two LED strips are driven: main backlight/status LEDs on `LED_DATA_PIN` (currently 22) and dial indicator LEDs on `INDICATOR_LED_DATA_PIN` (currently 36). The serial protocol still exposes one logical per-gauge LED segment: `0-2` backlight, `3-4` indicators, `5-6` status. `gaugePins[i].ledOrder` is a per-LED type string (one char per LED, `'G'` = GRB-ordered, `'R'` = RGB-ordered) and its length defines the logical LED count. `TOTAL_LEDS`, `TOTAL_MAIN_LEDS`, and `TOTAL_INDICATOR_LEDS` are computed at compile time. Per-gauge logical and physical offsets are cached in `setup()`. LED writes dirty only their physical strip, and the loop flushes each FastLED controller independently with `showLeds()`.
### Serial command protocol
Commands arrive as newline-terminated ASCII lines. Each `parse*` function in `processLine` handles one command family:
| Command | Syntax | Effect |
|---|---|---|
| `SET` | `SET <id> <pos>` | Move gauge to absolute step position |
| `SPEED` | `SPEED <id> <steps/s>` | Set max speed |
| `ACCEL` | `ACCEL <id> <steps/s²>` | Set acceleration |
| `ENABLE` | `ENABLE <id> <0\|1>` | Enable/disable driver output |
| `ZERO` | `ZERO <id>` | Mark current position as home without moving |
| `HOME` | `HOME <id>` / `HOMEALL` | Run homing sequence |
| `SWEEP` | `SWEEP <id> <accel> <speed>` | Start sweep (0/0 stops) |
| `POS?` | `POS?` | Query all gauges: `POS <id> <cur> <tgt> <homed> <homingState> <sweep>` |
| `LED` | `LED <id> <idx> <r> <g> <b>` | Set one LED (0-based index within gauge segment) to RGB colour (0255 each); `<idx>` may be a range `N-M` to set LEDs N through M in one command; also stops any active effect on those LEDs |
| `LED?` | `LED?` | Query all LEDs: one `LED <id> <idx> <r> <g> <b>` line per LED, then `OK` |
| `BLINK` | `BLINK <id> <idx> <on_ms> <off_ms> <r> <g> <b>` | Blink LED(s) at given colour; `<idx>` may be a range `N-M`; `on_ms`/`off_ms` both 0 stops blinking. 4-arg form (no colour) uses current LED colour |
| `BREATHE` | `BREATHE <id> <idx> <period_ms> <r> <g> <b>` | Smooth triangle-wave fade between black and the given colour; `<idx>` may be a range `N-M` |
| `DFLASH` | `DFLASH <id> <idx> <r> <g> <b>` | Two quick flashes (100 ms on/off each) followed by a 700 ms pause, then repeats; `<idx>` may be a range `N-M` |
| `PING` | `PING` | Responds `PONG` |
All commands reply `OK` or `ERR BAD_ID` / `ERR BAD_CMD` etc.
### Adding gauges
1. Increment `GAUGE_COUNT`.
2. Add a `constexpr GaugePins` entry to `gaugePins[]` (including the `ledOrder` string — one char per LED, `'G'` for GRB or `'R'` for RGB).
3. Tune `maxPos` and `homingBackoffSteps` in the corresponding `Gauge` default or at runtime.
4. `TOTAL_LEDS`, `gaugeLedOffset[]`, and `gaugeLedCount[]` update automatically — no manual changes needed.