Спор «где в квартире холоднее» у нас длился до первого скетча: детская на северо-западной стороне, спальня на юге, и каждый вечер обе стороны конфликта приводили в доказательство собственную руку. Рука — плохой термометр, а вот два DHT22 по копеечному прайсу решают спор окончательно. Базу про несколько датчиков на одной плате мы уже разбирали в уроке про комнаты и зоны: свой пин, свой объект, разнесённый опрос. Сегодня следующий этаж — суд: насколько вообще можно верить разнице двух показаний, и что сделать, чтобы верить ей осознанно.
Подвох в том, что даже два свежих DHT22 из одной партии показывают в одном месте различие в две-пять десятых градуса: паспортная погрешность ±0,5 °C у каждого, и перекос экземпляров складывается, а не вычитается. Поэтому строка «детская холоднее на 0,3» — не результат измерения, а шум, и принимать по ней решения — значит автоматизировать самообман. Лекарств три: усреднение по пяти чтениям, которое сжимает дрожь, поправка на перекос конкретной пары и порог решений, втрое шире погрешности.
План урока: скетч с двумя объектами на пинах 2 и 4, попарный вывод обеих комнат и дельты, кольцевая пятёрка чтений на комнату, автомат «перемещение тепла» — реле вентилятора, который гонит тепло из тёплой комнаты в холодную, когда разница переваливает за два градуса. Плюс две грабли длинной линии: почему дальний датчик отвечает через раз и что ставят у него на питании.
Пятёрка чтений и честное сравнение
Усреднение устроено проще, чем звучит: кольцевой массив на пять слотов на каждую комнату, каждые две секунды новое чтение записывается в свой слот, среднее пересчитывается по всем пяти. Полное обновление среднего занимает десять секунд — климат комнаты меняется на масштабе минут, поэтому задержка невидима, а выигрыш конкретен: одиночное чтение DHT22 дрожит на одну-три десятых, среднее пятёрки — на одну десятую. В уроке про медиану тот же приём сделан устойчивее к выбросам — медиана выбрасывает дикий кадр целиком, среднее размазывает его на пять строк; для комнат, где выбросы редки, хватает и среднего.
Дельта между комнатами — валюта всех решений этого скетча, и в неё стоит вглядеться отдельно. Ради неё я и развёл датчики по комнатам: сам по себе номер 23,4 мало о чём говорит, а разница 23,4 против 20,9 — это уже найденные два с половиной градуса, которые батарея потратила, а дальняя комната не получила. Дельта по средним пятёрок живёт спокойной жизнью: ночью за закрытыми дверями она подрастает, к полудню после проветривания садится почти до нуля — по этой кривой суточный режим квартиры виден лучше, чем по любому одиночному термометру.
Поправку на перекос пары даёт сверка, которую я называю «объятие»: раз в месяц оба датчика ложатся рядом на один стол на час, средние за час сравниваются, разница фиксируется как offset и вычитается в скетче. Датчик, показывающий на 0,4 больше соседа, после поправки перестаёт приписывать своей комнате несуществующее тепло. Без сверки сравнение всегда врёт в пользу того экземпляра, который врёт вверх, — и никакой порог в два градуса этого не скроет, если решать надо на границе единицы. Методику сверки с внешним эталоном, а не только друг с другом, разобрал урок про калибровку.
Вывод обеих комнат — одной строкой: комнатное среднее, второе среднее, дельта и состояние вентилятора. Такая строка читается с листа и красиво падает в Serial Plotter двумя рядами — о том, как график строится прямо из чисел в мониторе, писал урок про Serial Plotter. На LCD 16×2 та же пара ложится по строке на комнату с дельтой внизу — дисплейная часть без изменений переносится из урока про термогигрометр.
Длинный провод: 100 нФ у самого датчика
Геометрия квартиры внесла правку в идеальную схему: спальня дальше кладовки с платой, и линия датчика потянула три метра. Первый же вечер — пропуски через раз: спальня то отвечает, то молчит, детская на двадцати сантиметрах хвоста работает идеально. Причина не в библиотеке и не в экземпляре: интерфейс DHT — однопроводной с жёсткими таймингами, фронты сигнала на длинной линии затупляются от наводок и ёмкости провода, и на двух-трёх метрах датчик начинает срываться спорадически. Форумные ветки про «DHT22 работает через раз» почти всегда заканчиваются этой диагностикой.
Лечение стоит рубль и ставится за минуту: керамический конденсатор 100 нФ между питанием и землёй прямо у ножек датчика — не у платы. Он глотает наводки по питанию там, где они доходят до чувствительной электроники сенсора. Подтяжку 10 кОм на линии данных я тоже переставил к дальнему концу — у сенсора, а не у колодки, — провод протянул цельным без скруток, и после этого ноль пропусков за неделю наблюдений на тех же трёх метрах. Питание для дальнего датчика при возможности ведите отдельной парой — общая коса с линией данных добавляет наводок, о которых датчик сообщает пропусками.
Различать виноватых помогает простая процедура. Пропуски, nan, через раз — это линия: смотрите длину, конденсатор, подтяжку и цельность провода. Оба датчика читаются, но один стабильно врёт на градус-полтора — это место установки: сквозняк от двери, батарея под окном, полка над техникой. Сдвиг в две-пять десятых у исправной пары — это экземпляр, и он лечится поправкой offset, а не заменой. Чек-лист монтажа и подтяжки по пунктам лежит в уроке про монтаж.
Автомат «перемещение тепла»
#include <DHT.h> DHT dhtRoom1(2, DHT22); // детская, короткий хвостDHT dhtRoom2(4, DHT22); // спальня, линия 3 м: 100 нФ у датчика, подтяжка у сенсора const int PIN_FAN = 7; // реле дверного вентилятораconst float FAN_ON = 2.0; // разница больше двух — гоним теплоconst float FAN_OFF = 1.0; // сошлось меньше чем на градус — хватит const int N = 5; // пятёрка чтений на комнатуfloat buf1[N], buf2[N];int idx = 0;bool filled = false;bool fan = false;unsigned long lastPoll = 0; float avg(const float *b) { float s = 0; for (int i = 0; i < N; i++) s += b[i]; return s / N;} void setup() { Serial.begin(9600); dhtRoom1.begin(); dhtRoom2.begin(); pinMode(PIN_FAN, OUTPUT); digitalWrite(PIN_FAN, LOW); for (int i = 0; i < N; i++) { // старт с реальных чисел, не с нулей buf1[i] = dhtRoom1.readTemperature(); buf2[i] = dhtRoom2.readTemperature(); delay(2000); // сенсор отвечает не чаще раза в 2 с }} void loop() { if (millis() - lastPoll < 2000) return; lastPoll = millis(); float t1 = dhtRoom1.readTemperature(); float t2 = dhtRoom2.readTemperature(); if (isnan(t1) || isnan(t2)) { Serial.println("skip: chtenie sorvalos"); return; } buf1[idx] = t1; buf2[idx] = t2; idx = (idx + 1) % N; if (idx == 0) filled = true; if (!filled) { Serial.println("nabiraem pyaterku..."); return; } float m1 = avg(buf1); float m2 = avg(buf2); float d = m1 - m2; // поправку offset вычтите здесь if (d > FAN_ON) fan = true; // гистерезис против щёлканья if (d < FAN_OFF) fan = false; digitalWrite(PIN_FAN, fan ? HIGH : LOW); Serial.print("r1="); Serial.print(m1, 1); Serial.print(" r2="); Serial.print(m2, 1); Serial.print(" d="); Serial.print(d, 1); Serial.print(" fan="); Serial.println(fan ? "ON" : "off");}Пороги выбраны не на глаз. Включение на разнице больше двух градусов — вчетверо шире дрожи среднего пятёрки и вдвое шире худшего перекоса пары: решение физически не может принять шум за сигнал. Выключение на единице — гистерезис в целый градус, чтобы вентилятор не щёлкал на границе; автоматом управляет та же механика двух порогов, что и у всякого реле в этом разделе. Реакция всего контура — минуты: пятёрка обновляется за десять секунд, воздух в комнатах выравнивается дольше, и спешить тут некуда.
Обратите внимание на старт: до первого полного заполнения пятёрки автомат молчит и печатает nabiraem pyaterku. Десять секунд blindness при включении — честная цена среднего; альтернатива — решать по первому же чтению с его дрожью в три десятых, и все пороги приходится раздувать. В setup буферы забиваются первыми пятью реальными чтениями с честной паузой delay(2000) между ними: стартовое среднее с нулями или с одним и тем же числом в пяти слотах дало бы ложную дельту на первые минуты.
| Наблюдение | Что это значит | Как поступить |
|---|---|---|
| разница средних меньше 0,5 °C | в пределах перекоса экземпляров | вывода нет: это шум пары, не климат комнат |
| разница 0,5–2 °C | реальный, но слабый перекос | следить в логе и на графике, автомат молчит |
| разница устойчиво больше 2 °C | настоящий перекос комнат | реле гонит тепло в холодную, гистерезис выключит ниже 1 °C |
| одна строка стабильно сдвинута на 1–2 °C | место установки: сквозняк, батарея, техника | перенести датчик, а не править скетч |
Процедура «кто виноват» проверяется перестановкой. Поменяйте датчики местами физически и подождите полчаса: сдвиг уехал вместе с датчиком — это экземпляр, вычтите offset; сдвиг остался в комнате — это место, ищите батарею и сквозняк; появились пропуски — это линия, возвращайтесь к конденсатору. Три испытания за вечер закрывают все три источника перекоса, и спор о том, кто врёт, больше не требует мнений.
Сам автомат «перемещение тепла» — скромный по железу: реле и любой вентилятор в дверном проёме или переточном канале. Он не греет и не охлаждает — он отменяет разницу, и зимой это заметно бьёт в счётчики: тепло, которое батарея уже потратила, перестаёт копиться в одной комнате. Механику вытяжного вентилятора с его воздухообменом и обратным клапаном я разбирал в уроке про вытяжку — там же про то, почему вентилятору нужен свой блок питания, а не пин платы.
Куда расти дальше: вывод обеих комнат на LCD с дельтой в нижней строке, два ряда в Serial Plotter, чтобы видеть суточные ритмы каждой комнаты, и медиана вместо среднего, если в квартире появится источник выбросов. Датчики в комнатах — это первый шаг к дому, где вместо «мне кажется» в каждой войне за термостат участвует лог.
- 1. Два новых DHT22 из одной партии на одном столе показывают 24,1 и 24,6. Что это?
- 2. Зачем конденсатор 100 нФ ставят именно у датчика на длинной линии?
- 3. Среднее по пяти чтениям обновляется каждые 2 секунды. Когда оно полностью сменится новыми данными?
- 4. Разница средних достигла 2,3 °C, вентилятор включился. Когда он выключится?
- 5. Один датчик систематически показывает на 1,5 °C теплее второго. С чего начать поиск?
- Перекос экземпляров ±0,5 °C — паспортная норма пары: сравнение без поправки offset врёт в пользу того, кто врёт вверх.
- Кольцевая пятёрка чтений: дрожь одиночного кадра сжимается до одной десятой, полное обновление — десять секунд.
- Дальний датчик на линии 2–3 м лечится 100 нФ у ножек и подтяжкой у сенсора: интерфейс DHT длинных линий не прощает.
- Автомат «перемещение тепла»: включение на разнице больше 2 °C, выключение ниже 1 °C — пороги втрое шире шума.
- Диагностика «кто виноват» — перестановкой: уехал с датчиком — экземпляр, остался в комнате — место, пропуски — линия.
Частые вопросы по теме урока
- Два новых DHT22 из одной партии на одном столе показывают 24,1 и 24,6. Что это?
- Погрешность ±0,5 °C у каждого экземпляра складывается в перекос пары до градуса. Замена не лечит — лечит сверка «объятие» и поправка offset в скетче. Паспортный перекос экземпляров: ±0,5 °C у каждого, учитывается поправкой
- Зачем конденсатор 100 нФ ставят именно у датчика на длинной линии?
- Керамика 100 нФ между VCC и GND у ножек сенсора срезает наводки по питанию. У платы она бесполезна: помехи доходят до датчика по проводу, и фильтр должен стоять у потребителя. Чтобы глотать наводки по питанию там, где они доходят до электроники сенсора
- Среднее по пяти чтениям обновляется каждые 2 секунды. Когда оно полностью сменится новыми данными?
- Каждый такт в среднее встаёт одно новое чтение из пяти: полное обновление — пять тактов по две секунды, десять секунд. Для климата комнат это мгновение. Через 10 секунд
- Разница средних достигла 2,3 °C, вентилятор включился. Когда он выключится?
- Порог выключения сознательно отнесён от порога включения: на границе дрожь показаний иначе заставила бы реле щёлкать. Один градус гистерезиса шире любого шума среднего. Когда разница упадёт ниже 1,0: гистерезис в целый градус
- Один датчик систематически показывает на 1,5 °C теплее второго. С чего начать поиск?
- Перестановка различает виноватых: сдвиг уехал с датчиком — экземпляр, остался в комнате — место установки, добавились пропуски — линия. Три проверки вместо догадок. Поменять датчики местами и посмотреть, уехал ли сдвиг