День #7: Мониторинг движения!

День 7 адвент-календаря мейкера: мониторинг движения

Добро пожаловать в седьмой день вашего адвент-календаря «12 проектов Кодмаса». Сегодня мы будем использовать датчик, который обнаруживает движение, позволяя нашему Pico реагировать на людей и животных, когда они находятся рядом с нашим проектом.

Это цифровой датчик, который выдаёт сигнал HIGH при обнаружении движения. Мы можем запрограммировать его аналогично кнопкам из дня #3 — как триггер для нашей программы.

Поехали!

Содержимое коробки #7

В этой коробке вы найдёте:

  • 1x Мини PIR-датчик

  • 3x Провода-перемычки папа-папа

Компоненты дня 7

Сегодняшний проект

Датчик в вашем наборе — это PIR-датчик, что расшифровывается как П ассивный И нфра- К расный (Passive Infra-Red). PIR-датчики обнаруживают движение через тепловую энергию (инфракрасное излучение), исходящую от людей или животных. На снеговиков он не среагирует!

Эти датчики широко используются в домашних охранных системах — если в вашем доме есть сигнализация, посмотрите по углам потолков, и вы, возможно, увидите нечто похожее.

Сегодня мы настроим наш датчик движения, а затем протестируем его, двигая телом. Затем, как и в предыдущих коробках, объединим его с другими компонентами, чтобы создать забавные небольшие проекты, включая собственную мини-систему сигнализации — и заодно изучим новую функцию!

Собираем цепь

Вы знаете, с чего начать… отключите Pico от USB-порта компьютера.

Теперь уберите детали датчика освещённости со вчерашнего дня, оставив на место светодиоды и зуммер вместе с Pico на основной макетной плате. Ваша цепь должна выглядеть вот так для начала:

Начальная точка дня 7

Теперь добавим датчик движения. Обратите внимание: на диаграммах ниже используется обобщённая деталь датчика движения из Fritzing, так как в настоящее время в программе нет детали для мини-версии из вашей коробки. Подключение одинаковое.

Пожалуйста, держите датчик за края зелёной печатной платы при установке, так как это хрупкий компонент!

Важно! Ориентация датчика!

Ориентация пинов PIR очень важна! Посмотрите на изображение ниже с ориентацией угловых пинов — оно показывает, какая сторона является 3,3 В, а какая — GND (средний пин — для нашего GPIO):

Ориентация PIR-датчика

Теперь установите ваш PIR в верхнюю часть мини-макетной платы в ориентации, показанной на изображении выше (с пином 3,3 В слева), как показано ниже:

PIR-датчик в мини-макетной плате

Теперь подключите три пина к вашей цепи с помощью проводов-перемычек:

  • Подключите левый пин к пину 3,3 В (физический пин 36)

  • Подключите правый пин к синей шине GND

  • Подключите средний пин к GPIO 26 (физический пин 31)

Ваша цепь должна выглядеть вот так:

Полная цепь с PIR-датчиком

Задание 1: Базовое обнаружение движения

Давайте запустим этот датчик с минимальной начальной программой. Пример кода ниже использует вещи, которые мы рассматривали в предыдущих коробках, так что вы должны быть вполне с ним знакомы.

Код

Как всегда, мы добавляем импорты, затем настраиваем пин GPIO для датчика.

