ESP32 DevKit v1 · pinport
готово
⋮

Тепловой насос воздух–вода на ESP32, версия 2: таблица ЭРВ, защита по току и MQTT

Вторая версия контроллера теплового насоса воздух–вода по замечаниям пользователей: стартовая позиция ЭРВ из таблицы «улица → шаги» с самообучением, ПИ с шагом по открытию вентиля, счётчик пусков, вход аппаратной защиты с причиной в журнале, защита по току компрессора, порог оттайки по морозу, отопительная кривая, остановка при закрытых зонах пола, выход аварии и MQTT по темам. Первая версия остаётся в галерее.

Что на схеме

Плата ESP32 DevKit v1, к ней подключены:

  • DS18B20 (термометр 1-Wire) «Всасывание» — ts, температура 8 °C
  • DS18B20 (термометр 1-Wire) «Нагнетание» — td, температура 80 °C
  • DS18B20 (термометр 1-Wire) «Змеевик» — te, температура 2 °C
  • DS18B20 (термометр 1-Wire) «Обратка» — tr, температура 28 °C
  • DS18B20 (термометр 1-Wire) «Подача» — tp, температура 33 °C
  • DS18B20 (термометр 1-Wire) «Улица» — to, температура 5 °C
  • Шаговый двигатель «ЭРВ» — eev
  • Потенциометр «Давл. высокое» — ph
  • Потенциометр «Давл. низкое» — pl
  • Потенциометр «Ток компрессора» — pa
  • Переключатель «Проток пола» — fl
  • Переключатель «Цепь защит» — ch
  • Переключатель «Зоны закрыты» — zn
  • Кнопка «Пуск / сброс» — btn
  • Светодиод «Авария» — la, цвет красный
  • Резистор «330 Ом» — ra, номинал 330 Ом
  • Реле «Компрессор» — k1
  • Реле «Вентилятор» — k2
  • Реле «Насос пола» — k3
  • Реле «4-ход. клапан» — k4
  • Ввод 230 В «Ввод 230 В» — in
  • Автоматический выключатель «Цепи упр.» — qf1
  • Автоматический выключатель «Компрессор» — qf2
  • Контактор «Контактор» — km1
  • Двигатель однофазный «Компрессор» — mc
  • Двигатель однофазный «Вентилятор» — mf
  • Двигатель однофазный «Насос пола» — mw
  • Светильник 230 В «Катушка клапана» — la1

Задействованы выводы платы: 3V3, GND, D4, D5, D18, D19, D21, D22, D34, D35, VN, D27, D16, D14, D13, D17, D25, D26, D32, D33. Всего соединений на схеме: 71.

Что это и чем отличается от первой версии

Второй вариант установки воздух–вода на базе наружного блока кондиционера «старт–стоп»: змеевик блока забирает тепло у уличного воздуха, компрессор сжимает фреон, в пластинчатом теплообменнике — конденсаторе — фреон отдаёт тепло воде тёплого пола, электронный расширительный вентиль (ЭРВ) на шаговом двигателе дросселирует жидкость обратно к змеевику. Первую версию мы оставили в галерее («Тепловой насос воздух–вода на ESP32: оттайка, ЭРВ и панель Settings»); эта собрана по замечаниям тех, кто её повторял. Что изменилось:

  1. Стартовая позиция ЭРВ — из таблицы, а не константа 220 шагов. Ключ — температура на улице, поправка — температура обратки пола.
  2. Шаг ПИ зависит от открытия вентиля (флаг в панели).
  3. Счётчик пусков за час и за всё время, длительность последнего цикла.
  4. Вход «цепь аппаратной защиты»: если цепь HP/термостатов разомкнулась, в журнале — что видели датчики в этот момент.
  5. Защита по току компрессора: слишком малый ток (обрыв, сухой ход) и слишком большой.
  6. MQTT отдельными темами, по значению на тему.
  7. Порог оттайки зависит от мороза.
  8. Отопительная кривая по четырём точкам вместо одного наклона.
  9. Выход аварии и вход «все зоны пола закрыты» с отдельным разбором потери протока.
  10. Один фреон для сборки на железе и обновление по воздуху — константами в начале скетча.

