gauge: add flashing arc alarm when meter is in red

This commit is contained in:
Sebastián Nieto 2026-09-09 22:30:31 -03:00
parent ddc64a54dc
commit 6db6187011
2 changed files with 192 additions and 27 deletions

View file

@ -37,6 +37,11 @@ uint8_t engine_off_count = 0; // counter to indicate engine is off then sleep
float old_data[maxpidIndex] = {-999, -999, -999, -999}; // keep old data
float last_valid_data[maxpidIndex] = {-999, -999, -999, -999}; // keep last valid data for instant redraw
// Arc warning flash (blinking alarm when gauge is in TFT_RED)
bool arcFlashVisible = true;
uint32_t lastArcFlashTime = 0;
bool wasInRedAlarm[4] = { false, false, false, false };
// backlight variable average counter
uint8_t low_count = 0;
uint8_t high_count = 0;
@ -818,20 +823,45 @@ void plotArc4(uint8_t cell, float data, int warn, int min, int max, bool digit,
oldBlocks = NUM_BAR_BLOCKS;
bool colorChanged = (col != oldCol);
if (colorChanged || old_data[cell] < min) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, col);
if (col == TFT_RED) {
wasInRedAlarm[cell] = true;
if (colorChanged) {
arcFlashVisible = true;
lastArcFlashTime = millis();
for (uint8_t i = 0; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_RED);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
} else if (arcFlashVisible) {
if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_RED);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
}
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
} else if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, col);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
} else {
wasInRedAlarm[cell] = false;
if (colorChanged || old_data[cell] < min) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, col);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
} else if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, col);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
}
}
@ -960,20 +990,45 @@ void plotFullScreen(uint8_t cell, float data, int warn, int min, int max,
oldBlocks = NUM_BAR_BLOCKS;
bool colorChanged = (col != oldCol);
if (colorChanged || old_data[cell] < min) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawBarBlock(i, col);
if (col == TFT_RED) {
wasInRedAlarm[cell] = true;
if (colorChanged) {
arcFlashVisible = true;
lastArcFlashTime = millis();
for (uint8_t i = 0; i < newBlocks; i++) {
drawBarBlock(i, TFT_RED);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
} else if (arcFlashVisible) {
if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawBarBlock(i, TFT_RED);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
}
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
} else if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawBarBlock(i, col);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawBarBlock(i, TFT_DARKGREY);
} else {
wasInRedAlarm[cell] = false;
if (colorChanged || old_data[cell] < min) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawBarBlock(i, col);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
} else if (newBlocks > oldBlocks) {
for (uint8_t i = oldBlocks; i < newBlocks; i++) {
drawBarBlock(i, col);
}
} else if (newBlocks < oldBlocks) {
for (uint8_t i = newBlocks; i < oldBlocks; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
}
}
@ -1197,6 +1252,115 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
}
/*-------------------------------*/
// Non-blocking handler to blink/flash arcs on alarm (when in TFT_RED)
void handleArcAlarmFlash() {
uint32_t now = millis();
bool toggleTick = false;
if (now - lastArcFlashTime >= 250) {
lastArcFlashTime = now;
arcFlashVisible = !arcFlashVisible;
toggleTick = true;
}
if (fullScreenCell >= 0 && fullScreenCell < 4) {
uint8_t cell = fullScreenCell;
if (!cellIsNumeric[cell] && last_valid_data[cell] != -999) {
uint8_t pidIdx = pidInCell[cell];
int warn = warningValue[pidIdx].toInt();
float data = last_valid_data[cell];
uint16_t col = getMeterColor(pidIdx, data, warn);
bool inRed = (col == TFT_RED);
if (wasInRedAlarm[cell] && !inRed) {
// Exited red alarm: restore steady arc
wasInRedAlarm[cell] = false;
int min = pidConfig[pidIdx][4].toInt();
int max = pidConfig[pidIdx][5].toInt();
int newBlocks = map(data, min, max, 0, NUM_BAR_BLOCKS);
if (newBlocks < 0) newBlocks = 0;
if (newBlocks > NUM_BAR_BLOCKS) newBlocks = NUM_BAR_BLOCKS;
for (uint8_t i = 0; i < newBlocks; i++) {
drawBarBlock(i, col);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
} else if (inRed) {
wasInRedAlarm[cell] = true;
if (toggleTick) {
int min = pidConfig[pidIdx][4].toInt();
int max = pidConfig[pidIdx][5].toInt();
int newBlocks = map(data, min, max, 0, NUM_BAR_BLOCKS);
if (newBlocks < 0) newBlocks = 0;
if (newBlocks > NUM_BAR_BLOCKS) newBlocks = NUM_BAR_BLOCKS;
if (arcFlashVisible) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawBarBlock(i, TFT_RED);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_DARKGREY);
}
} else {
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
drawBarBlock(i, TFT_BLACK);
}
}
}
}
}
} else {
// 4 quadrants mode
for (uint8_t cell = 0; cell < 4; cell++) {
if (!cellIsNumeric[cell] && last_valid_data[cell] != -999) {
uint8_t pidIdx = pidInCell[cell];
int warn = warningValue[pidIdx].toInt();
float data = last_valid_data[cell];
uint16_t col = getMeterColor(pidIdx, data, warn);
bool inRed = (col == TFT_RED);
if (wasInRedAlarm[cell] && !inRed) {
// Exited red alarm: restore steady arc
wasInRedAlarm[cell] = false;
int min = pidConfig[pidIdx][4].toInt();
int max = pidConfig[pidIdx][5].toInt();
int newBlocks = map(data, min, max, 0, NUM_BAR_BLOCKS);
if (newBlocks < 0) newBlocks = 0;
if (newBlocks > NUM_BAR_BLOCKS) newBlocks = NUM_BAR_BLOCKS;
for (uint8_t i = 0; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, col);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
} else if (inRed) {
wasInRedAlarm[cell] = true;
if (toggleTick) {
int min = pidConfig[pidIdx][4].toInt();
int max = pidConfig[pidIdx][5].toInt();
int newBlocks = map(data, min, max, 0, NUM_BAR_BLOCKS);
if (newBlocks < 0) newBlocks = 0;
if (newBlocks > NUM_BAR_BLOCKS) newBlocks = NUM_BAR_BLOCKS;
if (arcFlashVisible) {
for (uint8_t i = 0; i < newBlocks; i++) {
drawQuadBarBlock(cell, i, TFT_RED);
}
for (uint8_t i = newBlocks; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_DARKGREY);
}
} else {
for (uint8_t i = 0; i < NUM_BAR_BLOCKS; i++) {
drawQuadBarBlock(cell, i, TFT_BLACK);
}
}
}
}
}
}
}
}
// Target and current brightness variables for smooth fade
uint8_t targetBacklight = 255;
float currentBacklight = 255.0f;

View file

@ -335,7 +335,8 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
/*###################################*/
void loop() {
updateBacklightFade(); // non-blocking smooth backlight fade handler
updateBacklightFade(); // non-blocking smooth backlight fade handler
handleArcAlarmFlash(); // non-blocking arc alarm flash handler (blinks when in TFT_RED)
// SCAN TOUCHSCREEN
// - Single click on a quadrant: toggles between clock (arc) and number