Здесь мы используем подтяжку к нулю (pull down), чтобы датчик был LOW, пока не сработает — мы не хотим, чтобы этот пин «плавал» между двумя состояниями (как мы рассматривали в день #3).

Следующая интересная деталь — мы ждём, пока датчик стабилизируется или «прогреется», прежде чем переходить в цикл while.

Прогрев

Это хорошая практика с PIR-датчиками, особенно если у вас есть проект, разработанный для запуска сразу при включении микроконтроллера. Это даёт датчику возможность установить базовый уровень своего окружения, прежде чем пытаться обнаруживать изменения. Некоторые более продвинутые датчики даже выполняют начальное самотестирование, которое может занять минуту или две.

Мы отводим 10 секунд — этого, кажется, достаточно для данного датчика.

Далее мы используем цикл while, чтобы проверять сигнал HIGH от PIR-датчика, который затем выводит «I SEE YOU», ждёт 5 секунд и продолжает цикл снова.

Скопируйте код в Thonny и попробуйте. Мы обнаружили, что если сидеть совершенно неподвижно, а затем помахать руками, вы сможете протестировать программу без того, чтобы вставать с места!

# Imports
from machine import Pin
import time

# Set up PIR pin with pull down
pir = Pin(26, Pin.IN, Pin.PULL_DOWN)

print("Warming up...")

time.sleep(10) # Delay to allow the sensor to settle

print("Sensor ready!")

while True: # Run forever

    time.sleep(0.01) # Delay to stop unnecessary program speed

    if pir.value() == 1: # If PIR detects movement

        print("I SEE YOU!")

        time.sleep(5) # Wait 5 seconds before looking for more movement

        print("Sensor active") # Let us know that the sensor is active

Задание 2: Сигнализация на основе движения

Это отличный проект для датчиков движения, особенно если у вас есть назойливый брат или сестра, которые постоянно «берут» вещи из вашей комнаты…

Мы можем использовать наш PIR-датчик для активации зуммера и светодиодов, заставляя нежданных гостей подпрыгнуть и, надеюсь, отпугнув их!

Код

В примере ниже мы снова добавляем наши светодиоды и зуммер, поэтому заново определяем их пины для использования.

Мы также не хотим, чтобы вы забыли, как создавать функции (которые мы рассматривали в день #5 с зуммером), поэтому вы заметите, что мы создали функцию под названием alarm(), которую мы вызываем всякий раз, когда хотим активировать светодиоды и зуммер. Функция здесь не была строго необходима, но это хорошая практика!

Функция заставляет наши светодиоды и зуммер звучать/мигать ровно 5 раз, но на этот раз мы не используем счётчик — вместо этого мы познакомимся с функцией range

Функция range

Функция range очень удобна, когда нужно повторить что-то определённое количество раз.

Допустим, мы хотим напечатать «Ещё одна функция!» двадцать раз. Мы могли бы добавить двадцать строк print, или использовать счётчик, прибавляя +1 каждый раз, но ещё один (более удобный/короткий) способ — использовать range — и вот как это выглядит:

for i in range(20):
    print("Not another function!")

Не зацикливайтесь на том, почему „i“ — это именно „i“ — замените его на „t“ или „v“ и посмотрите, что произойдёт — результат тот же! Традиционно „i“ использовалось всегда, поэтому большинство программистов придерживаются этого. Считайте, что „i“ означает iteration (итерация) или index (индекс) — и это начнёт иметь смысл… «**for* every i**teration with**in the range of 20»* — понятно?

Мы не вводили это раньше, когда использовали счётчики, так как считаем, что функция range может казаться немного более пугающей для начинающих программистов. Вы также можете добавлять значения в скобках, чтобы задать диапазон/шаг, но пока ограничимся самым простым использованием.

Мы увеличиваем громкость зуммера перед функцией range и снижаем её после — обратите внимание на расположение и отступы этих строк: они находятся вне функции range. Также у нас есть строка в начале программы, чтобы убедиться, что зуммер всегда выключен перед началом.

Итак, теперь, когда мы понимаем, что делает range, скопируйте код ниже в Thonny, запустите его и сидите очень тихо или выйдите из комнаты на 20 секунд. Когда вы вернётесь, вы должны сработать сигнализацию!

# Imports
from machine import Pin, PWM
import time

# Set up the LED pins
red = Pin(18, Pin.OUT)
amber = Pin(19, Pin.OUT)
green = Pin(20, Pin.OUT)

# Set up the Buzzer pin as PWM
buzzer = PWM(Pin(13))

# Set PWM duty to 0% at program start
buzzer.duty_u16(0)

# Set up PIR pin with pull down
pir = Pin(26, Pin.IN, Pin.PULL_DOWN)

# Warm up/settle PIR sensor
print("Warming up...")
time.sleep(10) # Delay to allow the sensor to settle
print("Sensor ready!")

def alarm(): # Our alarm function

    # Set PWM duty (volume up)
    buzzer.duty_u16(10000)

    for i in range(5): # Run this 5 times

        buzzer.freq(5000) # Higher pitch

        red.value(1) # Red ON
        amber.value(1) # Amber ON
        green.value(1) # Green ON

        time.sleep(1)

        buzzer.freq(500) # Lower pitch

        red.value(0) # Red OFF
        amber.value(0) # Amber OFF
        green.value(0) # Green OFF

        time.sleep(1)

    # Set PWM duty (volume off)
    buzzer.duty_u16(0)

while True: # Run forever

    time.sleep(0.01) # Delay to stop unnecessary program speed

    if pir.value() == 1: # If PIR detects movement

        print("I SEE YOU!")

        alarm() # Call our function

        print("Sensor active") # Let us know that the sensor is active again

День #7 завершён!

Последнее задание содержало много деталей, поэтому мы остановимся здесь на сегодня и не будем перегружать ваш свежий программистский мозг!

PIR-датчик может быть очень увлекательным в использовании, и они бывают самых разных форм и размеров — вы в кратчайшие сроки создадите собственную домашнюю систему безопасности.

Итак, что мы рассмотрели в день #7? Сегодня вы:

  • Собрали цепь с PIR-датчиком

  • Научились использовать PIR-датчик с MicroPython и Pico

  • Создали мини-систему сигнализации!

  • Изучили функцию range

  • Повторили использование функций

Как всегда, сохраните вашу цепь в безопасном месте до завтра (не разбирайте ничего пока) — и до встречи после завтрака!