Всё остальное — шесть DS18B20 на двух линиях, давления, оттайка четырёхходовым клапаном, защита воды от замерзания, панель Settings — как в первой версии; о нём подробно написано в её статье.

Стартовая позиция ЭРВ: таблица, формула и самообучение

Сразу после пуска компрессора и после оттайки вентиль надо поставить в положение, близкое к рабочему: от этого зависит, сколько жидкости уйдёт в змеевик в первые минуты. Константа подходит одной погоде. Поэтому положение берётся из таблицы из пяти точек «температура на улице → шагов», между точками — линейная интерполяция, за краями — значение крайней точки (не экстраполяция). Сверху добавляется поправка на обратку пола: чем она горячее, тем выше давление конденсации и тем больше нужно прикрыть вентиль (шагов на градус выше опорной обратки 30 °C).

Откуда берутся числа по умолчанию. Из формулы расхода: вентиль пропускает тем больше, чем больше перепад давления, а нужен ему расход компрессора, который растёт с давлением кипения:

шагов = eevStart · (Pкип / Pкип0) · √((Pконд0 − Pкип0) / (Pконд − Pкип))

Опора — кипение 0 °C, конденсация 40 °C, 220 шагов. Кипение принимается на 8 К ниже уличного воздуха, конденсация — на 8 К выше обратки. Это первое приближение, а не паспорт вентиля: настоящая характеристика ЭРВ нелинейна, поэтому таблицу подстраивают руками (панель → «Стартовая позиция ЭРВ») или оставляют самообучению. При смене фреона кнопка «Заполнить по формуле» пересчитывает таблицу для нового.

Самообучение. Если перегрев держался у цели (в пределах ±1 К) дольше заданного времени (30 с в симуляторе, 10 минут на железе), текущее открытие считается подходящим для этой уличной температуры, и два соседних узла таблицы сдвигаются к нему на 20 % расхождения — пропорционально весам. Запись во флеш происходит только при остановке компрессора, а не по ходу работы: NVS рассчитана на ограниченное число записей, и счётчик пусков с таблицей не должны её выбить. В журнале строка «самообучение: …» показывает, что и куда сдвинулось. Выключается переключателем.

ПИ с шагом, зависящим от открытия

Скоростной ПИ-регулятор считает приращение Kp·(ошибка − прошлая) + Ki·ошибка·5 с. При малом открытии вентиля шаг в несколько шагов двигателя меняет расход сильнее, чем при большом, и один и тот же коэффициент то раскачивает контур, то вяло его ведёт. Теперь Kp и Ki умножаются на (открытие / piRef)^piPow: piRef — 250 шагов, степень 1 по умолчанию, множитель ограничен 0,25–3. В панели («ЭРВ») это переключатель «Масштабировать Kp и Ki по открытию»: выключите его — и увидите поведение первой версии.

Пуски, цикличность и буфер

Компрессор «старт–стоп» не любит частых пусков. Плата считает пуски за последний час (по меткам времени последних 24), всего (в NVS, пишется при остановке) и запоминает длительность последней работы и паузы перед ней. Если пусков за час больше предела (по умолчанию 6), в журнал идёт предупреждение: объёма воды в контуре не хватает, и установка тактует. Лекарство — буферная ёмкость на подаче или меньший гистерезис вместе с большей паузой между пусками; цифры в панели («Последний цикл») показывают, помогло ли. Пуски внутри оттайки тоже считаются: для компрессора это такие же включения.

Аппаратная защита и вход «цепь цела»

Предупреждение о нехватке фреона. Если ЭРВ открыт на максимум, а перегрев всё равно больше цели на 4 К и дольше 5 минут (в симуляторе — 20 секунд), плата не останавливает установку, но пишет в журнал «возможна нехватка фреона или засор фильтра», показывает «Предупреждение» на панели и публикует тему warning в MQTT. Без него такое состояние выглядит штатным: регулятор просто упёрся в предел. Порог и время — в панели (0 секунд — не следить); сообщение снимается, когда перегрев вернулся к цели. Что именно — фреон или фильтр, скетч не знает: смотрите глазок и разность температур до и после фильтра.

