Ультразвуковой датчик расстояния HC-SR04 на Raspberry Pi

Ультразвуковой датчик расстояния HC-SR04 на Raspberry Pi

В предыдущих руководствах мы рассмотрели датчики температуры, PIR-датчики движения и кнопки и переключатели, все из которых можно подключить напрямую к GPIO-портам Raspberry Pi. Ультразвуковой дальномер HC-SR04 очень прост в использовании, однако выходной сигнал необходимо преобразовать с 5 В до 3,3 В, чтобы не повредить наш Raspberry Pi! В этом руководстве мы познакомим вас с некоторыми основами физики и электроники, чтобы объяснить каждый шаг!

Что вам понадобится:

  • HC-SR04

  • Резистор 1 кОм

  • Резистор 2 кОм

  • Соединительные провода (Jumper Wires)

Ультразвуковые датчики расстояния

Звук состоит из колебательных волн, распространяющихся через среду (например, воздух), при этом высота тона определяется близостью этих волн друг к другу, что определяется как частота. Лишь часть звукового спектра (диапазона частот звуковых волн) воспринимается человеческим ухом и определяется как «акустический» диапазон. Очень низкочастотный звук ниже акустического диапазона называется «инфразвуком», а высокочастотный звук выше — «ультразвуком». Ультразвуковые датчики предназначены для определения близости объекта или расстояния до него с помощью отражения ультразвука, подобно радару, для вычисления времени, необходимого для отражения ультразвуковых волн между датчиком и твёрдым объектом. Ультразвук используется главным образом потому, что он не слышен человеческому уху и относительно точен на коротких дистанциях. Конечно, для этой цели можно использовать и акустический звук, но тогда у вас будет шумный робот, издающий звуковой сигнал каждые несколько секунд…

Базовый ультразвуковой датчик состоит из одного или нескольких ультразвуковых передатчиков (по сути, динамиков), приёмника и схемы управления. Передатчики излучают высокочастотный ультразвуковой сигнал, который отражается от любых ближайших твёрдых объектов. Часть этого ультразвукового шума отражается и обнаруживается приёмником датчика. Этот обратный сигнал затем обрабатывается схемой управления для вычисления разницы во времени между отправкой и получением сигнала. Это время впоследствии может быть использовано вместе с некоторыми хитрыми математическими расчётами для вычисления расстояния между датчиком и отражающим объектом.

Ультразвуковой датчик HC-SR04

Ультразвуковой датчик HC-SR04, который мы будем использовать в этом руководстве для Raspberry Pi, имеет четыре вывода: земля (GND), выход эхо-импульса (ECHO), вход триггерного импульса (TRIG) и питание 5 В (Vcc). Мы питаем модуль через Vcc, заземляем через GND и используем наш Raspberry Pi для отправки входного сигнала на TRIG, который запускает датчик для отправки ультразвукового импульса. Импульсные волны отражаются от ближайших объектов, и некоторые из них возвращаются обратно к датчику. Датчик обнаруживает эти обратные волны и измеряет время между триггерным и возвратным импульсом, а затем отправляет сигнал 5 В на вывод ECHO.

ECHO будет находиться в состоянии «низкого уровня» (0 В) до тех пор, пока датчик не будет запущен и не получит эхо-импульс. Как только обратный импульс будет обнаружен, ECHO устанавливается в «высокий уровень» (5 В) на время этого импульса. Длительность импульса — это полное время между отправкой датчиком ультразвукового импульса и обнаружением обратного импульса приёмником датчика. Поэтому наш Python-скрипт должен измерить длительность импульса и затем вычислить расстояние на основе этого значения.

ВАЖНО. Выходной сигнал датчика (ECHO) на HC-SR04 рассчитан на 5 В. Однако входной вывод GPIO Raspberry Pi рассчитан на 3,3 В. Подача 5 В сигнала на незащищённый вход 3,3 В может повредить ваши GPIO-выводы, чего мы хотим избежать! Нам потребуется использовать небольшую схему делителя напряжения, состоящую из двух резисторов, чтобы снизить выходное напряжение датчика до уровня, с которым наш Raspberry Pi может работать.

