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

Введение Характеристики датчика HC-SR04 Распиновка Алгоритм работы датчика Код Оптимизация подключения (используем три провода вместо четырех) Особенности использования, советы
Пара слов о теории
Ультразвуковой датчик состоит из двух преобразователей. Один болтает, второй подслушивает. Бывают датчики, в которых преобразователи встроены в один корпус: сам болтает - сам слушает, но в случае с HC-SR04 это не так.

Разговор датчика происходит на частоте 40kHz (40000 герц). Летучие мыши смогут подслушать, человек - нет. Человек слышит звук на частоте от 20 до 20000 герц. Всё что ниже - инфразвук, всё что выше - ультразвук. Если вам за 30, ваш верхний порог слуха сильно меньше.
Датчик позволяет обнаруживать предметы на расстоянии от 3см до 400см, с точностью до 3мм. В статье рассмотрим как увеличить точности и наденость измерения. HC-SR04 имеет аналоги: US-015, US-016, US-025, US-026, US-100, RCWL-1601, CS100, SRF05 и т.п., они могут иметь нзначительные отличия, чаще всего это максмальный диапазон измерения. Работают все перечисленные ультразуковые датчики по одному принципу. Эта статья поможет разобраться с любым
Характеристики датчика HC-SR04

Рабочее напряжение DC5V
Рабочий ток 15мА
Рабочая частота 40кГц
Максимальный диапазон 400см
Минимальный диапазон 2см
Точность дальности 3мм
Эффективный угол измерения 15 гр
Рабочий угол измерения 30 гр
Габаритные размеры платы 45x20x15мм

Распиновка

VCC Контакт, на который подключается +5V.
Trig Триггер, принимает управляющий сигнал.
Echo Вывод генерирует импульс, когда принимается отраженный сигнал.
GND Подключается к земле.
Алгоритм работы датчика
От общих принципов переходим к конкретике. При кратковременной подаче высокого сигнала на триггер датчика, звукоизлучатель отправляет пакет (Pulse) из 8 коротких звуковых импульсов.
digitalWrite(pinTrig, HIGH);
delayMicroseconds(10);
digitalWrite(pinTrig, LOW);

Сразу после излучения звукового пакета (Pulse), контакт Echo переходит в состояние HIGH. Когда звуковой сигнал отразится от объекта и вернется обратно на датчик, вывод Echo незамедлительно установится в состояние LOW. Если по прошествии 38 миллисекунд сигнал не вернулся, что ж, всё теперь, раньше надо было... Датчик перестает ожидать возвращения сигнала. Таким образом мы получили некую ширину импульса Echo. Интерпретируем ее. Для расчета понадобится простая формула.
Расчет времени


Рассчитаем пример, используя математику третьего класса. В дополнение к сказанному вспомним скорость звука, она равна 0,0343см/с.
скорость звука = 0,0343см/с
Пусть на выводе Echo мы получили ширину импульса равную 200 микросекунд. Ширина импульса пропорциональна времени, которое потребовалось для обнаружения передаваемого сигнала. Считаем.
200мкс * 0,0343 = 6,86см
6,86см - такое расстояние прошел звук.
❕Важное замечание: Звук дошел до предмета и отразившись вернулся обратно. Т.е. чтобы узнать расстояние до предмета, нужно поделить значение на 2. Пересчитаем заново.
(200мкс / 2) * 0,0343 = 3,43см
Просто? Просто. ✔
Записывается это так:
distance = (duration/2)*0.0343;
Код
Начнем с основы, после упростим. В этом примере код написан без использования сторонних библиотек.
*/ Работаем с ультразвуковым датчиком HC-SR04 и Arduino
* без применения сторонних библиотек
*/
#define trig 9
#define echo 11
/* переменные хранящие ширину импульса и дистанцию до объекта */
long duration;
int distance;
void setup() {
pinMode(trig, OUTPUT); // конфигурируем trig(D9) контроллера как Выход
pinMode(echo, INPUT); // конфигурируем echo(D11) контроллера как Вход
Serial.begin(9600); // подключаем последовательные порт
}
void loop() {
digitalWrite(trig, LOW); //установим триггер в LOW на 2мкс
delayMicroseconds(2);
/*отправляем сигнал длительностью 10 мкс на триггер датчика HC-SR04 */
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
duration = pulseIn(echo, HIGH); // запишем ширину импульса Echo в duration
distance = (duration/2)*0.0343; // переводим ширину импульса в расстояние
// выводим результат в последовательный порт
Serial.print("Distance = ");
Serial.println(distance);
}

