Files
Arduino/CPU_temp/docs/2026-09-14-cpu-temp-design.md
oskarvitaliiandClaude Opus 5 59848698ff 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>
2026-09-14 21:42:24 +07:00

9.4 KiB
Raw Permalink Blame History

CPU Temp — настольный индикатор температуры процессора

Дата: 2026-09-14 Статус: дизайн согласован, реализация не начата

Задача

Показывать температуру CPU домашнего ПК на отдельной плате ESP32-C3 с OLED-экраном 72×40, стоящей на столе. Кроме текущего значения — история за последнюю минуту, чтобы было видно, греется машина под нагрузкой или нет.

Оборудование

Параметр Значение
Плата ESP32-C3 (QFN32), ревизия v0.4, встроенный OLED 0.42″
Флеш 4 МБ (XMC), кристалл 40 МГц
Подключение нативный USB Espressif, VID_303A&PID_1001, на текущем ПК — COM4
FQBN esp32:esp32:esp32c3 (ядро esp32 3.3.8)
ПК Windows 10 Pro, Intel Core i5-11400H

Архитектура

LibreHardwareMonitorLib.dll ──> PowerShell-агент ──COM4 (USB CDC)──> ESP32-C3 ──I2C──> OLED 72×40
        (драйвер, MSR)            раз в секунду        текстовая строка         U8g2

Плата ничего не измеряет сама и не хранит настроек: принимает строки и рисует. Вся работа с железом ПК — на стороне агента.

Почему так

  • Данные с ПК, а не встроенный датчик ESP32. Встроенный сенсор меряет собственный кристалл платы — величина малоинформативная.
  • Температуру CPU читает LibreHardwareMonitor, а не наш код. Прямое чтение требует MSR-регистров через подписанный драйвер ядра и отдельных формул под каждое поколение CPU. LHM даёт готовую LibreHardwareMonitorLib.dll.
  • Транспорт — COM-порт, не Wi-Fi. Плата и так питается по USB от этого же ПК: провод уже есть. Нет настройки сети, паролей, IP и mDNS.
  • Агент на PowerShell, не на C#. Загрузка .NET-сборки доступна из PowerShell напрямую; компилятор и IDE не нужны.

Протокол

Одна строка в секунду, \n в конце:

T=67.0;L=34
Ключ Смысл Формат
T CPU Package, °C дробное
L общая загрузка CPU, % целое

Формат «ключ=значение» выбран ради расширяемости: добавление G= (GPU) или M= (RAM) не ломает старую прошивку — неизвестные ключи прошивка молча игнорирует. Скорость 115200.

Отсутствие данных. Если валидная строка не приходила дольше 5 секунд, прошивка показывает NO DATA и перестаёт дописывать историю (чтобы пауза не рисовалась как провал температуры).

Экран

Разрешение 72×40, монохром, драйвер SSD1306 с ненулевым смещением по обеим осям. Используется U8G2_SSD1306_72X40_ER_F_HW_I2C из U8g2 2.36.19 (уже установлена).

┌────────────────────────┐
│  67°  34%              │  крупные цифры (~24 px) + мелкая загрузка
│                        │
│ ▁▂▃▃▄▆█▆▅▄▃▂▂▁▁▂▃▄▅▆   │  спарклайн: 72 точки = 72 секунды
└────────────────────────┘

Шкала графика фиксированная: 30–90 °C. Автомасштаб отвергнут: в простое шум ±1 °C рисовался бы горами и создавал ложную тревогу. Значения вне диапазона обрезаются по краю.

История — кольцевой буфер на 72 значения (по пикселю на точку, одно значение в секунду).

Состав проекта

CPU_temp/
  CPU_temp.ino          setup/loop, тайм-аут «нет данных»
  link.h / link.cpp     чтение строки из Serial, разбор в структуру CpuStats
  ui.h  / ui.cpp        отрисовка U8g2, кольцевой буфер истории
  docs/                 этот документ
  agent/
    cpu_temp_agent.ps1  агент для ПК
    README.md           установка и автозапуск

Границы модулей: link ничего не знает об экране и отдаёт только структуру с данными и признаком свежести; ui не знает, откуда данные взялись, и принимает ту же структуру. Оба тестируются и меняются независимо.

Агент

Файл agent/cpu_temp_agent.ps1:

  1. загружает LibreHardwareMonitorLib.dll из D:\Soft\LibreHardwareMonitor;
  2. включает мониторинг CPU, ищет сенсоры Temperature/CPU Package и Load/CPU Total;
  3. находит COM-порт по VID_303A&PID_1001 (не по фиксированному номеру: номер меняется при перетыкании в другой разъём);
  4. раз в секунду пишет строку протокола;
  5. при исчезновении порта (перезагрузка платы, перезаливка прошивки) — переподключается в цикле, не падая.

Требует прав администратора: без них драйвер LHM не загружается и температура приходит пустой.

Автозапуск — задание в Планировщике заданий: триггер «при входе в систему», галка «Выполнить с наивысшими правами», окно скрыто.

Установка LibreHardwareMonitor

Каталог D:\Soft\LibreHardwareMonitor — вне репозитория Arduino. Само приложение не запускается, нужны только LibreHardwareMonitorLib.dll и её драйвер.

Порядок работ и риски

  1. Определить пины I2C дисплея эмпирически. Шелкография подписывает GPIO8/GPIO9 (дефолтные Wire-пины ESP32-C3), но встроенный OLED у плат этого семейства обычно на GPIO5/GPIO6. Первый шаг — залить I2C-сканер и найти адрес экрана перебором обеих пар. Пины не угадывать.
  2. Прошивка: вывод фиксированной заглушки на экран — убедиться в геометрии и смещении 72×40.
  3. Приём и разбор строк, NO DATA по тайм-ауту.
  4. График.
  5. Агент, затем автозапуск.

Прочие риски:

  • COM4 — тот же порт, через который прошивается плата. Перед каждой заливкой агента надо останавливать, иначе PermissionError. То же ограничение уже описано в CLAUDE.md для монитора порта Arduino IDE.
  • USB CDC On Boot должен быть включён в настройках платы, иначе Serial уйдёт в аппаратный UART, а не в USB.

Решения, принятые явно

  • Git: проект пока не добавляется в белый список .gitignore. Заливаем, когда появятся первые рабочие результаты, чтобы не засорять публичную историю.
  • Автозапуск агента: через Планировщик заданий (вариант B), а не ручной ярлык.
  • Каталог LHM: D:\Soft\LibreHardwareMonitor.

Вне рамок (YAGNI)

  • GPU, RAM, частоты, вентиляторы — протокол расширяем, но сейчас не делаем.
  • Переключение экранов кнопкой BOOT.
  • Wi-Fi, веб-панель, сохранение настроек в LittleFS — прошивке нечего хранить.

Подтверждённые пины (Задача 1, 2026-09-14)

Сканер tools/i2c_scan перебрал пары (5,6), (6,5), (8,9), (9,8). Устройство отвечает только на одной:

SDA=5 SCL=6: device 0x3C

Итого: SDA = GPIO5, SCL = GPIO6, адрес 0x3C. Подпись GPIO8/GPIO9 на шелкографии относится к дефолтным Wire-пинам ESP32-C3, а не к разводке встроенного экрана.