5.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build & Upload
This is a single-file Arduino sketch (Gaugecontroller.ino). Requires the FastLED library (arduino-cli lib install FastLED). Use the Arduino IDE or arduino-cli:
# Compile (replace board/port as needed)
arduino-cli compile --fqbn arduino:avr:mega Gaugecontroller.ino
# Upload
arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:avr:mega Gaugecontroller.ino
Serial monitor: 115200 baud (Serial is both CMD_PORT and DEBUG_PORT).
Switching serial ports (debug → production)
Two #defines at the top of Gaugecontroller.ino control where commands and debug output go:
#define CMD_PORT Serial // command channel (host sends SET, HOME, etc.)
#define DEBUG_PORT Serial // diagnostic prints (homing, boot messages)
Debug / USB-only (default): both point to Serial (the USB-CDC port). Connect via minicom or the Arduino IDE serial monitor at 115200 baud.
Production (hardware UART): change CMD_PORT to a hardware serial port so a host MCU or Raspberry Pi can drive it without occupying the USB port:
#define CMD_PORT Serial1 // TX1=pin18, RX1=pin19
#define DEBUG_PORT Serial // keep USB for monitoring, or silence it (see below)
Arduino Mega hardware UARTs:
| Port | TX pin | RX pin |
|---|---|---|
| Serial1 | 18 | 19 |
| Serial2 | 16 | 17 |
| Serial3 | 14 | 15 |
setup() calls DEBUG_PORT.begin(115200) only. If CMD_PORT differs from DEBUG_PORT you must also begin it — add a second begin call in setup():
CMD_PORT.begin(115200);
Silencing debug output entirely: point DEBUG_PORT at a null stream, or wrap all DEBUG_PORT calls in an #ifdef DEBUG guard. The simplest option is to replace the define with a no-op object, but the easiest production approach is just to leave DEBUG_PORT Serial and ignore the USB output.
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,ledCount). DeclaredconstexprsoTOTAL_LEDScan be computed from it at compile time. Configured in thegaugePins[]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
One shared WS2812B strip is driven from LED_DATA_PIN (default 6). Each gauge owns a contiguous segment of the strip; gaugePins[i].ledCount sets the segment length (0 = no LEDs). TOTAL_LEDS is computed at compile time via constexpr sumLedCounts() — no manual constant to keep in sync. Per-gauge offsets into the flat leds[] array are computed once in setup() into gaugeLedOffset[]. FastLED.show() is called immediately after each LED command.
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 (0–255 each); <idx> may be a range N-M to set LEDs N through M in one command |
LED? |
LED? |
Query all LEDs: one LED <id> <idx> <r> <g> <b> line per LED, then OK |
PING |
PING |
Responds PONG |
All commands reply OK or ERR BAD_ID / ERR BAD_CMD etc.
Adding gauges
- Increment
GAUGE_COUNT. - Add a
constexpr GaugePinsentry togaugePins[](includingledCount). - Tune
maxPosandhomingBackoffStepsin the correspondingGaugedefault or at runtime. TOTAL_LEDSandgaugeLedOffset[]update automatically — no manual changes needed.