Инкубатор из моего прошлого опыта — коробка из пенопласта, лампа на 40 ватт, термостат на DHT22 — довёл первую кладку до вывода, и я уже почил на лаврах. Лавры кончились в июне, когда короб переехал на утеплённую лоджию: солнце через окно догревало лучше сорокаваттки, лампа была выключена полдня, а термометр всё равно полз от 38,2 к 38,8. Термостат честно делал свою работу — но его работа умела только одно направление: вниз. Выключить нагрев — не значит охладить. Когда тепло приходит само, без розетки, автоматике нужен второй канал, который это тепло стравит.
Кулер я отмёл сразу: струя по яйцам сгоняет с скорлупы тёплую воздушную плёнку и сушит её — в промышленных машинах вентилятор перемешивает весь объём, а не дует точечно, и повторить это в пенопластовой коробке без отрицательного эффекта я не сумел. Осталось пассивное решение: щель в крышке пять на пять сантиметров, прикрытая лёгкой створкой из того же пенопласта. Стравливать перегрев через щель — то же самое, что приоткрыть форточку в душной комнате: медленно, без сквозняка по кладке, но неуклонно. Открывать створку выпросил серво SG90: ход в сорок градусов, тяга с трёхкратным запасом для створки весом в десять граммов.
Итоговая раскладка каналов такая: DHT22 на пине 2 измеряет, реле на пине 7 с лампой греет, серво на пине 11 приоткрывает форточку. Паспорт инкубации — 37,5–38,0 °C и влажность 55 % первые восемнадцать дней: ниже нижней границы греем, выше 38,5 открываем щель. Весь этот урок — не про железо, а про договор между двумя каналами: два независимых регулятора на одном датчике без общих правил дерутся так, что лог превращается в пинг-понг каждые полминуты.
Война каналов и мёртвая зона
Сначала я собрал наивную схему: реле греет ниже 38,0, серво открывает выше 38,0 — два независимых «если», вместе они и составляли всю политику. Дальше — дословная хроника одного утреннего часа: лампа погасла на 38,0, короб по инерции дошёл до 38,3, серво открыла щель; сквозняк сверху снял полградуса за несколько минут, датчик увидел 37,9, реле зажгло лампу; лампа плюс щель вернули короб на 38,2 — и всё по кругу. За час реле щёлкнуло одиннадцать раз, редуктор серво прошёл свой ход столько же, а температура за это время ни разу не задержалась внутри коридора дольше пяти минут.
Лекарство из климатотехники — мёртвая зона шире, чем шум сенсора плюс инерция короба. Моя раскладка: реле включается ниже 37,5 и выключается выше 38,5; серво начинает открывать выше 38,5 и полностью закрывается ниже 37,5. Между 37,5 и 38,5 лежит градус тишины, в котором не движется ни лампа, ни створка. Шум DHT22 между опросами — две-четыре десятых градуса — зону физически не перепрыгивает: чтобы сменился режим, воздух обязан пройти её целиком, а это минуты, а не опросы.
Общий разнос каналов на примере обогревателя против кулера разобран в уроке про два канала климата, механика одиночного окна с двумя порогами — в уроке про клацанье реле. Здесь отличие от обеих задач: перегрев в инкубаторе страшнее недогрева — при 39,0 кладка гибнет за считаные часы, при 37,0 эмбрион замирает за сутки и больше, — поэтому канал серво стоит ставить ближе к уставке, чем подсказывает симметрия: его задача поймать первый же выброс, а не дожидаться красивой статистики.
Скетч: реле как тумблер, серва как полоса
#include <DHT.h>#include <Servo.h> DHT dht(2, DHT22);Servo vent; const int PIN_RELAY = 7;const int PIN_SERVO = 11; const float T_HEAT_ON = 37.5; // ниже — зажигаем лампуconst float T_HEAT_OFF = 38.5; // выше — гасим, между — состояние без измененийconst float T_VENT_ON = 38.5; // выше — начинаем открыватьconst float T_VENT_OFF = 37.5; // ниже — закрываем полностьюconst float VENT_FULL = 39.5; // при этом перегреве — полный ход створки const float VENT_MAX_ANGLE = 70.0; // упор вместо паспортных 180 bool heating = false;float ventAngle = 0.0;unsigned long lastPoll = 0; void setup() { Serial.begin(9600); pinMode(PIN_RELAY, OUTPUT); digitalWrite(PIN_RELAY, LOW); vent.attach(PIN_SERVO); vent.write(0); dht.begin(); Serial.println("t | heat | vent");} void loop() { if (millis() - lastPoll < 2000) return; // DHT22 отвечает раз в две секунды lastPoll = millis(); float t = dht.readTemperature(); if (isnan(t)) { Serial.println("chtenie sorvalos, reshenie ne menjajem"); return; } // Канал тепла: тумблер с двумя порогами if (t < T_HEAT_ON) heating = true; if (t > T_HEAT_OFF) heating = false; digitalWrite(PIN_RELAY, heating ? HIGH : LOW); // Канал форточки: угол растёт вместе с перегревом if (t > T_VENT_ON) { float p = (t - T_VENT_ON) / (VENT_FULL - T_VENT_ON); p = constrain(p, 0.0, 1.0); ventAngle = p * VENT_MAX_ANGLE; } else if (t < T_VENT_OFF) { ventAngle = 0.0; } vent.write((int)ventAngle); Serial.print(t, 1); Serial.print(" | heat="); Serial.print(heating ? "ON" : "off"); Serial.print(" | vent="); Serial.println((int)ventAngle);}Почему каналы построены по-разному. Лампа дозировать не умеет: она либо греет всей своей сороковкой, либо выключена — отсюда тумблер с двумя порогами, привычная механика одиночного термостата. Форточка дозировать умеет: щель в два миллиметра стравливает одно количество тепла, сантиметровая — совсем другое, поэтому угол серво в скетче растёт вместе с перегревом: при 38,6 это узкая щель около семи градусов поворота, при 39,0 — тридцать пять, дальше 39,5 — полный ход семьдесят. Это половина пропорционального регулятора, а полный разбор полосы — с выбором её ширины и упорами — сделан в уроке про форточку теплицы.
Второе решение, которое стоит проговорить: оба канала решают по одной цифре. Одно чтение за такт, один t — и реле, и створка судят по нему. Два чтения подряд дали бы две разные цифры — шум датчика в две-четыре десятых никуда не делся бы, — и каналы начали бы управляться по разным мирам: лампа верит одному числу, створка другому. Сам такт в две секунды диктует сенсор, а не вкус: быстрее физически нельзя, и это разобрано в уроке про интервал опроса.
Таймер держится на millis, а не на delay, хотя скетч пока занят только климатом: первая же добавка — предохранительный зуммер, счётчик щелчков реле, лог на SD — встанет в тот же цикл без переделки, а delay(2000) её бы оглушал на каждой итерации. Привычка обходиться без блокировки разобрана в уроке про millis вместо delay — здесь она окупается на первом же расширении.
В симуляторе руку с ползунком заменяет физика короба: воздух сам себя не греет и не остывает, поэтому тянуть температуру приходится вам. На живом коробе после гашения лампы график ещё полминуты ползёт вверх — короб запас тепло, и форточка, начавшая открываться на 38,5, встречает этот подъём уже открытой щелью. Приём для проверки зоны на реальном железе: добавьте в строку лога возраст состояния каждого канала — сколько секунд реле в текущем положении и сколько створка. Здоровый инкубатор показывает возраст минутами; если счётчик реле обнуляется чаще, чем раз в минуту, зона узка.
Там же, в логе, живёт мой любимый счётчик — щелчки реле за ночь. Короб с исправной зоной даёт единицы включений за тёмное время: воздух в утеплённом пенопласте почти не меняется. Десятки щелчков в час — это не «точнее работает», это война каналов в терминальной стадии: редуктор серво и контакты реле изнашиваются, а коридор всё равно держится хуже, чем при одном градусе тишины.
| Температура | Реле лампы | Серво форточки | Что происходит в коробе |
|---|---|---|---|
| ниже 37,5 °C | включено | закрыто, 0° | недогрев: лампа догоняет, форточка не мешает |
| 37,5–38,5 °C | как было | как было | мёртвая зона: оба канала молчат, воздух идёт к уставке |
| 38,5–39,5 °C | выключено | щель 0–70° по перегреву | лишнее тепло стравливается пассивно, без сквозняка по яйцам |
| выше 39,5 °C | выключено | полный ход, 70° | авария: прикрыта независимым зуммером-предохранителем |
Влажность, переворот и независимый предохранитель
Влажность 55 % — вторая строка паспорта инкубации, и DHT22 её честно видит. Но управлять ею сервой нельзя: рычаг влажности — площадь мокрой поверхности в поддоне, а не створка. Хуже того, форточка и влажность тянут канат в разные стороны: каждая открытая щель сушит воздух, и при 55 % внизу и перегреве сверху автоматике придётся выбирать, что важнее. Мой выбор — жертвовать влажностью: перегрев убивает за часы, сухость за часы не убивает ничего. Тактику работы с влагой как величиной — через точки росы, а не через проценты — разложил урок про осушение.
Переворот яиц четыре-шесть раз в сутки — вторая серво и отдельный таймер на millis. В скетч этого урока её сознательно не ставил: третий канал на том же датчике превращает учебную развилку в кашу, а механика отдельного канала с таймером ничем не отличается от термостата из базового раздела. Соберёте — лог переворотов пишите в тот же Serial отдельной строкой, чтобы ночью по бумаге видеть, спит ли таймер.
И главное, что стоит прикрутить к этому скетчу в первую же ночь: независимый предохранитель. Отдельный зуммер и отдельная проверка «если t выше 39,0 — орать», которая не делит с регулятором ни переменных, ни логики: если главный скетч завис, если датчик умер и вернул последнее значение навсегда, простая параллельная проверка молчит вместе с ними — поэтому в серьёзных самодельных инкубаторах рядом со скетчем ставят второй биметаллический термостат или хотя бы зуммер на собственном сравнении. Голос тревоги и его ритмы — в уроке про зуммер и пороги.
- 1. Зачем между реле нагрева и сервой форточки мёртвая зона?
- 2. Реле включается ниже 37,5 и выключается выше 38,5. Датчик показал 38,1, нагрев сейчас работает. Что делает реле?
- 3. Чем определяется угол серво в скетче?
- 4. Что для кладки опаснее и почему?
- 5. Зачем отдельный зуммер на 39,0 °C, если регулятор уже открывает форточку?
- Два канала на одном датчике без договора дерутся: пинг-понг, одиннадцать щелчков реле в час, ноль пользы.
- Мёртвая зона 37,5–38,5: реле включается ниже, выключается выше; серво зеркально. Внутри — тишина.
- Реле — тумблер (лампа не дозирует), серва — пропорциональная полоса 38,5–39,5 с упором на 70°.
- Один опрос — одна цифра — два решения: каналы не должны судить по разным чтениям.
- Влажность 55 % не реле серво, а поддон с водой; независимый зуммер на 39,0 — предохранитель против смерти главного скетча.
Частые вопросы по теме урока
- Зачем между реле нагрева и сервой форточки мёртвая зона?
- Зона в один градус шире шума DHT22 в две-четыре десятых: чтобы сменился режим, воздух обязан пройти её целиком. Без неё каналы дёргаются на каждом колебании показаний. Чтобы оба канала молчали в коридоре, а шум сенсора не мог сменить режим
- Реле включается ниже 37,5 и выключается выше 38,5. Датчик показал 38,1, нагрев сейчас работает. Что делает реле?
- Гистерезис держит решение: выключение произойдёт только выше 38,5. Внутри зоны оба канала хранят своё состояние, сколько бы ни шумело показание. Продолжает греть: внутри мёртвой зоны состояние не меняется
- Чем определяется угол серво в скетче?
- Форточка дозирует: угол растёт вместе с перегревом от нуля на 38,5 до полного хода 70° у 39,5. Это пропорциональный канал против тумблера реле. Размером перегрева внутри полосы от 38,5 до 39,5 °C
- Что для кладки опаснее и почему?
- Перегрев необратим и быстр: выше 39,0 счёт идёт на часы. Недогрев при 37,0 замирает эмбрион на сутки и больше. Асимметрия диктует канал серво ставить ближе к уставке. Перегрев: при 39,0 кладка гибнет за считаные часы
- Зачем отдельный зуммер на 39,0 °C, если регулятор уже открывает форточку?
- Форточка — канал регулятора: если скетч завис или датчик умер, она молчит вместе с ним. Параллельная простая проверка на 39,0 — последняя линия, которая не делит судьбу с главным кодом. Чтобы слышать тревогу из другой комнаты при аварийном перегреве