Describes the two-part refactor: gauge_config.h for centralised pin and motion defaults, and uniform sscanf parsing across all parse* functions.
5.1 KiB
5.1 KiB
Gaugecontroller v2.0 Design
Date: 2026-05-21
Branch: Stepper-Only
Scope: Code quality / architecture — same features, better structure. No behaviour change.
Goal
Eliminate scattered magic constants and inconsistent parsing patterns. A developer adding or tuning a gauge should only need to edit one file.
What is NOT changing
- ISR logic, Q16 fixed-point stepping, trapezoidal velocity profile
- Serial protocol commands and responses
- Runtime
Gaugestruct fields (stayfloatfor velocity, speed, accel) - LED code (absent on this branch; out of scope)
Section 1: gauge_config.h
Create Gaugecontroller/gauge_config.h alongside the sketch.
New struct
struct GaugeConfig {
// Hardware
uint8_t dirPin;
uint8_t stepPin;
int8_t enablePin; // -1 = no enable pin
bool dirInverted;
bool stepActiveHigh;
bool enableActiveLow;
// Motion defaults (integers — cast to float in setup())
long minPos;
long maxPos;
long homingBackoffSteps;
int maxSpeed; // steps/s
int accel; // steps/s²
int homingSpeed; // steps/s
};
Config table
constexpr GaugeConfig gaugeConfigs[] = {
// dir step en dirInv stepHi enLow min max backoff speed accel homeSpd
{ 48, 49, -1, false, true, true, 0, 3780, 3800, 4000, 6000, 500 },
{ 8, 9, -1, true, true, true, 0, 3780, 3800, 4000, 6000, 500 },
{ 52, 53, -1, false, true, true, 0, 3780, 3800, 4000, 6000, 500 },
{ 50, 51, -1, false, true, true, 0, 3780, 3800, 4000, 6000, 500 },
};
static const uint8_t GAUGE_COUNT =
sizeof(gaugeConfigs) / sizeof(gaugeConfigs[0]);
Adding gauge 5 is one new table row. GAUGE_COUNT updates automatically.
Changes to Gaugecontroller.ino
- Remove
constexpr GaugePins gaugePins[],struct GaugePins, and the hardcodedGAUGE_COUNT. - Add
#include "gauge_config.h". - In
setup(), initialise eachGauge's motion defaults fromgaugeConfigs[i]:
gauges[i].minPos = gaugeConfigs[i].minPos;
gauges[i].maxPos = gaugeConfigs[i].maxPos;
gauges[i].homingBackoffSteps = gaugeConfigs[i].homingBackoffSteps;
gauges[i].maxSpeed = (float)gaugeConfigs[i].maxSpeed;
gauges[i].accel = (float)gaugeConfigs[i].accel;
gauges[i].homingSpeed = (float)gaugeConfigs[i].homingSpeed;
- All existing references to
gaugePins[i].dirPinetc. becomegaugeConfigs[i].dirPinetc. (field names are identical). - Remove the hardcoded default initialisers from the
Gaugestruct definition (maxPos = 3780,homingBackoffSteps = 3800,maxSpeed = 4000.0f,accel = 6000.0f,homingSpeed = 500.0f,minPos = 0). These fields become zero-initialised and are then set fromgaugeConfigs[i]insetup(), eliminating the risk of the struct defaults and config table silently diverging.
Section 2: Uniform sscanf parsing
Three parse* functions currently use manual indexOf/substring. Convert them to sscanf to match the rest of the parser.
parseSpeed
bool parseSpeed(const String& line) {
int id; float speed;
if (sscanf(line.c_str(), "SPEED %d %f", &id, &speed) == 2) {
if (id < 0 || id >= GAUGE_COUNT) { sendReply("ERR BAD_ID"); return true; }
if (speed <= 0.0f) { sendReply("ERR BAD_SPEED"); return true; }
gauges[id].maxSpeed = speed;
sendReply("OK");
return true;
}
return false;
}
parseAccel
bool parseAccel(const String& line) {
int id; float accel;
if (sscanf(line.c_str(), "ACCEL %d %f", &id, &accel) == 2) {
if (id < 0 || id >= GAUGE_COUNT) { sendReply("ERR BAD_ID"); return true; }
if (accel <= 0.0f) { sendReply("ERR BAD_ACCEL"); return true; }
gauges[id].accel = accel;
sendReply("OK");
return true;
}
return false;
}
parseSweep
bool parseSweep(const String& line) {
int id; float accel, speed;
if (sscanf(line.c_str(), "SWEEP %d %f %f", &id, &accel, &speed) == 3) {
if (id < 0 || id >= GAUGE_COUNT) { sendReply("ERR BAD_ID"); return true; }
Gauge& g = gauges[id];
if (accel <= 0.0f || speed <= 0.0f) {
g.sweepEnabled = false;
g.velocity = 0.0f;
stopTimerStepping(id);
sendReply("OK");
return true;
}
g.accel = accel;
g.maxSpeed = speed;
g.sweepEnabled = true;
g.sweepTowardMax = true;
atomicWriteLong(g.targetPos, g.maxPos);
sendReply("OK");
return true;
}
return false;
}
No change to accepted syntax, error codes, or response format.
File inventory
| File | Change |
|---|---|
Gaugecontroller/gauge_config.h |
New — all pin + motion defaults |
Gaugecontroller/Gaugecontroller.ino |
Remove GaugePins, add include, update setup(), rewrite 3 parsers |
Success criteria
- Sketch compiles cleanly with
arduino-cli compile --fqbn arduino:avr:mega Gaugecontroller GAUGE_COUNTneed not be edited when adding a gauge — onlygaugeConfigs[]changes- No
indexOf/substringremain in anyparse*function - All existing protocol commands behave identically to v1