feat(cpu_temp): индикатор температуры CPU на ESP32-C3 с OLED
Плата принимает по USB-CDC строки "T=67.0;L=34" от агента на ПК и рисует крупную цифру, загрузку и график за последнюю минуту на экране 72x40. Пины дисплея (SDA=5, SCL=6) определены сканером, а не по шелкографии: подписи GPIO8/GPIO9 на плате - это дефолтные Wire-пины чипа. Агент читает сенсоры через LibreHardwareMonitorLib. С версии 0.9.5 она требует отдельно установленный драйвер PawnIO: без него загрузка CPU читается, а температуры пусты даже под администратором. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ed4dad0a52
commit
59848698ff
12 files changed
+1473
No files matched your search
@@ -0,0 +1,79 @@
|
||||
#include "ui.h"
|
||||
|
||||
#include <U8g2lib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Подтверждено сканером из tools/i2c_scan: экран отвечает только на этой паре.
|
||||
static const uint8_t PIN_SDA = 5;
|
||||
static const uint8_t PIN_SCL = 6;
|
||||
|
||||
// Порядок параметров: (rotation, reset, clock, data) — SCL идёт раньше SDA.
|
||||
static U8G2_SSD1306_72X40_ER_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE, PIN_SCL, PIN_SDA);
|
||||
|
||||
static const uint8_t GRAPH_W = 72; // по пикселю на отсчёт: 72 точки = 72 секунды
|
||||
static const uint8_t GRAPH_TOP = 28;
|
||||
static const uint8_t GRAPH_H = 12;
|
||||
|
||||
// Шкала фиксированная: при автомасштабе шум +-1 градус в простое рисовался бы горами.
|
||||
static const float SCALE_MIN = 30.0f;
|
||||
static const float SCALE_MAX = 90.0f;
|
||||
|
||||
static uint8_t history[GRAPH_W]; // 0 = нет данных, иначе высота столбика 1..GRAPH_H
|
||||
|
||||
void uiBegin() {
|
||||
display.begin();
|
||||
display.clearBuffer();
|
||||
display.setFont(u8g2_font_6x10_tf);
|
||||
display.drawStr(0, 24, "WAIT");
|
||||
display.sendBuffer();
|
||||
}
|
||||
|
||||
void uiPushSample(float tempC) {
|
||||
if (tempC < SCALE_MIN) tempC = SCALE_MIN;
|
||||
if (tempC > SCALE_MAX) tempC = SCALE_MAX;
|
||||
|
||||
const float norm = (tempC - SCALE_MIN) / (SCALE_MAX - SCALE_MIN);
|
||||
uint8_t h = (uint8_t)(norm * GRAPH_H + 0.5f);
|
||||
if (h < 1) h = 1;
|
||||
|
||||
memmove(history, history + 1, GRAPH_W - 1);
|
||||
history[GRAPH_W - 1] = h;
|
||||
}
|
||||
|
||||
static void drawGraph() {
|
||||
for (uint8_t x = 0; x < GRAPH_W; x++) {
|
||||
const uint8_t h = history[x];
|
||||
if (h == 0) continue;
|
||||
display.drawVLine(x, GRAPH_TOP + GRAPH_H - h, h);
|
||||
}
|
||||
}
|
||||
|
||||
void uiRender(bool fresh, float tempC, int loadPct) {
|
||||
display.clearBuffer();
|
||||
|
||||
if (!fresh) {
|
||||
display.setFont(u8g2_font_6x10_tf);
|
||||
display.drawStr(0, 14, "NO");
|
||||
display.drawStr(0, 26, "DATA");
|
||||
display.sendBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[8];
|
||||
|
||||
// Крупные цифры температуры.
|
||||
snprintf(buf, sizeof(buf), "%d", (int)(tempC + 0.5f));
|
||||
display.setFont(u8g2_font_logisoso24_tn);
|
||||
display.drawStr(0, 24, buf);
|
||||
const int numWidth = display.getStrWidth(buf);
|
||||
|
||||
// Градус и загрузка — мелким шрифтом справа.
|
||||
display.setFont(u8g2_font_5x7_tf);
|
||||
display.drawStr(numWidth + 2, 10, "\xb0");
|
||||
snprintf(buf, sizeof(buf), "%d%%", loadPct);
|
||||
display.drawStr(numWidth + 2, 24, buf);
|
||||
|
||||
drawGraph();
|
||||
|
||||
display.sendBuffer();
|
||||
}
|
||||
Reference in new issue
Block a user