Термостат для рассады на подоконнике я собрал за один вечер: коробка с плёнкой, лампа накаливания на сорок ватт в роли обогрева, DHT22 и релейный модуль. Уставка была одна — 24 градуса. Через сутки я поймал себя на том, что считаю щелчки реле, и насчитал больше десяти в минуту: лампа зажигалась, прогревала воздух на полградуса, реле выключалось, воздух за четыре-пять секунд остывал обратно — и всё по кругу. Скетч был скопирован из туториала с одной уставкой, и выглядел безупречно ровно до первого запуска.
В этом уроке — как выглядит термостат с двумя уставками: числом включения и числом выключения, которые лежат в коде двумя именованными константами. Добавим счётчик переключений и строку состояния в Serial — за вечер такой лог расскажет об автомате больше, чем мультиметр за неделю. И отдельно разберём ловушку, на которой спотыкается каждый второй: охлаждающий термостат собирают копипастой нагревательного, а гистерезис при этом обязан перевернуться.
Почему одна уставка щёлкает
У порога показания датчика не стоят: между соседними опросами они гуляют на две-три десятых градуса даже в неподвижной комнате, а у DHT11 прыгают целыми градусами. С одной уставкой каждое чтение — отдельное голосование: 23,8 — включить, 24,2 — выключить, 23,9 — снова включить. Реле исполняет каждый вердикт: щелчок, пусковой ток лампы, помеха в питание платы. Ночью этот стрекот слышен через дверь, а контакты реле вырабатывают ресурс в сотни раз быстрее расчётного.
С двумя уставками голосование одно: решение может перевернуть только чтение, пробежавшее окно целиком. Короткие шаги на две-три десятых окно не проходят, и реле молчит. Базовую механику мы собирали в уроке про термостат с гистерезисом, а цену каждого лишнего щелчка — износ контактов и выбор ширины коридора под шум конкретного датчика — считали в уроке про стрекот реле. Здесь я переношу тот же принцип на язык двух уставок, потому что с ним удобнее спорить и отлаживать: числа видны, а не спрятаны в арифметике.
Отдельный бонус двух уставок — читаемость порогов посторонним человеком. Печатаете обе цифры в шапке лога при старте — и через полгода, вернувшись к проекту, видите не формулу с вычитанием, а два бытовых утверждения: включай при двадцати трёх, выключай при двадцати пяти. С этим легко свериться по любому бытовому термометру, легко объяснить домочадцам, почему реле обязано молчать в этом коридоре, и легко заметить, что кто-то крутил значения до вашего возвращения.
Две уставки и перевёрнутый гистерезис
Для нагрева правило звучит так: включаем, когда температура упала ниже нижней границы, выключаем, когда поднялась выше верхней. В коде это две константы — T_ON = 23.0 и T_OFF = 25.0 — и одна переменная состояния, которая помнит, что реле делает прямо сейчас. Между границами автомат ни о чём не решает: он держит последнее решение, каким бы ни было показание.
У охлаждения всё то же самое, но в зеркале: включаем выше верхней границы, выключаем ниже нижней. Скопировать нагревательный if для вытяжки или вентилятора и не перевернуть границы — классическая промашка: автомат начинает включать охлаждение, когда холодно, и выключать, когда жарко, то есть работать ровно наоборот. Мы собирали вентиляторный автомат в уроке про вытяжку — там инверсия сделана нарочито и видна в коде. Правило одно для обоих направлений: включение на внешней границе, выключение на внутренней, между ними реле молчит.
Ещё один угол, под которым стоит посмотреть на две уставки: они превращают гистерезис из заклинания в измеримый зазор. Ширина окна — единственное число, которое вы подбираете под систему, и при отладке его удобно вынести в отдельную константу, оставив центр на месте. Я держу ширину ползунком в период настройки и «вмораживаю» её обратно в T_ON и T_OFF, когда автомат отлажен: в коде остаётся минимум живых чисел, а не формула на каждое чтение.
#include <DHT.h> DHT dht(2, DHT22); const int RELAY = 7; // релейный модульconst float T_ON = 23.0; // ниже — включаем обогревconst float T_OFF = 25.0; // выше — выключаем. Окно 2 градусаconst unsigned long PERIOD = 2000; unsigned long lastPoll = 0;bool heating = false; // текущее состояние автоматаint vklyucheniy = 0; // счётчик переключений void setup() { Serial.begin(9600); pinMode(RELAY, OUTPUT); digitalWrite(RELAY, LOW); dht.begin(); Serial.print("ustavki: on "); Serial.print(T_ON, 1); Serial.print(" / off "); Serial.println(T_OFF, 1);} void loop() { if (millis() - lastPoll < PERIOD) return; lastPoll = millis(); float t = dht.readTemperature(); if (isnan(t)) { Serial.println("net chteniya - reshenie otlozheno"); return; } if (!heating && t <= T_ON) { heating = true; vklyucheniy++; digitalWrite(RELAY, HIGH); } else if (heating && t >= T_OFF) { heating = false; digitalWrite(RELAY, LOW); } Serial.print("t="); Serial.print(t, 1); Serial.print(" on="); Serial.print(T_ON, 1); Serial.print(" off="); Serial.print(T_OFF, 1); Serial.print(" -> "); if (heating) Serial.print("greev"); else Serial.print("tishina"); Serial.print(" ciklov "); Serial.println(vklyucheniy);}Строка net chteniya в логе — важная деталь: при срыве чтения автомат не меняет решение, а просто откладывает его до следующего опроса. Слепое реле опаснее молчащего. Что происходит при длинной серии таких срывов и как автоматика переживает их без паники — отдельная тема урока про диагностику nan и третьего урока этого кластера.
Счётчик vklyucheniy — это протокол испытаний в одной цифре. У здорового термостата с окном в два градуса и лампой в сорок ватт счётчик растёт на единицы-десятки за вечер; если он летит десятками в час — окно узкое для этой пары «нагрузка плюс объём», и его стоит расширить. А строка состояния, печатаемая каждый опрос, превращает отладку в чтение: видно и порог, и решение, и то, как быстро они меняются.
Одна практическая деталь формата: я печатаю числа через пробелы и знаки равенства, потому что такой лог режется по столбцам любым инструментом — от awk до формулы в электронной таблице. Красивые строки с текстовыми словами — для глаз, а для расчётов лучше скука из чисел. Уставки печатаю вместе с каждым показанием, а не один раз в шапке: каждая строка сама себе документ, и обрезок лога из середины ночи читается без оглядки на начало.
Две мелочи про жизнь автомата после перезапуска. Плата перезагружается не только от кнопки reset: открытие монитора дёргает DTR и скетч стартует заново — переменная heating обнуляется, реле стоит в LOW до первого честного чтения, то есть один период тишины гарантирован. Для рассады это безразлично, а в инкубаторе такое поведение на руку: первый же опрос ниже T_ON включает обогрев заново, без ожиданий. Вторая мелочь — сравнения в if не случайно нестрогие: t <= T_ON и t >= T_OFF. Точное равенство по float не срабатывает практически никогда — показания ходят на десятые доли, и ветка с двойным равенством превращается в мёртвый код.
| Симптом в Serial | Диагноз | Что править |
|---|---|---|
| Одно и то же t, режим меняется каждый опрос | Окно уже, чем дыхание датчика на границе | Расширить окно до 2 градусов и шире |
| Счётчик циклов растёт десятками в час | Окно не под эту пару «нагрузка плюс объём» | Расширить окно или упредить инерцию нагрузки |
| Реле щёлкает само, температура далеко от уставок | Наводки, питание, плохой контакт линии | Проверить линию по чек-листу диагностики |
| Строки net chteniya в логе | Срыв чтения: решение отложено, реле молчит | Искать железную причину, логику не трогать |
Числа уставок берутся из задачи, а не из головы автомата. Нижняя граница — та температура, ниже которой рассаде (или закваске, или черенкам) уже плохо; верхняя — где ей жарко. Окно между ними — плата за тишину: чем инертнее нагрузка, тем шире окно имеет смысл ставить. Лампа накаливания разгоняется за секунды — ей хватает узкого окна; масляному радиатору ставьте два-три градуса, он всё равно остывает полдня. Если сомневаетесь между двумя ширинами, берите шире: лишние полградуса окна стоят пары лишних минут на прогрев, а узкое окно — сотен лишних щелчков за сезон.
И последняя роскошь, которую дают две уставки в одном месте: если уставки хочется менять с кнопок или сохранять между включениями, они переезжают в EEPROM одной строкой каждая — мы разбирали это в уроке про пороги в EEPROM. Пока их достаточно печатать в шапке лога при старте: строка ustawki в мониторе — это шапка протокола испытаний, которая всегда под рукой.
Финальная проверка автомата занимает ночь и ничего не стоит. Запустите его с распечаткой лога, утром посчитайте строки greev: у здорового настольного термостата их единицы-десятки, реле молчит часами, а температура ходит по коридору мягкой пилой. Если вместо этого утром в счётчике сотни — не трогайте железо, сначала расширьте окно вдвое и повторите ночь. Вторая ночь с сотнями означает, что датчик стоит в потоке от самой лампы: перенесите его на противоположную стенку коробки, где воздух уже перемешался, и третья ночь обычно становится первой спокойной.
Куда двигаться дальше, когда комната и обогрев уже под контролем: собрать оба направления в одном автомате. Четыре уставки — T_HEAT_ON, T_HEAT_OFF, T_COOL_ON, T_COOL_OFF — и обязательный зазор в один-два градуса между выключением нагрева и включением охлаждения. Без зазора каналы дерутся: лампа догревает воздух, вытяжка тут же сливает его в трубу, счётчики растут, а климат стоит на месте. Драку видно по раздельным счётчикам циклов, поэтому их заводят парой — по одному на каждый канал, а не одним общим числом.
- 1. Почему термостат с одной уставкой щёлкает у порога?
- 2. Что делает автомат, пока температура находится внутри окна между уставками?
- 3. Скопировали скетч обогревателя под вытяжку и не перевернули уставки. Что увидите?
- 4. Комнатный термостат на DHT22, дыхание показаний — две-три десятых. Какое окно разумно?
- 5. Счётчик переключений показывает сотни щелчков за сутки. Первый вывод?
- Две уставки — два именованных числа: включение на внешней границе, выключение на внутренней, между ними реле молчит.
- У нагрева T_ON ниже T_OFF, у охлаждения наоборот — копипасту из обогревателя проверяют направлением первым делом.
- Строка состояния в Serial — показание, обе уставки, решение, счётчик: лог становится протоколом испытаний.
- Окно назначают по системе: на порядок шире дыхания показаний; инертной нагрузке — ещё шире.
- Счётчик переключений — метрика здоровья: единицы-десятки за вечер нормально, десятки в час — окно узкое.
Частые вопросы по теме урока
- Почему термостат с одной уставкой щёлкает у порога?
- Одна уставка заставляет реле исполнять вердикт каждого чтения. Дыхание показаний на границе превращается в серию щелчков, пусковых токов и износа. Показания дышат на две-три десятых от опроса к опросу, и каждое переворачивает решение
- Что делает автомат, пока температура находится внутри окна между уставками?
- Окно — зона без решений: пока воздух не пробежал его целиком, реле держит прежнее состояние. Поэтому короткие шаги датчика ничего не переключают. Держит последнее решение и молчит
- Скопировали скетч обогревателя под вытяжку и не перевернули уставки. Что увидите?
- У охлаждения гистерезис зеркальный: включение выше верхней границы, выключение ниже нижней. Неперевернутые уставки дают автомат-перевёртыш. Автомат включается при жаре и выключается при холоде — работает против задачи
- Комнатный термостат на DHT22, дыхание показаний — две-три десятых. Какое окно разумно?
- Окно назначают на порядок шире межопросного дыхания. Для комнаты это полтора-два градуса; пять — уже лишние щелчки и раскачка климата. Полтора-два градуса: на порядок шире дыхания показаний
- Счётчик переключений показывает сотни щелчков за сутки. Первый вывод?
- Сотни за сутки — признак узкого окна или датчика в потоке горячего воздуха. Сначала расширяют окно, потом смотрят на размещение. Окно мало для этой системы — расширить