Делители напряжения

Делитель напряжения состоит из двух резисторов (R1 и R2), соединённых последовательно и подключённых к входному напряжению (Vin), которое необходимо понизить до нашего выходного напряжения (Vout). В нашей схеме Vin будет ECHO, которое необходимо уменьшить с 5 В до нашего Vout, равного 3,3 В.

Схема делителя напряжения

Следующая схема и простое уравнение могут быть применены ко многим ситуациям, где необходимо снизить напряжение. Если вы не хотите вникать в техническую часть, просто возьмите 1 резистор на 1 кОм и 1 резистор на 2 кОм.

Формула делителя напряжения

Не углубляясь слишком сильно в математику, нам фактически нужно вычислить только одно значение сопротивления, так как важно именно соотношение деления. Мы знаем наше входное напряжение (5 В) и требуемое выходное напряжение (3,3 В), и мы можем использовать любую комбинацию резисторов для достижения нужного снижения. У меня как раз есть куча лишних резисторов на 1 кОм, поэтому я решил использовать один из них в схеме в качестве R1.

Подставив наши значения, получим следующее:

Расчёт делителя напряжения

Итак, мы используем резистор 1 кОм для R1 и резистор 2 кОм в качестве R2!

Сборка схемы

Для этого проекта мы будем использовать четыре вывода Raspberry Pi: GPIO 5V [Pin 2] — Vcc (питание 5 В), GPIO GND [Pin 6] — GND (земля 0 В), GPIO 23 [Pin 16] — TRIG (выход GPIO) и GPIO 24 [Pin 18] — ECHO (вход GPIO)

Схема подключения выводов Raspberry Pi
  1. Подключите четыре провода «папа-мама» к выводам HC-SR04 следующим образом: Красный — Vcc, Синий — TRIG, Жёлтый — ECHO и Чёрный — GND.

Подключение проводов к HC-SR04
  1. Подключите Vcc к положительной шине макетной платы, а GND — к отрицательной шине.

  2. Подключите GPIO 5V [Pin 2] к положительной шине, а GPIO GND [Pin 6] — к отрицательной шине.

Подключение питания и земли на макетной плате
  1. Подключите TRIG к свободной шине и соедините эту шину с GPIO 23 [Pin 16]. (Вы можете подключить TRIG напрямую к GPIO 23, если хотите). Лично я просто предпочитаю делать всё на макетной плате!

Подключение TRIG к GPIO 23
  1. Подключите ECHO к свободной шине, соедините с другой свободной шиной через R1 (резистор 1 кОм)

  2. Соедините шину R1 с шиной GND через R2 (резистор 2 кОм). Оставьте промежуток между двумя резисторами.

Подключение резисторов делителя напряжения
  1. Подключите GPIO 24 [Pin 18] к шине с вашим R1 (резистор 1 кОм). Этот GPIO-вывод должен находиться между R1 и R2

Подключение GPIO 24 между резисторами

Вот и всё! Наш датчик HC-SR04 подключён к нашему Raspberry Pi!

Готовая схема подключения HC-SR04 к Raspberry Pi

Программирование на Python

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

Выходной сигнал ультразвукового датчика (ECHO) всегда будет на низком уровне (0 В), пока он не будет запущен — в этом случае он выдаст 5 В (3,3 В с нашим делителем напряжения!). Поэтому нам нужно настроить один GPIO-вывод как выход для запуска датчика и один как вход для обнаружения изменения напряжения на ECHO.

Сначала импортируем библиотеку Python GPIO, импортируем библиотеку time (чтобы наш Pi делал паузы между шагами) и зададим нумерацию GPIO-выводов.

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)

Далее нам нужно задать имена нашим входному и выходному выводам, чтобы мы могли обращаться к ним позже в нашем Python-коде. Мы назовём наш выходной вывод (который запускает датчик) GPIO 23 [Pin 16] как TRIG, а наш входной вывод (который считывает обратный сигнал от датчика) GPIO 24 [Pin 18] как ECHO.

TRIG = 23
ECHO = 24

