// Индикатор температуры CPU: плата принимает строки "T=67.0;L=34" по USB-COM // от агента на ПК и рисует их на встроенном OLED 72x40. Сама ничего не меряет. // // Все настройки — в config.h. #include "config.h" #include "link.h" #include "ui.h" static CpuStats stats = {0.0f, 0}; static uint32_t lastData = 0; static uint32_t lastSample = 0; static uint32_t lastDraw = 0; static bool everGot = false; static bool alarmActive = false; void setup() { pinMode(PIN_LED, OUTPUT); digitalWrite(PIN_LED, !LED_ACTIVE_LEVEL); linkBegin(); uiBegin(); } // Гистерезис: включаемся на верхнем пороге, отпускаем только на нижнем. static void updateAlarm(float tempC) { if (!alarmActive && tempC >= ALARM_ON_C) alarmActive = true; else if (alarmActive && tempC <= ALARM_OFF_C) alarmActive = false; } void loop() { CpuStats fresh; if (linkPoll(fresh)) { stats = fresh; lastData = millis(); everGot = true; } const bool isFresh = everGot && (millis() - lastData < STALE_MS); if (isFresh) { updateAlarm(stats.tempC); } else { alarmActive = false; // без данных о перегреве судить не по чему } // Общая фаза для экрана и светодиода, чтобы они моргали синхронно. const bool blinkOn = (millis() / ALARM_BLINK_MS) % 2 == 0; // Тревога — мигает, нет данных — горит ровно, норма — погашен. bool ledOn; if (!isFresh) ledOn = true; else if (alarmActive) ledOn = blinkOn; else ledOn = false; digitalWrite(PIN_LED, ledOn ? LED_ACTIVE_LEVEL : !LED_ACTIVE_LEVEL); // Историю дописываем только при живой связи: пауза не должна рисоваться провалом. if (isFresh && millis() - lastSample >= SAMPLE_MS) { lastSample = millis(); uiPushSample(stats.tempC); } if (millis() - lastDraw >= DRAW_MS) { lastDraw = millis(); uiRender(isFresh, stats.tempC, stats.loadPct, alarmActive && blinkOn); } }