Термостат на Arduino с DHT22: реле и гистерезис
Термостат — первый проект, где датчик превращается в регулятор: DHT22 меряет температуру, а реле включает обогрев, когда стало холодно, и выключает, когда прогрелось. Наивная реализация «если меньше 18 — включить» работает плохо: температура у порога колеблется на десятые доли градуса, и реле клацает каждые полминуты, выжигая контактную группу и раздражая звуком. Правильный термостат держит две уставки — включение при 18,0, выключение при 19,5 — и этот зазор в полтора градуса называется гистерезисом.
В нашем симуляторе термостат собирается из двух карточек палитры «Макетка»: DHT-датчик с ползунком температуры и модуль реле, который щёлкает и зажигает индикатор при срабатывании. Рантайм исполняет DHT22 по-настоящему — readTemperature с характерной дрожью в десятую градуса — и digitalWrite на реле. Ниже — проверенный скетч с разбором и таблица того, что остаётся за железом.
Две уставки вместо одной: зачем нужен гистерезис
Логика термостата с гистерезисом асимметрична по определению: включаем обогрев, когда температура упала ниже 18,0, а выключаем только когда поднялась выше 19,5. Между 18,0 и 19,5 — «мёртвая зона», в которой система ничего не делает и держит предыдущее состояние. Обогрев остывает не мгновенно, поэтому температура доезжает до середины зоны уже после выключения реле — и не возвращается к порогу через три секунды.
Второй обязательный приём — правильный старт реле. Модуль реле почти всегда активен LOW: LOW на входе — контакт замкнут, HIGH — разомкнут. Если первым делом вызвать pinMode(7, OUTPUT), пин выдаст LOW — и обогрев включится на долю секунды при каждой загрузке. Порядок лечения: сначала digitalWrite(PIN_RELE, HIGH), и только потом pinMode — линия держится высокой ещё до настройки направления, и при старте реле молчит.
#include <DHT.h>DHT dht(2, DHT22);const int PIN_RELE = 7;const float T_NIZ = 18.0; // ниже — включаем обогревconst float T_VERH = 19.5; // выше — выключаем (гистерезис 1,5 градуса) void setup() { pinMode(PIN_RELE, OUTPUT); digitalWrite(PIN_RELE, HIGH); // активный LOW: HIGH = реле выключено dht.begin(); Serial.begin(9600);} void loop() { float t = dht.readTemperature(); if (isnan(t)) { // датчик не ответил — на плате так бывает Serial.println("dht ne otvetil"); delay(2000); return; } if (t < T_NIZ) { digitalWrite(PIN_RELE, LOW); // обогрев ВКЛ Serial.print("obogrev ON t="); Serial.println(t); } else if (t > T_VERH) { digitalWrite(PIN_RELE, HIGH); // обогрев ВЫКЛ Serial.print("obogrev OFF t="); Serial.println(t); } delay(2000); // DHT22 нельзя спрашивать чаще}Прогон в симуляторе: карточка DHT показывает свою температуру, реле-карточка щёлкает и зажигает индикатор, когда ползунок уводят ниже 18, и гаснет выше 19,5; в мёртвой зоне — между порогами — реле стоит как стояло. Serial печатает решения с десятыми долями — «obogrev OFF t=23.59», «obogrev ON t=16.02». Датчик живёт своей жизнью: показания плавают на ±0,1–0,25 градуса, как у настоящего DHT22, поэтому решения выглядят живыми, а не роботизированными.
Честная граница: что исполняет симулятор
| Проверка | Симулятор | Только железо |
|---|---|---|
| DHT dht(2, DHT22), begin, readTemperature | исполняется, тип DHT22 признаётся | то же самое |
| Дрожь показаний ±0,1–0,25 °C | есть, встроена в рантайм | то же самое, сильнее |
| digitalWrite на реле, активный LOW | исполняется, индикатор на карточке | щёлкает слышно |
| isnan(t) при отказе датчика | компилируется, но в браузере nan не случается | да — обрыв провода |
| Реальный нагрев от «обогрева» | нет: температура ведётся ползунком | да |
| Ток катушки реле и износ контактов | не моделируется | да |
Грабли: уставки, нагрузка и интервал опроса
- Гистерезис 1,5 градуса — не догма: инкубатору хватает 0,2–0,3, для пола в гараже берут 2–3. Малый зазор — частые щелчки, большой — температурные качели. Правило: зазор не меньше, чем естественные колебания комнаты за минуту.
- Температуру храните только во float: int потеряет десятые доли, порог 18,5 станет 18, а термостат начнёт щёлкать на каждом градусе. И печатайте в Serial тоже float — сразу видно, где порог.
- delay(2000) — не прихоть: DHT22 по даташиту отвечает не чаще раза в два секунды, чаще спрашивать — nan и мусор. Снижение интервала — первая причина «датчик показывает нули».
- Реле-модуль на 10 А — не для ТЭНа: ток обогревателя 2 кВт — это 9 А, на пределе. Для мощной нагрузки берите контактор, а реле оставьте для помпы, вентилятора или лампы.
- Симулятор не нагревается от «обогрева»: ползунок карточки DHT из палитры «Макетка» двигаете руками. На живой плате замкнутый цикл «нагрел — выключил — остыл» виден сам, и по нему подбирают гистерезис.