Затем мы выведем сообщение, чтобы сообщить пользователю, что идёт измерение расстояния…

print("Distance Measurement In Progress")

Далее настроим два GPIO-порта как входы или выходы, как было определено ранее.

GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)

Затем убедимся, что вывод Trigger установлен в низкий уровень, и дадим датчику секунду на стабилизацию.

GPIO.output(TRIG, False)
print("Waiting For Sensor To Settle")
time.sleep(2)

Датчик HC-SR04 требует короткий импульс длительностью 10 мкс для запуска модуля, что заставит датчик начать программу дальнометрии (8 ультразвуковых импульсов на частоте 40 кГц) для получения эхо-ответа. Итак, чтобы создать наш триггерный импульс, мы устанавливаем вывод trigger в высокий уровень на 10 мкс, а затем снова в низкий.

GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)

Теперь, когда мы отправили наш импульсный сигнал, нам нужно прослушивать наш входной вывод, который подключён к ECHO. Датчик устанавливает ECHO в высокий уровень на время, необходимое для прохождения импульса туда и обратно, поэтому наш код должен измерить время, в течение которого вывод ECHO находится в высоком состоянии. Мы используем цикл «while» для обеспечения того, чтобы каждая временная метка сигнала была записана в правильном порядке.

Функция time.time() записывает последнюю временную метку для данного условия. Например, если вывод переходит из низкого в высокий уровень, и мы записываем низкое состояние с помощью функции time.time(), записанная временная метка будет последним моментом, когда этот вывод был в низком состоянии.

Поэтому нашим первым шагом должна быть запись последней временной метки низкого уровня для ECHO (pulse_start), то есть непосредственно перед получением обратного сигнала и переходом вывода в высокий уровень.

while GPIO.input(ECHO) == 0:
    pulse_start = time.time()

Как только сигнал получен, значение меняется с низкого (0) на высокое (1), и сигнал будет оставаться высоким на протяжении длительности эхо-импульса. Поэтому нам также нужна последняя временная метка высокого уровня для ECHO (pulse_end).

while GPIO.input(ECHO) == 1:
    pulse_end = time.time()

Теперь мы можем вычислить разницу между двумя записанными временными метками и, следовательно, длительность импульса (pulse_duration).

pulse_duration = pulse_end - pulse_start

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

Формула расчёта расстояния

Скорость звука непостоянна и зависит от среды, через которую он распространяется, а также от температуры этой среды. Однако некоторые умные физики вычислили скорость звука на уровне моря, поэтому мы примем базовое значение 343 м/с. Если вы пытаетесь измерить расстояние через воду, именно здесь вы ошибётесь — убедитесь, что используете правильную скорость звука!

Нам также нужно разделить наше время на два, потому что то, что мы рассчитали выше, — это фактически время, за которое ультразвуковой импульс проходит расстояние до объекта и обратно. Нам нужно только расстояние до объекта! Мы можем упростить расчёт для выполнения в нашем Python-скрипте следующим образом:

Упрощённая формула расчёта расстояния

Мы можем добавить этот расчёт в наш Python-скрипт:

distance = pulse_duration * 17150

Теперь нам нужно округлить наше расстояние до 2 знаков после запятой (для аккуратности!)

distance = round(distance, 2)

Затем мы выводим расстояние. Приведённая ниже команда выведет слово «Distance:», за которым следует переменная distance, а затем единица измерения «cm»

print("Distance:", distance, "cm")

Наконец, мы очищаем наши GPIO-выводы, чтобы убедиться, что все входы/выходы сброшены

GPIO.cleanup()
Полный Python-скрипт для измерения расстояния

Сохраните ваш Python-скрипт (мы назвали наш «range_sensor.py») и запустите его с помощью следующей команды. Запуск от имени root (sudo) важен для этого скрипта:

Результат работы скрипта измерения расстояния

Датчик стабилизируется в течение нескольких секунд, а затем измерит ваше расстояние!

Источники

Благодарим следующие источники за информацию для этого руководства:

Raspberry Pi Spy — Часть 1

Raspberry Pi Spy — Часть 2