Контроллер — не единственная защита. Для настоящего компрессора часть защит ставят аппаратно, в цепь катушки контактора — чтобы они работали, даже если плата зависла или пропало питание датчика:

  • реле высокого давления (HP) — нормально замкнутый контакт последовательно в цепь катушки, без обходов. Разомкнулось — контактор отпал; многие реле HP с ручным сбросом, и пуск невозможен, пока кто-то не придёт и не разберётся;
  • реле низкого давления (LP) — тоже в цепь катушки, но с обходом на время пуска. В момент пуска давление всасывания ещё не поднялось, и «голое» LP в цепи либо не даст компрессору стартовать, либо выбьет его тут же. Обход делают реле времени на 30–120 с или контактом пускового реле: он шунтирует LP только на время пуска, потом LP работает как обычно;
  • термостат нагнетания или корпуса и реле протока — последовательно в ту же цепь.

Вход D16 этим не управляет. Это оптрон (PC817 или модуль на 230 В), вход которого стоит после последнего контакта цепи, перед катушкой: он сообщает контроллеру «напряжение на катушке есть». На схеме его заменяет переключатель ch: замкнут на землю (движок справа) — цепь цела. Если цепь разомкнулась при работе, плата останавливает всё, поднимает аварию «сработала аппаратная защита» и пишет в журнал, что видели датчики в этот момент — высокое давление, низкое, нагнетание, потерю протока, близкую к замерзанию подачу. Если ничего из этого не видно, так и написано: смотрите реле HP и LP, термостаты, контактор. Если цепь разомкнута до пуска, установка не стартует и через 3 с объясняет, почему. Авария по цепи сама не повторяется: кто-то должен прийти к реле.

Защита по току

Ток компрессора — потенциометр pa на входе D39 (VN), шкала 0…10 А. На железе вместо него — трансформатор тока с выпрямителем и делителем или счётчик PZEM-004T по UART: для PZEM достаточно заменить тело функции readCurrent(), остальная часть скетча берёт ток только из переменной amps. PZEM в симуляторе не эмулируется, и с настоящим датчиком эта часть не проверялась.

Через несколько секунд после пуска (пусковой бросок не считается) ток должен быть между «не ниже» (1,5 А: обрыв, сухой ход, не включился контактор) и «не выше» (8,5 А). Выход за предел — авария, которая сама не повторяется. Все три числа — в панели.

Оттайка: порог зависит от мороза

Змеевик считается обмёрзшим, если он холоднее порога (−3 °C) и холоднее уличного воздуха на 8 К. На сильном морозе та же шуба инея даёт меньшую разницу — воздух и так холодный, — поэтому порог снижается на 0,25 К за каждый градус мороза, но не ниже 3 К: при −12 °C это 5 К. Все три числа — в панели («Оттайка»). Ход оттайки, паузы на выравнивание давлений и защита воды те же, что в первой версии.

Все зоны закрыты — это не авария насоса

Термоголовки на коллекторе пола закрываются, когда в комнатах тепло. Когда закрыты все, насос гонит воду в тупик, проток пропадает — и первая версия объявляла аварию. Теперь вход D14 (zn: замкнут — все сервоприводы закрыты) отделяет эту ситуацию от неисправности насоса: компрессор останавливается без аварии, в журнал идёт «проток пропал (… компрессор работал N с): все зоны пола закрыты — остановка без аварии», а пока зоны закрыты, пуска нет и панель говорит почему. Открылась хоть одна — установка запускается сама. Если проток пропал, а зоны открыты, — это насос или фильтр, и тут уже авария; в журнале время работы до потери протока. Для настоящей установки к тому же нужен перепускной клапан (байпас) между подачей и обраткой: он оставляет минимальный проток при закрытых зонах.

Отопительная кривая и выход аварии

Цель подачи считается по наклону (на сколько поднять цель на каждый градус мороза) или по четырём точкам «улица → подача» — переключатель на панели. Кривая по умолчанию совпадает с наклоном 0,4 К/К, поэтому переход неощутим; редактируйте точки, когда увидите, что при −20 °C полу нужно не 38 °C, а 41.

