Датчик движения и обработка событий

Датчик движения превращает 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. Главное — реагировать на переходы состояния, а не на каждый тик, и держать действие таймером. Дальше подключим датчик температуры.

Проверьте себя
1. На что важно реагировать при обработке сигнала датчика движения?
AНа каждое значение 1
BНа переход состояния (0->1 появилось движение, 1->0 прекратилось)
CТолько на нули
DНа температуру
2. Что измеряет PIR-датчик?
AЦвет
BИзменение инфракрасного (теплового) излучения от движущихся тёплых объектов
CЗвук
DВлажность