3 Gauges, routines switched
This commit is contained in:
@@ -2,31 +2,30 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <FastLED.h>
|
#include <FastLED.h>
|
||||||
|
|
||||||
static const uint8_t GAUGE_COUNT = 2;
|
static const uint8_t GAUGE_COUNT = 3;
|
||||||
|
|
||||||
// LED strip — one shared WS2812B strip, segmented per gauge.
|
// One shared WS2812B strip, split into per-gauge segments.
|
||||||
// Set LED_DATA_PIN to the digital pin driving the strip data line.
|
|
||||||
// TOTAL_LEDS is computed automatically from gaugePins[].ledCount.
|
|
||||||
static const uint8_t LED_DATA_PIN = 22;
|
static const uint8_t LED_DATA_PIN = 22;
|
||||||
|
|
||||||
// For now: commands come over USB serial
|
// For now, command and debug traffic share the same serial port.
|
||||||
#define CMD_PORT Serial1
|
#define CMD_PORT Serial1
|
||||||
#define DEBUG_PORT Serial1
|
#define DEBUG_PORT Serial1
|
||||||
|
|
||||||
struct GaugePins {
|
struct GaugePins {
|
||||||
uint8_t dirPin;
|
uint8_t dirPin;
|
||||||
uint8_t stepPin;
|
uint8_t stepPin;
|
||||||
int8_t enablePin; // -1 if unused
|
int8_t enablePin; // -1 means there is no enable pin
|
||||||
bool dirInverted;
|
bool dirInverted;
|
||||||
bool stepActiveHigh;
|
bool stepActiveHigh;
|
||||||
bool enableActiveLow;
|
bool enableActiveLow;
|
||||||
uint8_t ledCount; // WS2812B LEDs on this gauge's strip segment (0 if none)
|
uint8_t ledCount; // LEDs assigned to this gauge
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr GaugePins gaugePins[GAUGE_COUNT] = {
|
constexpr GaugePins gaugePins[GAUGE_COUNT] = {
|
||||||
// dir, step, en, dirInv, stepHigh, enActiveLow, leds
|
// dir, step, en, dirInv, stepHigh, enActiveLow, leds
|
||||||
{50, 51, -1, false, true, true, 7}, // Gauge 0
|
{50, 51, -1, false, true, true, 7}, // Gauge 0
|
||||||
{8, 9, -1, true, true, true, 7}, // Gauge 1
|
{8, 9, -1, true, true, true, 7}, // Gauge 1
|
||||||
|
{52, 53, -1, false, true, true, 7}, // Gauge 2
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr uint8_t sumLedCounts(uint8_t i = 0) {
|
constexpr uint8_t sumLedCounts(uint8_t i = 0) {
|
||||||
@@ -47,8 +46,8 @@ struct Gauge {
|
|||||||
long targetPos = 0;
|
long targetPos = 0;
|
||||||
|
|
||||||
long minPos = 0;
|
long minPos = 0;
|
||||||
long maxPos = 3780; // adjust to your usable travel
|
long maxPos = 3780;
|
||||||
long homingBackoffSteps = 3800; // should exceed reverse travel slightly
|
long homingBackoffSteps = 3800; // Deliberately a touch past full reverse travel.
|
||||||
|
|
||||||
float velocity = 0.0f;
|
float velocity = 0.0f;
|
||||||
float maxSpeed = 5000.0f;
|
float maxSpeed = 5000.0f;
|
||||||
@@ -77,14 +76,11 @@ struct BlinkState {
|
|||||||
LedFx fx = FX_BLINK;
|
LedFx fx = FX_BLINK;
|
||||||
CRGB onColor;
|
CRGB onColor;
|
||||||
unsigned long lastMs = 0;
|
unsigned long lastMs = 0;
|
||||||
// FX_BLINK
|
|
||||||
uint16_t onMs = 500;
|
uint16_t onMs = 500;
|
||||||
uint16_t offMs = 500;
|
uint16_t offMs = 500;
|
||||||
bool currentlyOn = false;
|
bool currentlyOn = false;
|
||||||
// FX_BREATHE: smooth triangle-wave fade
|
|
||||||
uint16_t periodMs = 2000;
|
uint16_t periodMs = 2000;
|
||||||
uint16_t cyclePos = 0;
|
uint16_t cyclePos = 0;
|
||||||
// FX_DFLASH: two quick flashes then pause
|
|
||||||
uint8_t dphase = 0;
|
uint8_t dphase = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,6 +166,7 @@ void updateHoming(uint8_t id) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case HS_START:
|
case HS_START:
|
||||||
|
// No endstop here; homing just walks back far enough to hit the hard stop.
|
||||||
g.velocity = 0.0f;
|
g.velocity = 0.0f;
|
||||||
g.stepAccumulator = 0.0f;
|
g.stepAccumulator = 0.0f;
|
||||||
g.homingStepsRemaining = g.homingBackoffSteps;
|
g.homingStepsRemaining = g.homingBackoffSteps;
|
||||||
@@ -266,6 +263,7 @@ void updateGauge(uint8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float dir = (error > 0) ? 1.0f : (error < 0 ? -1.0f : 0.0f);
|
float dir = (error > 0) ? 1.0f : (error < 0 ? -1.0f : 0.0f);
|
||||||
|
// Basic trapezoidal profile: brake if the remaining travel is shorter than the stop distance.
|
||||||
float brakingDistance = (g.velocity * g.velocity) / (2.0f * g.accel + 0.0001f);
|
float brakingDistance = (g.velocity * g.velocity) / (2.0f * g.accel + 0.0001f);
|
||||||
|
|
||||||
if ((float)labs(error) <= brakingDistance) {
|
if ((float)labs(error) <= brakingDistance) {
|
||||||
@@ -286,6 +284,7 @@ void updateGauge(uint8_t id) {
|
|||||||
g.velocity = dir * 5.0f;
|
g.velocity = dir * 5.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Integrate fractional steps until there is enough to emit a real pulse.
|
||||||
g.stepAccumulator += g.velocity * dt;
|
g.stepAccumulator += g.velocity * dt;
|
||||||
|
|
||||||
while (g.stepAccumulator >= 1.0f) {
|
while (g.stepAccumulator >= 1.0f) {
|
||||||
@@ -565,9 +564,7 @@ bool parseLed(const String& line) {
|
|||||||
bool parseBlink(const String& line) {
|
bool parseBlink(const String& line) {
|
||||||
int id, onMs, offMs, r, g, b;
|
int id, onMs, offMs, r, g, b;
|
||||||
char idxToken[16];
|
char idxToken[16];
|
||||||
// Accept both forms:
|
// Optional RGB values let BLINK either reuse or replace the current colour.
|
||||||
// BLINK <id> <idx> <on_ms> <off_ms> — use current LED colour
|
|
||||||
// BLINK <id> <idx> <on_ms> <off_ms> <r> <g> <b> — set colour in same command
|
|
||||||
int count = sscanf(line.c_str(), "BLINK %d %15s %d %d %d %d %d",
|
int count = sscanf(line.c_str(), "BLINK %d %15s %d %d %d %d %d",
|
||||||
&id, idxToken, &onMs, &offMs, &r, &g, &b);
|
&id, idxToken, &onMs, &offMs, &r, &g, &b);
|
||||||
if (count != 4 && count != 7) return false;
|
if (count != 4 && count != 7) return false;
|
||||||
@@ -590,7 +587,7 @@ bool parseBlink(const String& line) {
|
|||||||
|
|
||||||
CRGB color = (count == 7)
|
CRGB color = (count == 7)
|
||||||
? CRGB(constrain(r, 0, 255), constrain(g, 0, 255), constrain(b, 0, 255))
|
? CRGB(constrain(r, 0, 255), constrain(g, 0, 255), constrain(b, 0, 255))
|
||||||
: CRGB(0, 0, 0); // placeholder; overwritten per-LED below when count==4
|
: CRGB(0, 0, 0); // Placeholder; replaced with the live LED colour below.
|
||||||
|
|
||||||
unsigned long nowMs = millis();
|
unsigned long nowMs = millis();
|
||||||
for (int i = idxFirst; i <= idxLast; i++) {
|
for (int i = idxFirst; i <= idxLast; i++) {
|
||||||
@@ -697,6 +694,7 @@ void updateBlink() {
|
|||||||
uint32_t newPos = (uint32_t)bs.cyclePos + dt;
|
uint32_t newPos = (uint32_t)bs.cyclePos + dt;
|
||||||
bs.cyclePos = (uint16_t)(newPos % bs.periodMs);
|
bs.cyclePos = (uint16_t)(newPos % bs.periodMs);
|
||||||
bs.lastMs = nowMs;
|
bs.lastMs = nowMs;
|
||||||
|
// Cheap triangle wave. It does the job and nobody has complained yet.
|
||||||
uint16_t half = bs.periodMs >> 1;
|
uint16_t half = bs.periodMs >> 1;
|
||||||
uint8_t bri = (bs.cyclePos < half)
|
uint8_t bri = (bs.cyclePos < half)
|
||||||
? (uint8_t)((uint32_t)bs.cyclePos * 255 / half)
|
? (uint8_t)((uint32_t)bs.cyclePos * 255 / half)
|
||||||
@@ -707,7 +705,7 @@ void updateBlink() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FX_DFLASH: {
|
case FX_DFLASH: {
|
||||||
static const uint16_t dur[4] = {100, 100, 100, 700};
|
static const uint16_t dur[4] = {100, 100, 100, 700}; // on, off, on, longer off
|
||||||
if ((nowMs - bs.lastMs) >= dur[bs.dphase]) {
|
if ((nowMs - bs.lastMs) >= dur[bs.dphase]) {
|
||||||
bs.lastMs = nowMs;
|
bs.lastMs = nowMs;
|
||||||
bs.dphase = (bs.dphase + 1) & 3;
|
bs.dphase = (bs.dphase + 1) & 3;
|
||||||
@@ -781,7 +779,7 @@ void setup() {
|
|||||||
gauges[i].lastUpdateMicros = micros();
|
gauges[i].lastUpdateMicros = micros();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute per-gauge LED offsets and initialise the strip.
|
// Flatten the per-gauge LED counts into offsets on the shared strip.
|
||||||
uint8_t ledOff = 0;
|
uint8_t ledOff = 0;
|
||||||
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
|
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
|
||||||
gaugeLedOffset[i] = ledOff;
|
gaugeLedOffset[i] = ledOff;
|
||||||
@@ -801,12 +799,14 @@ void loop() {
|
|||||||
readCommands();
|
readCommands();
|
||||||
updateBlink();
|
updateBlink();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
|
||||||
|
updateGauge(i);
|
||||||
|
}
|
||||||
|
|
||||||
if (ledsDirty) {
|
if (ledsDirty) {
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
ledsDirty = false;
|
ledsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < GAUGE_COUNT; i++) {
|
|
||||||
updateGauge(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user