Выход аварии D17 — светодиод с резистором 330 Ом. Для лампы или сирены на железе между выводом и нагрузкой нужен транзистор (например, IRLZ44N с резистором на затворе и диодом на катушке сирены); вывод платы нагрузку не потянет. Включён, пока идёт авария.

MQTT: по значению на тему

Каждое значение публикуется в свою тему pinport/heatpump/air/<имя> с флагом retain: state, fault, fault_text, compressor, fan, pump, valve, superheat, t_evap, t_cond, p_low, p_high, eev_steps, starts_hour, starts_total, current, protection_chain, flow, zones_closed, а температуры — в temp/suction, temp/discharge, temp/coil, temp/return, temp/supply, temp/outdoor. Так Home Assistant получает готовые датчики без разбора JSON. Тема меняется не чаще раза в секунду (5 секунд на железе) и раз в 20 секунд (5 минут) обновляется, даже если не менялась; статус …/status — online или offline (последняя воля). Контроллер только публикует и команд из сети не принимает — управление остаётся на странице и кнопке. Брокер недоступен — плата работает без него и пробует подключиться не чаще раза в 30 секунд (пока компрессор идёт — в две минуты), чтобы блокировка подключения не останавливала ЭРВ и защиты.

В симуляторе любой адрес ведёт на встроенный брокер PinPort (вкладка «MQTT»); на железе пропишите свой брокер, логин и пароль в начале скетча.

Сборка на железо: константы в начале

  • SIM_DEMO — 0: вернутся реальные задержки (пауза 5 минут, выбег минута, оттайка до десяти минут).
  • REAL_BUILD — 1: в прошивке остаётся один фреон, а лишние таблицы и выбор в панели убираются.
  • REFRIGERANT_DEFAULT — номер фреона (0 R22, 1 R410A, 2 R134a, 3 R407C, 4 R404A, 5 R290, 6 R600a).
  • USE_OTA — 1: обновление по воздуху через ArduinoOTA; на время обновления установка останавливается. В симуляторе не проверяется.
  • VALVE_HEAT_ON — по схеме своего блока.
  • Датчики давления через делитель, драйвер ЭРВ (ULN2003/ULN2803 или L298N/DRV8833), реле — модуль AC-DC-ESP32-Relay-x4 с выводами 25, 26, 32, 33.

Что проверено и что нет

Логика скетча — таблица и интерполяция, самообучение, запись во флеш только при остановке, масштаб ПИ, счётчик пусков, цепь защит, ток, зоны, порог оттайки, кривая, темы MQTT, поведение без брокера, переход millis() через 2³² — прогнана на хосте с подставными библиотеками и виртуальным временем; сценарий этой страницы — тоже. Прошивка под ESP32 и сам PinPort в этих прогонах не участвовали: если что-то на вашей схеме ведёт себя иначе, пришлите журнал из порта. На железе не проверялись ни OTA, ни PZEM, ни транзисторный выход аварии.

Что не так в симуляторе

Пока галочка «запускать со сценарием» снята, датчики и ток вам не принадлежат: ими управляет модель фреонового контура (вкладка «Контур»). Реле платы включают компрессор, вентилятор, насос пола и четырёхходовой клапан (катушка под током — нагрев), шаги ЭРВ открывают клапан, а давления, температуры и ток компрессора возвращаются в датчики. Поэтому ПИ в симуляторе сходится: перегрев откликается на положение вентиля, а самообучение запоминает настоящий результат, а не граничное положение. На морозе змеевик обмерзает, и скетч размораживает его клапаном — лёд тает за счёт тепла, которое установка отбирает у воды.

Рычагов на вкладке три: температура на улице, заправка и засор фильтра. Утечка заставит ЭРВ уйти на максимум и даст предупреждение о фреоне. Ручки потенциометров давления и тока и температуры датчиков при включённой модели ничего не решают: их перезаписывает модель. Со сценарием она молчит: сценарий задаёт те же датчики по своим строкам.