Упростим написание кода используя готовые библиотеки. Код станет компактнее, мы получим возможность удобно управлять сразу несколькими ультразвуковыми датчиками, до 15 штук, и повысим точность измерения благодаря многократным переизмерениям. Для датчика HC SR-04 написано много библиотек, остановимся на NewPing
*/ Работаем с ультразвуковым датчиком HC-SR04 и Arduino
* с применением библиотеки NewPing
*/
#include <NewPing.h> // подключаем библиотеку
#define TRIGGER_PIN 9
#define ECHO_PIN 11
// максимальная дистанция измерения в сантиметрах
#define MAX_DISTANCE 200
//создаем экземпляр
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
Serial.begin(115200);
}
void loop() {
delay(50);
Serial.print("Ping: ");
Serial.print(sonar.ping_cm());
Serial.println("cm");
}
В примере подключен один датчик. Если датчиков несколько — заменим строку:
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
на строки с перечислением всех датчиков:
/* если датчиков несколько, то нужно перечислить все.
*NewPing sonar[3]={ // в квадратных скобках колич. датчиков, максимум 15
*NewPing(3,4,MAX_DISTANCE),
*NewPing(5,6,MAX_DISTANCE),
*NewPing(7,8,MAX_DISTANCE)
*}
Более детально пример с подключением нескольких датчиков разобран в примерах к библиотеке NewPing.
Код стал короче, но мы потеряли в точности. Дистанция округляется до 1см, для многих задач этого достаточно. Если точность вам важна — допилим код. Для большей надежности проведем несколько замеров подряд, это снизит влияние некорректно проведенных измерений.
#include <NewPing.h> // подключаем библиотеку
#define TRIGGER_PIN 9
#define ECHO_PIN 11
// максимальная дистанция измерения в сантиметрах
#define MAX_DISTANCE 400
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
float duration;
long distance;
void setup()
{
Serial.begin(9600);
}
void loop()
{
// произведем 5 измерений вместо одного, это нивелирует
// часть ошибок измерения, результат станет надежнее
duration = sonar.ping_median(5); // измерений может быть больше 5
distance = (duration / 2) * 0.0343; // рассчитываем расстояние
// выводим результат в последовательный порт
Serial.print("Distance = ");
Serial.print(distance);
Serial.println(" cm");
delay(500);
}
Оптимизация подключения (используем три провода вместо четырех)
Контакты Trig и Echo не обязательно подключать на два разных пина Arduino. Можно подключить их к одному пину, а высвободившиеся пины использовать для других задач. Особенно это полезно при использовании контроллеров с ограниченным количество контактов. Вот как это делается:
#define Trig 11 // Trig и Echo подключены к 11 пину (пин может быть любым)
#define Echo 11

В остальном код остается прежним. В 3-проводном режиме пин используется и как вход, и как выход, но не одновременно, в процессе работы он активно меняет свое состояние.
Особенности использования, советы
Преимущества измерения ультразвуком:
Освещенность — не влияет на измерения
Задымленность (умеренная) — не влияет на измерения
Пыль (умеренная) — не влияет на измерения
Цвет предмета — не влияет на измерения
Жидкость и прозрачные тела не являются проблемой для ультразвука, в отличии от оптического измерения
Факторы затрудняющие измерения ультразвуком:
Влияние материала (мягкие поверхностей, например, шерсть, поглощает ультразвуковую звуковую волну и не отражает звук).
Грязь
Снег и лед
Конденсат
Слишком мелкие объекты измерения
Рассматриваемый в статье датчик является дешевым и чувствительным к условиям внешней среды, но существуют датчики с высокой степенью защиты IP67, что снижает воздействие конденсации и мороза при работе в закрытых помещениях или в условиях высокой влажности.
Датчик можно использовать в разных проектах: обнаружение препятствий, контроль уровня жидкости, измерение высоты и расстояния, парктроник. Модуль совместим с разными микроконтроллерами: Raspberry Pi, ARM, PIC, AVR(Arduino), ESP8266 и т.п. Главное обеспечить плату питанием 5V, при снижении питающего напряжения датчик может выдавать ложные показания.
Смотрите пример использование датчика в игрушке-копилке.