4.2 KiB
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. No external libraries required on the Stepper-Only branch. Use the Arduino IDE or arduino-cli:
The ESP32 bridge runs ESPHome; the config is in gaugecontroller.yaml.
# 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 Serial (USB) at 38400 baud.
Switching serial ports (debug → production)
Two #defines at the top of Gaugecontroller.ino control where commands and debug output go:
#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 Serial (USB), so command and debug traffic go over the Arduino USB port 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:
#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:
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
GaugeConfig— compile-time config per gauge: pin assignments (dir, step, enable, polarity flags) and motion defaults (minPos, maxPos, homingBackoffSteps, maxSpeed, accel, homingSpeed). All gauges are defined ingauge_config.hasconstexpr GaugeConfig gaugeConfigs[].GAUGE_COUNTis derived automatically from the array length.Gauge— per-gauge runtime state: position, target, velocity, accel, homing state machine, sweep mode. Initialised fromgaugeConfigs[]insetup().
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.
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> |
CFG? |
CFG? |
Query all gauges: CFG <id> <maxSpeed> <accel> per gauge |
PING |
PING |
Responds PONG |
All commands reply OK or ERR BAD_ID / ERR BAD_CMD etc.
Adding gauges
- Open
Gaugecontroller/gauge_config.hand append one row togaugeConfigs[]. GAUGE_COUNTupdates automatically — no other changes needed.