Модель учебная: сосредоточенные параметры, температурный глайд смесей не считается, размер установки подогнан под компрессор 1,1 кВт из этого примера.

Библиотеки

Пример собирается с библиотеками:

  • WiFi
  • Preferences
  • LittleFS
  • OneWire
  • DallasTemperature
  • AccelStepper
  • PubSubClient
  • Settings

Они уже установлены на сервере сборки — отмечать их в проекте вручную не нужно, список приезжает вместе с примером.

Как это устроено в коде

Основное, чем пользуется скетч:

  • Preferences — хранение настроек во flash, переживает перезапуск
  • Stepper — шаги двигателя по фазам
  • constrain() — зажимает значение в границах
  • millis() — миллисекунды с запуска: на них строят работу без остановки
  • Serial.println() — печатает строку в монитор порта
  • digitalWrite() — выставляет на выводе высокий или низкий уровень
  • Serial.printf() — печатает в монитор порта с форматированием
  • analogRead() — измеряет напряжение на выводе через АЦП
  • digitalRead() — читает уровень на выводе
  • WiFiClient — TCP-соединение с сервером
  • WiFi.begin() — подключается к точке доступа виртуального Wi-Fi
  • delay() — пауза, на время которой ядро занято ожиданием

В скетче 1815 строк; свои функции: satTemp(), satPress(), formulaPos(), fillTable(), setDefaults(), sortTables(), saveSettings(), loadSettings(); подключено заголовков: 9. Сам скетч открыт на соседней вкладке — его можно менять и запускать заново.

Что попробовать изменить

  1. Нажмите «Запустить». Плата найдёт по три датчика на каждой линии и найдёт ноль ЭРВ. Сценарий сам переведёт вправо ползунок протока fl и переключатель цепи защит ch («течёт» и «цепь цела»); без сценария сделайте это мышью, иначе установка не запустится — разомкнутая цепь перед пуском это тоже авария, и журнал скажет, почему.
  2. Нажмите кнопку на схеме: включится насос тёплого пола и катушка клапана, через несколько секунд — компрессор и вентилятор блока. В журнале будет «ЭРВ N шагов (по таблице)» — стартовая позиция из таблицы по уличной температуре и обратке пола, а не константа 220.
  3. Откройте «Веб-интерфейс» → «Стартовая позиция ЭРВ»: таблица из пяти точек, поправка на обратку и строка «Для текущих условий». Задайте для to («Улица») другую температуру — число изменится. Смените фреон и нажмите «Заполнить по формуле» — таблица пересчитается.
  4. Откройте вкладку MQTT симулятора: плата публикует pinport/heatpump/air/state, compressor, superheat, starts_total, protection_chain, current и температуры в temp/… — по значению на тему, с retain.
  5. Мороз и оттайка: задайте to −12 °C, затем te («Змеевик») −18 °C. Разница с воздухом 6 К; в первой версии порог был 8 К, и оттайки бы не было, теперь на морозе он 5 К. Поднимите te до +12 °C — оттайка закончится.
  6. Переведите вправо переключатель zn («Зоны закрыты») и влево ползунок fl: проток пропал, но все зоны закрыты — компрессор останавливается без аварии, пуска нет, пока зоны закрыты. Верните оба — установка запустится сама.
  7. Крутите ручку pa («Ток компрессора») выше 85 %: через секунду авария по току, загорается светодиод la («Авария»). Долгое нажатие кнопки сбрасывает аварию. Ток ниже 15 % после пуска — тоже авария (обрыв, сухой ход).
  8. Переведите ch влево во время работы: сработала аппаратная защита, в журнале — что видели датчики в этот момент (или «причина не видна»). Если до этого поднять ph примерно до 70 % (около 33 бар — ещё не авария по давлению), в причине будет «высокое давление».

Смотрите также

← Все примеры галереи

Схема
Проект из галереи — запускать можно, менять нельзя.

      
Сборка ещё не запускалась.

    Печатайте в Serial числа — они станут графиком. Serial.println(t); — один ряд, Serial.printf("t:%.1f h:%.1f\n", t, h); — два с подписями. Формат тот же, что понимает плоттер Arduino IDE.