Датчик температуры и усреднение показаний
Реальные датчики врут: их показания дрожат от помех. Хороший код не верит одному замеру, а усредняет несколько.
Один замер температуры — это мнение. Среднее из десяти замеров — это уже факт. Усреднение превращает шумные данные в надёжные.
Вспомни, как ты меряешь температуру градусником: первые секунды цифры скачут, и только подождав, ты доверяешь результату. С электронными датчиками то же самое, только дрожь не от тебя, а от помех — рядом включился мотор, по проводу пробежала наводка, чуть просел блок питания. В итоге датчик, лежащий в комнате с ровной температурой 21.5°C, может выдать подряд 21.4, 21.6, потом внезапно 35.0, а затем снова 21.5. Если программа поверит каждому числу буквально, она будет дёргаться от каждого случайного скачка.
Популярный датчик температуры и влажности — DHT22, а для точной температуры — DS18B20, который работает по протоколу 1-Wire. Но какой бы датчик ни был, у всех общая проблема: показания «шумят», скачут на доли градуса от помех. Поэтому грамотный код относится к датчику как к слегка ненадёжному свидетелю: выслушивает несколько раз и делает выводы из совокупности, а не из одной фразы.
Как работает под капотом
DS18B20 датчик
+---------+
| VDD |---- 3.3V
| DATA |---- GPIO4 --[резистор 4.7к]-- 3.3V
| GND |---- GND
+---------+
|
1-Wire протокол -> цифровое значение температуры
Откуда вообще берётся шум? Сигнал от датчика идёт по проводу, а провод — это маленькая антенна: он ловит наводки от всего, что рядом излучает (зарядки, моторы, Wi-Fi). К тому же сам датчик измеряет с конечной точностью и иногда «округляет» в разные стороны. Резистор 4.7к на схеме выше (его называют подтягивающим) как раз помогает линии DATA держаться в чётком состоянии, но полностью убрать дрожь он не может — поэтому финальную чистку делает уже код.
Сырой поток: 21.4 21.6 35.0 21.5 21.3
^
выброс (наводка)
Фильтр выбросов -> усреднение -> 21.5 ровно
Чтение настоящего датчика зависит от железа и библиотек, поэтому это пример для Pi:
# на Pi: датчик DS18B20 виден как файл в /sys/bus/w1/...
from w1thermsensor import W1ThermSensor
sensor = W1ThermSensor()
print(sensor.get_temperature())
А вот сглаживание показаний — чистая логика, которую отладим в браузере. Соберём несколько замеров и посчитаем среднее, заодно отбросив явные выбросы. Попробуй сам ▶
# Усреднение шумных показаний температуры
raw = [21.4, 21.6, 35.0, 21.5, 21.3, 21.7, 21.5] # 35.0 - выброс
# 1) отбрасываем выбросы, далёкие от среднего
avg_all = sum(raw) / len(raw)
clean = [t for t in raw if abs(t - avg_all) < 5]
# 2) усредняем оставшиеся
smooth = sum(clean) / len(clean)
print("Сырые замеры:", raw)
print("После фильтра:", [round(t, 1) for t in clean])
print(f"Сглаженная температура: {smooth:.2f}°C")
Сначала мы выкинули явно ошибочный замер 35.0, потом усреднили остальное. Так одна помеха не испортит результат.
Есть приём ещё надёжнее простого среднего — скользящее среднее. Вместо того чтобы копить замеры вечно, мы держим «окно» из последних N значений: пришёл новый замер — выкинули самый старый. Так температура реагирует на реальные изменения (например, ты открыл окно), но всё ещё сглаживает мгновенную дрожь. Отрепетируем эту идею на чистом Python. Попробуй сам ▶
# Скользящее среднее по окну из последних 3 замеров
stream = [21.5, 21.6, 35.0, 21.4, 21.5, 21.7]
window = []
N = 3
for value in stream:
window.append(value)
if len(window) > N:
window.pop(0) # держим только последние N
avg = sum(window) / len(window)
print(f"замер {value:5.1f} -> окно {window} -> среднее {avg:.2f}")
Частые ошибки
- Верят одному замеру. Из-за шума одно значение может сильно отличаться — усредняй.
- Не отбрасывают выбросы. Один аномальный замер может перекосить среднее.
- Опрашивают слишком часто. DHT22, например, нельзя читать чаще раза в 2 секунды.
- Берут слишком большое окно. Если усреднять сотню замеров, датчик станет «тормозным» и не заметит реальное похолодание.
- Молча глотают ошибку чтения. Иногда датчик возвращает None или мусор — такой замер надо пропустить, а не подмешивать в среднее.
Best practices
- Собирай окно из нескольких замеров и усредняй (скользящее среднее).
- Отбрасывай явные выбросы перед усреднением.
- Соблюдай минимальный интервал опроса для своего датчика.
- Подбирай размер окна под задачу: маленькое — быстрая реакция, большое — гладкость.
- Проверяй замер на адекватность диапазона (например, −40…+80°C) и отбрасывай явный мусор.
Эта идея — не верить одному измерению, а смотреть на серию — выходит далеко за рамки термометра. Точно так же сглаживают сигнал GPS в навигаторе, шаги в фитнес-браслете и пульс в умных часах. Научившись усреднять температуру, ты освоил приём, которым пользуются почти все устройства, имеющие дело с «живыми», шумными данными из реального мира.
Итоги. Показания датчиков шумят, поэтому одному замеру не верят: собирают несколько, отбрасывают выбросы и усредняют, а ещё лучше — держат скользящее окно последних значений. Эту логику легко отладить на чистом Python. Дальше используем датчики в проектах умного дома.