Датчик движения и обработка событий
Датчик движения превращает Pi в сторожа, который замечает любое шевеление в комнате и реагирует мгновенно.
PIR-датчик — это глаз, который видит не картинку, а тепло. Человек проходит мимо — датчик ловит изменение инфракрасного излучения.
Ты наверняка видел, как в подъезде свет вспыхивает сам, стоит выйти из лифта, а потом гаснет, когда все разошлись. За этим стоит ровно тот датчик, который мы сейчас подключим к Pi. Любое тёплое тело — человек, кошка, даже большая собака — излучает инфракрасный свет, невидимый глазу. PIR-датчик не делает фотографий, он просто замечает, что тепловая «картинка» перед ним изменилась, и говорит: «тут кто-то шевельнулся».
Самый популярный датчик движения — PIR (пассивный инфракрасный). Он цифровой: выдаёт 1, когда замечает движение, и 0, когда всё спокойно. Подключается просто: питание, земля и сигнальный провод на GPIO. Слово «пассивный» здесь важное — датчик ничего не излучает сам, в отличие от радара или ультразвука, а лишь молча слушает тепло вокруг. Поэтому он дешёвый, экономный и не мешает другим устройствам.
Как работает под капотом
PIR датчик
+--------+
| VCC |---- 5V (физ. 2)
| OUT |---- GPIO23 (физ. 16)
| GND |---- GND (физ. 6)
+--------+
|
движение -> OUT становится 1
Внутри PIR стоит пироэлектрический сенсор, разделённый на две половинки, и белый купол-линза (его называют линзой Френеля), который делит поле зрения на множество секторов. Когда тёплое тело пересекает границу между секторами, одна половинка ловит чуть больше тепла, чем другая, — возникает разница, и датчик понимает, что что-то движется. Именно поэтому PIR прекрасно ловит человека, идущего поперёк, и почти не замечает того, кто стоит неподвижно: без пересечения секторов нет и разницы.
Поле зрения PIR, разбитое линзой на секторы:
| A | B | A | B | A | B |
человек идёт ->
разница тепла A vs B -> OUT = 1
На Pi с gpiozero это выглядит как обработка событий — мы не сидим в цикле, а говорим «когда появится движение, вызови вот эту функцию» (пример для платы):
from gpiozero import MotionSensor
pir = MotionSensor(23)
pir.when_motion = lambda: print("Движение!")
pir.when_no_motion = lambda: print("Тихо...")
pause()
А саму логику обработки потока событий отладим в браузере. Представим, что датчик прислал серию сигналов, и мы хотим реагировать только на переходы «стало движение» / «движение прекратилось». Попробуй сам ▶
# Обработка событий движения: реагируем только на ИЗМЕНЕНИЯ
readings = [0, 0, 1, 1, 1, 0, 0, 1, 0] # сигнал датчика по тикам
prev = 0
alarms = 0
for tick, value in enumerate(readings):
if value == 1 and prev == 0:
alarms += 1
print(f"тик {tick}: ДВИЖЕНИЕ обнаружено (тревога #{alarms})")
elif value == 0 and prev == 1:
print(f"тик {tick}: движение прекратилось")
prev = value
print(f"Всего срабатываний: {alarms}")
Ключевая идея — реагировать на переход состояния, а не на каждый тик. Иначе при долгом движении мы бы получили десятки повторных «тревог».
На практике одного «увидел движение» часто мало: хочется, чтобы свет горел ещё какое-то время после того, как человек замер или вышел. Это называется таймер удержания. Логику тоже удобно отрепетировать на чистом Python: запоминаем момент последнего движения и держим «активное» состояние, пока не пройдёт пауза. Попробуй сам ▶
# Таймер удержания: держим "активно" ещё hold секунд после движения
events = [(0, 1), (1, 0), (2, 0), (8, 1), (9, 0), (20, 0)]
hold = 5 # сколько секунд держать после последнего движения
last_motion = -100
for t, motion in events:
if motion == 1:
last_motion = t
active = (t - last_motion) < hold
print(f"t={t:2d}: движение={motion} -> свет {'ГОРИТ' if active else 'погас'}")
Частые ошибки
- Срабатывает постоянно. PIR имеет крутилки чувствительности и задержки — отрегулируй их.
- Реагируют на каждый тик. Нужно ловить переход 0->1, а не само значение 1.
- Датчик «прогревается». Первые 30-60 секунд после включения PIR врёт — дай ему успокоиться.
- Ставят датчик напротив окна или батареи. Солнечный луч и горячий радиатор дают ложные срабатывания — направляй PIR в комнату, а не на источники тепла.
- Ждут, что PIR увидит стоящего человека. Без движения тепловая картинка не меняется, и датчик «теряет» неподвижного — это не поломка, а принцип работы.
Best practices
- Используй событийную модель
when_motionвместо вечного опроса. - Реагируй на переходы состояний, как в примере выше.
- Добавь задержку, чтобы не спамить уведомлениями при долгом движении.
- Дай датчику 1 минуту прогреться при старте программы, прежде чем доверять его показаниям.
- Логируй каждое срабатывание с временной меткой — так проще поймать ложные тревоги и понять их причину.
Итоги. PIR-датчик цифровой: 1 при движении, 0 в покое. Он ловит изменение инфракрасного тепла через линзу с секторами, поэтому видит движущегося и «не замечает» застывшего. gpiozero обрабатывает его через события when_motion. Главное — реагировать на переходы состояния, а не на каждый тик, и держать действие таймером. Дальше подключим датчик температуры.