# 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, а не к разводке встроенного экрана.