View Categories

Датчик расстояния HC-SR04

HC-SR04 – популярный ультразвуковой датчик расстояния. Может использоваться для измерения расстояния, определения препятствий для робота, как орган управления устройством и даже для построения карты помещения и наведения на подвижные объекты.

В наборе GyverKIT START IOT EXTRA
УЗ. дальномер

Характеристики:

  • Питание: 5V
  • Рабочий ток: 15 мА
  • Звуковая частота: 40 кГц
  • Угол измерения: 15 градусов
  • Диапазон измерения: 2 см.. 4 м
  • Точность: ~1 мм при грамотной фильтрации

Принцип работы #

Датчик работает довольно интересно: подаём импульс с продолжительностью 10 мкс на пин Trig, модуль посылает ультразвуковой импульс, он отражается от препятствия и детектируется. Затем с пина Echo возвращается импульс по продолжительности соответствующий времени путешествия звуковой волны. Ардуина этот импульс должна измерить.

Подключение к Arduino #

Подключаем к питанию и любым цифровым пинам:

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

Получение расстояния #

Для работы с датчиком в "ручном режиме" нужно подать короткий импульс на пин TRIG и получить импульс с пина ECHO:

// пины
#define HC_TRIG 3
#define HC_ECHO 2

// сделаем функцию для удобства
float getDist(uint8_t trig, uint8_t echo) {
  // импульс 10 мкс
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  // измеряем время ответного импульса
  uint32_t us = pulseIn(echo, HIGH);

  // считаем расстояние и возвращаем
  return us / 58.2;
}

void setup() {
  Serial.begin(115200);     // для связи
  pinMode(HC_TRIG, OUTPUT); // trig выход
  pinMode(HC_ECHO, INPUT);  // echo вход
}

void loop() {
  float dist = getDist(HC_TRIG, HC_ECHO);   // получаем расстояние
  Serial.println(dist);                     // выводим
  delay(50);
}

Подвигаю рукой перед датчиком:

Фильтрация #

Отфильтруем данные при помощи простейшего экспоненциального фильтра:

float distFilt = 0;

void loop() {
  float dist = getDist(HC_TRIG, HC_ECHO);   // получаем расстояние
  distFilt += (dist - distFilt) * 0.2;      // фильтруем
  Serial.println(distFilt);                 // выводим
  delay(50);
}

Кстати, опрос датчика при помощи pulseIn(), не так уж плох: погрешность измерения составляет всего 0.5 мкс:

что в пересчёте на расстояние даёт точность 0.17 мм! На деле точность получается в два раза выше, так как фактически мы измеряем сигнал два раза (путь до препятствия и обратно). Сам датчик шумит гораздо сильнее, поэтому миллиметровую точность получить абсолютно не проблема. Но есть проблема в другом: выполнение кода блокируется на время измерения, например на трёх метрах это будет 17 мс. Вроде и немного, но для некоторых задач это будет весьма критично.

Важный момент: чтобы датчик не ловил "эхо" от самого себя – его не рекомендуется опрашивать чаще 30 мс!

Коррекция скорости звука #

Скорость звука зависит от температуры: при +20°С это 343 м/с, а при -20°С – 318 м/с! А ведь это целых 318 / 343 = 7%, что на расстоянии в 1 метр даст погрешность 7 сантиметров. Много, гораздо больше возможных погрешностей в измерении. Давайте это исправим.

В диапазоне -50.. 50°С зависимость является линейной и аппроксимируется уравнением V = 0.609 * t + 330.75:

Таким образом, для нахождения более точного расстояния с поправкой на температуру достаточно делить время импульса не на 58, а на.. кстати, откуда берётся 58? Для прохождения 1 м звуку понадобится 1 / 343 = 0.0029 с, или 2.915 мс. Мы получаем время туда и обратно, поэтому умножаем ещё на 2. В и для сантиметров – ещё на 10, и получаем 58.3. Гораздо понятнее было бы умножать время импульса на скорость звука и делить пополам.

Для расчёта расстояния в миллиметрах с учётом температуры в °С получим формулу:

S = us * V / 2000;                      // #1
S = us * (0.609 * t + 330.75) / 2000;   // #2
S = us * (t * 6 / 10 + 330) / 2000;     // #3

Настолько высокая точность нам не нужна, поэтому можно избавиться от float, чтобы код весил меньше (уравнение #3). Погрешность составит не более 1 мм на 1 метр. И финальный пример тогда:

// пины
#define HC_TRIG 3
#define HC_ECHO 2

int getMm(uint8_t trig, uint8_t echo, int t) {
  // импульс 10 мкс
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);

  // измеряем время ответного импульса
  uint32_t us = pulseIn(echo, HIGH);

  // считаем расстояние и возвращаем
  return us * (t * 6 / 10 + 330) / 2000ul;
}

void setup() {
  Serial.begin(115200);     // для связи
  pinMode(HC_TRIG, OUTPUT); // trig выход
  pinMode(HC_ECHO, INPUT);  // echo вход
}

void loop() {
  int t = 24;                               // представим, что получили с датчика
  int dist = getMm(HC_TRIG, HC_ECHO, t);    // получаем расстояние в мм
  Serial.println(dist);                     // выводим
  delay(50);
}

Библиотеки #

С датчиком можно работать без библиотек, стандартными средствами Arduino. Но есть и библиотеки:

  • HC-SR04 – можно установить по названию HC-SR04 из менеджера библиотек (автор Dirk Sarodnick)
  • NewPing – можно установить по названию NewPing из менеджера библиотек
  • GyverPing - моя библиотека

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

GyverPing #

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

#include <GyverPing.h>

#define HC_TRIG 3
#define HC_ECHO 2

GPingSync sonar(HC_TRIG, HC_ECHO);

void setup() {
    Serial.begin(115200);
}

void loop() {
    // сделать измерение
    sonar.ping();

    // открой плоттер для вывода графика
    Serial.print(sonar.getRaw());       // "сырое" значение
    Serial.print(',');
    Serial.print(sonar.getFiltered());  // фильтрованное от резких выбросов
    Serial.print(',');
    Serial.println(sonar.getSmooth());  // + усреднение, плавный точный сигнал

    delay(50);
}

Полезные страницы #

Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Прокрутить вверх