feat(ui): сглаживать температуру скользящим средним за 5 замеров
Мгновенное значение плавает на +-1 градус, и цифра мельтешила каждую секунду при полном покое. На экран теперь идёт среднее за TEMP_AVG_SAMPLES последних замеров; агент шлёт раз в секунду, так что это ровно 5 секунд. Сумма пересчитывается заново на каждом шаге, а не копится: на пяти числах это бесплатно, зато нет накопления ошибки округления за сутки непрерывной работы. Окно сбрасывается при обрыве связи, иначе после паузы среднее считалось бы по значениям до обрыва. Тревога переведена на усреднённое значение: иначе экран показывал бы 84, когда мигание уже идёт. Загрузка и график намеренно остались сырыми. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1047ae1452
commit
fcc96f5090
3 files changed
+64
-3
No files matched your search
+34
-3
@@ -13,6 +13,30 @@ static uint32_t lastSample = 0;
|
||||
static uint32_t lastDraw = 0;
|
||||
static bool everGot = false;
|
||||
static bool alarmActive = false;
|
||||
static bool wasFresh = false;
|
||||
static float tempShown = 0.0f; // усреднённое значение, именно оно на экране
|
||||
|
||||
// Скользящее среднее температуры. Сумма пересчитывается заново, а не копится:
|
||||
// на пяти числах это бесплатно, зато нет накопления ошибки округления за сутки
|
||||
// непрерывной работы.
|
||||
static float tempWindow[TEMP_AVG_SAMPLES];
|
||||
static uint8_t tempCount = 0;
|
||||
static uint8_t tempIndex = 0;
|
||||
|
||||
static void tempAvgReset() {
|
||||
tempCount = 0;
|
||||
tempIndex = 0;
|
||||
}
|
||||
|
||||
static float tempAvgPush(float v) {
|
||||
tempWindow[tempIndex] = v;
|
||||
tempIndex = (uint8_t)((tempIndex + 1) % TEMP_AVG_SAMPLES);
|
||||
if (tempCount < TEMP_AVG_SAMPLES) tempCount++;
|
||||
|
||||
float sum = 0.0f;
|
||||
for (uint8_t i = 0; i < tempCount; i++) sum += tempWindow[i];
|
||||
return sum / tempCount;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(PIN_LED, OUTPUT);
|
||||
@@ -32,14 +56,21 @@ void loop() {
|
||||
CpuStats fresh;
|
||||
if (linkPoll(fresh)) {
|
||||
stats = fresh;
|
||||
tempShown = tempAvgPush(fresh.tempC);
|
||||
lastData = millis();
|
||||
everGot = true;
|
||||
}
|
||||
|
||||
const bool isFresh = everGot && (millis() - lastData < STALE_MS);
|
||||
|
||||
// После паузы связи среднее нельзя считать по значениям до обрыва.
|
||||
if (wasFresh && !isFresh) tempAvgReset();
|
||||
wasFresh = isFresh;
|
||||
|
||||
if (isFresh) {
|
||||
updateAlarm(stats.tempC);
|
||||
// Тревога по усреднённому значению: иначе экран показывал бы 84, а мигание
|
||||
// уже шло бы. Побочно это защищает от срабатывания на одиночный выброс.
|
||||
updateAlarm(tempShown);
|
||||
} else {
|
||||
alarmActive = false; // без данных о перегреве судить не по чему
|
||||
}
|
||||
@@ -57,11 +88,11 @@ void loop() {
|
||||
// Историю дописываем только при живой связи: пауза не должна рисоваться провалом.
|
||||
if (isFresh && millis() - lastSample >= SAMPLE_MS) {
|
||||
lastSample = millis();
|
||||
uiPushSample(stats.tempC);
|
||||
uiPushSample(stats.tempC); // график по сырым: 5 градусов на пиксель, шум там не виден
|
||||
}
|
||||
|
||||
if (millis() - lastDraw >= DRAW_MS) {
|
||||
lastDraw = millis();
|
||||
uiRender(isFresh, stats.tempC, stats.loadPct, alarmActive && blinkOn);
|
||||
uiRender(isFresh, tempShown, stats.loadPct, alarmActive && blinkOn);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user