Рассмотрим ультразвуковой датчик измерения расстояния HC-SR04 (Ultrasonic ranging module HC-SR04).
Особенности
Напряжение питания: 5V DC
Ток покоя: <2mA
Эффективный угол: <15°
Диапазон измерения расстояния: 2–400 cm
Разрешение: 0.3 cm
Разъём сенсора — 4 обычных пина (2.54), что позволяет просто воткнуть его в беспаечную плату, припаять к макетной плате или использовать для подключения обычные пины (типа мама).
Размеры
Диаграмма направленности
Принцип работы
Сенсор излучает короткий ультразвуковой импульс (в момент времени 0), который отражается от объекта и принимается сенсором. Расстояние рассчитывается исходя из времени до получения эха и скорости звука в воздухе.
Т.о., сенсор получает сигнал эха, и выдаёт расстояние, которое кодируется длительностью электрического сигнал на выходе датчика (Echo).
Следующий импульс может быть излучён, только после исчезновения эха от предыдущего. Это время называется периодом цикла (cycle period). Рекомендованный период между импульсами должен быть не менее 50 мс.
Если на сигнальный пин (Trig) подаётся импульс длительностью 10 мкс, то ультразвуковой модуль будет излучать восемь пачек ультразвукового сигнала с частотой 40кГц и обнаруживать их эхо. Измеренное расстояние до объекта пропорционально ширине эха (Echo) и может быть рассчитано по формуле, приведённой на графике выше.
Документация на сенсор, так же указывает, что если никаких препятствий не обнаружено, то на выходе будет сигнал с длительностью 38ms.
Arduino и HC-SR04
Подключить датчик очень просто
— можно удобно воткнуть его в беспаечную макетную плату, подключить +5V и GND от контроллера Arduino/CraftDuino и подключить выводы датчика Trig и Echo к цифровым пинам контроллера.
Для работы Arduino с датчиком , уже есть готовая библиотека — Ultrasonic.
Я её немного подредактировал, адаптировал библиотеку для Arduino IDE версии 1.0 и добавил ещё один пример использования.
Скачать можно здесь:
ultrasonic-HC-SR04.zip
или в репозитории:
http://code.google.com/p/robocraft/
Библиотека проста в использовании и написана с использованием функций Arduino-вского фреймворка.
Конструктор Ultrasonic принимает два параметра — номера пинов к которым подключены выводы Trig и Echo, соответственно:
Ultrasonic ultrasonic(12, 13);
— здесь вывод датчика Trig подключён к 12-му пину Arduino, а Echo к 13-му.
Остаётся вызвать метод Ranging в качестве параметра которому задаётся во что пересчитывать расстояние до объекта — сантиметры или дюймы:
#define CM 1 #define INC 0
т.о. строчка
ultrasonic.Ranging(CM);
— вернёт расстояние до объекта (типа long) в сантиметрах.
исходный код метода Ranging:
long Ultrasonic::Ranging(int sys) { Timing(); distacne_cm = duration /29 / 2 ; distance_inc = duration / 74 / 2; if (sys) return distacne_cm; else return distance_inc; }
— вызывается внутренний метод Timing(), который считывает длительность импульса сигнала на выходе Echo сенсора, и переводится в требуемую систему счисления.
исходный код метода Timing:
long Ultrasonic::Timing() { digitalWrite(Trig_pin, LOW); delayMicroseconds(2); digitalWrite(Trig_pin, HIGH); delayMicroseconds(10); digitalWrite(Trig_pin, LOW); duration = pulseIn(Echo_pin, HIGH); return duration; }
— на пин Trig сенсора подаётся импульс длительностью 10 мкс, а затем используется Arduino-метод pulseIn(), который cчитывает высокий импульс c цифрового порта Arduino/CraftDuino и возвращает продолжительность импульса в микросекундах.
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);pulseIn(порт, значение, тайминг);— cчитывает импульс (высокий или низкий) c цифрового порта и возвращает продолжительность импульса в микросекундах.
подробнее: Программирование Arduino — дополнительные функции ввода/вывода
Пример использования, с выдачей расстояния до объекта в последовательный порт (в сантиметрах) — Ultrasonic2serial:
// // Ultrasonic HR-SC04 sensor test // // https://robocraft.ru // #include "Ultrasonic.h" // sensor connected to: // Trig - 12, Echo - 13 Ultrasonic ultrasonic(12, 13); void setup() { Serial.begin(9600); // start the serial port } void loop() { float dist_cm = ultrasonic.Ranging(CM); // get distance Serial.println(dist_cm); // print the distance delay(100); // arbitary wait time. }
Пример выдачи:
17.00 19.00 20.00 20.00 20.00 20.00 20.00 20.00 18.00 21.00 2599.00 2599.00 2599.00 2599.00 2599.00 2599.00 2599.00 2599.00 2599.00 2599.00
— это я немного поводил рукой перед сенсором.
Последние значения показывают неспособность сенсора определить расстояние до объекта.
UPD
Теперь купить можно и у нас=)
Ссылки
Arduino Library For Ultrasonic Ranging Module HC-SR04
документация на HC-SR04 (PDF)
По теме
Программирование Arduino — дополнительные функции ввода/вывода
Arduino как фреймворк
Датчик измерения расстояния SHARP-GP2Y0A710K0F — рассчёт расстояния
56 комментариев на «“Ультразвуковой датчик измерения расстояния HC-SR04”»
будет ли такой датчик эффективен для измерения расстояния впереди едущего автомобиля?
хочу сделать простую систему, вроде парктроника — только вперед. Например в пробке, если приближаешься ближе чем 30-50 сантиметров к препятствию — выдать сигнал.
Вроде ультразвуковой сенсор плохо реагирует на шероховатые поверхности, а оптический — на зеркальные. Или технологии уже шагнули вперед?
Пойдёт, мне кажется.
У него с человеками не очень гладко, да и то на больших расстояниях (больше 2м) с объектами по-крупнее нормально должен себя вести.
На шероховатости реагирует адекватно — пузо в свитере уверенно видит от притыка до 2м.
Только исполнение открытое слишком — явно не для автомобильных применений.
Хмм, действительно — исполнение хромает…
А как например ультрахвуковых датчиков парковки? Они стандартные, купить можно пачкой. Только вот пример работы бы…
И когда это добро появится в магазине?
на ебее полным полно) и стоит 3-4 доллара)
Подскажите, собрал как в статье, однако контроллер выдаёт 3 или 4 сантиметра, иногда перебиваясь десятками. Что я сделал не так?
почему то тестовый пример кода не компилируется…
А чего пишет-то?=))
«ultrasonic» does not name a type
А что Ultrasonic.h не найден не пишет?
Библиотеку, случаем, не забыли в ..\arduinoXX\libraries закинуть?=)
))) забыл конечно))) залил, сейчас работает! Спасибо!!)))
Подскажите, насколько важно напряжение питания для стабильности работы этого датчика?
Где-то читал что надо ровно 5 иначе показания будут плавать или как в моем случае не будет работать вообще. У меня показывает вечный ноль.
У меня внешнего источника нет, поэтому приходится брать питание с самой ардуины (которая в свою очереди питается через usb).
Не чутки они к питанию, не замечал…
По крайней мере от ардуиновских 5В (именно при питании от USB)
Все свои датчики проверяем именно так на общую работоспособность и на адекватность показаний.
Скорее оборван/неконтачит какой-нибудь провод или ошибка в подключении.
Запустил, все работает. Спасибо!
Скажите пожалуйста, а почему он иногда как бы немного подвисает и выдает несколько раз подряд какие-то огромные значения вида 3700?
Это он не подвисает это, похоже, дуина ждёт отражённого сигнала, и не дождавшись выдаёт, у меня, обычно ~2260.00 Получается если его в даль направить или препятствие стоит по таким углом, что от него эхо не слышно(например на стену/потолок под острым углом направить)
Мне просто очень нужно как-то избавиться от этого эффекта и иметь всегда стабильные данные. Можете что-то посоветовать? Может более дорогая модель или инфракрасные дальномеры?
У инфракрасных свои недостатки.
Может программная обработка-фильтрация?
Если надо чтоб под любым углом и на любые расстояния — то да, пробовать другие датчики.pulseIn ), играемся с ним.
Если просто убрать непонятную цифру — то да обработка. Хоть так — если расстояние больше 400 то оно = 400.
Если не нравится задержка при выводе в случае потери сигнала, то лезем в arduino-хх\libraries\Ultrasonic\Ultrasonic.cpp и добовляем в duration = pulseIn(Echo_pin, HIGH); таймаут(см
Всем привет!
Ребята, очень, очень нужна ваша помощь.
Сразу скажу, я полный нуб и начинающий электронщик-программист.
Работаю с avr codevision и atmega 128. Пишу программу, подсоединяю хедер Ultrasonic.h, добавляю его в библиотеку, но даже компиляцию не проходит. Ругается на файл «wProgram.h». в хедере. Убираю его, начинает ругаться на строчку «class Ultrasonic», мол скобки какой то не хватает.
Ребята, 2 недели голову ломаю. Все сайты облазил, но ничего. Помоги, пожалуйста. Растолкуйте, что нет (если можно поподробней).
Зарание благодарен)
если используете библиотеки для Arduino, то тогда нужно и ардуиновское «ядро» тащить.
По теме:
Как адаптировать библиотеки для Arduino 1.0
Arduino как фреймворк
Что за язык программирования используется для Arduino?
как же быть?
может кто встречал переделанную библиотеку под AVR CodeVision?
голову сломал, но нигде ничего…
загляните в исходники этой библиотеки или перечитайте статью и сможете убедиться, что ничего сложного библиотека не делает — для «выстрела» на пине Trig выставляется лог. 1 на 10 ms, а затем считываем длительность лог. 1 на пине Echo.
После чего, длительность импульса просто переводится в расстояние до препятствия.
Для считывания таймер счетчик использовать или можно без него?
Подключил как на картинке, программа скомпилировалсь успешно, но при нажатии ctrl + shift + U выдает: avrdude: usbdev_open(): did not find any USB device «usb»
в чем проблема?
В том что, цитирую «avrdude не находит никаких USB девайсов»=))
То есть дело не в программе и не в подключении УЗ-дальномера — сама дуна не определяется.
Странно, с той же самой версией IDE 1.0 блинк работал.
Драйвера стоят, устройство определяется через диспетчер задач.
Ура, все заработало, но есть одно НО: постоянный результат измерений — 0.00
меняйте местами провода Trig и Echo, проверяйте подключение.
С виду всё правильно, может где-то всё же неконтакт…
Работоспособность сонара, частично, можно проверить на слух — если поднести вплотную ухо к работающему сонару слышны негромкие щелчки.
Реально ли изменить частоту излучения модуля? допустим не 40кГц, а в 45-50 или наоборот ниже?
В принципе реально.
Вполне возможно достаточно просто поменять какой-нибудь резистор-конденсатор.
А может и не достаточно — неизвестно чем и как генерится посылка — на плате стоит подозрительная микросхема с затёртой маркировкой, и судя по тому как к ней подключен кварц — это МК =\ Если частоту задаёт он то шансы что-то переделать без гемора резко падают.
К тому же кроме копашения в схеме(кстати изменить частоту генерации может быть недостаточно, наверняка придётся лезть во входные цепи приёмника — перестраивать на новую частоту фильтры), может потребоваться замена/переделка излучателя и приёмника.
Обычно вся эта пьезокерамика работает на резонансной частоте и при уходе с неё как минимум резко упадёт эффективность/чувствительность (а то и вообще онемеют/оглохнут).
В общем готовое решение мне не известно, а разбирательство пахнет густо разложенными граблями, но пробовать никто не запрещает — осцилограф в руки и в бой!
Пример — великолепный! Но Я попытался его расширить и подключить одновременно два сенсора. При подаче питания на такую конструкцию через USB коннектор Ардуино проседает и умирает. В чём может быть причина и как её решить?
А по отдельности сонары оба нормально работают?
Если соднары исправны и надо чтобы они работали одновременно то:
Запитаться от от более мощного USB или подать внешнее питание.
Проверил сонары — по отдельности работают исправно, видимо не хватает питания. Хотя, вообще то странно от чего это сонары такие прожорливые…
При старте сонары жруть до 100мА, в установившемся режиме 20-30мА.
Так что если USB вялый (не даёт положенных 500мА) может и не хватить.
Можно подключить по очереди — подоткнули плату с сонаром, подождали пару секунд, подтыкайте второй (да прям на горячую=) если всё ок — точно слабый USB.
У меня проблема, когда расстояние становится такое что ответ в течении заданного времени (по умолчанию в библиотеке стоит 1с)-не получен (тобишь я отвожу датчик на большое расстояние 1м-9999м) ардуинка начинает слать постоянно 0 метров, встроенный светодиод на 13 пине перестает моргать и горит постоянно, даже если я снова подношу руку к датчику на расстояние 0-40 см, она как бы виснет в таком положении.А если залить скеч и не убирать руку от датчика более чем на 50см то всё норм, если больше-виснет. Сейчас заметил что чихнув, я вывел ардуинку из этого состояния 🙂 и она снова начала отправлять сигналы и замерять расстояния, проверил — хлопки, постукивания и прочая имитация сигнала тоже выводит его из этого состояния.В чем может быть проблема?
читайте на 3 поста выше
Если вы про изменения таймаута, например(duration=pulseIn()Echo_pin,HIGH,100000), то я это в первую очередь пробовал, ничего не помогает
еще пробовал скетч из этого видеоhttp://www.youtube.com/watch?v=MrkyIOtG6ok
он там в описании к видео вставил ссылку на скетч, скетч без использования библиотеки, у меня опять же виснет если отдалить на большое расстояние, и перестает слать импульсы
Попробуйте новую библиотеку —NewPing , которая фиксит зависание контроллера.
Это достигается установкой timeout-а (максимального ожидаемого расстояния) для функции pulseIn().
Всё равно, неужели какой-то датчик бракованный :(((
Была та же проблема, периодически начинал слать 0 метров и раздуплить можно было только кнопкой RESET на arduino. Проблема оказалась с pulseIn из описания — функция ждет пока pin 13 не станет в HIGH(получен вернувшийся сигнал от Trig) но в описании приписка, что если на момент вызова pulseIn сигнал уже HIGH то будет ждать пока он не сбросится в LOW. У меня после подвисания так и было (на момент вызова pulseIn сигнал уже HIGH). Решил проблему путем ручного сброса pin 13 в LOW когда начинает слать нули.
if (dist_cm == 0)
{
Serial.println(digitalRead(13));
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
pinMode(13, INPUT);
}
Полностью код
//robocraft.ru
// Ultrasonic HR-SC04 sensor test
//
//
//
#include «Ultrasonic.h»
int Relay = 4;
// sensor connected to:
// Trig — 12, Echo — 13
Ultrasonic ultrasonic(12, 13);
void setup()
{
Serial.begin(9600);// start the serial port
}
void loop()
{
float dist_cm = ultrasonic.Ranging(CM);// get distance
if (dist_cm == 0)
{
Serial.println(digitalRead(13));
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
pinMode(13, INPUT);
}
}
Serial.println(dist_cm); // print the distance
delay(100); // arbitary wait time.
}
Не знаю, от чего зависит правильность измерения… Но мне пришлось вводить поправочный коффициент cm=cm*1.15, подобранный экспериментально, только тогда показания стали более-менее правильные. Проверял на двух имеющихся датчиках — от конкретного экземпляра не зависило. Ну и ещё выбрал тип cm не int, а float, хотя такая точность и нафиг тут не нужна, но так всё смотрится серьёзнее )))
Вот только определение расстояния не правильно… для СМ так точно.
Звук проходит от излучателя до датчика расстояние Х со скоростью 340 м/с (скорость звука, конечно) отталкивается и возращается. Тоесть преодолевает расстояние 2Х.
Выходит, что 2Х/340=Т, где Т- время сигнала.
обратная задача. Знаем Т, ищем Х.
Х=Т*340/2 это в метрах. Чтоб в сантиметры перевести, думаю, не нужно рассказывать что делать.
Или еще проще вариант (без знаний школьной программы физики): открываем даташит на английском, читаем формулу определения расстояния… как-то так.
а можете дописать в коде чтоб при достижении 5 сантиметров издавался сигнал?
Никогда не работал с адруино. Шью контроллеры и к ним все подключаю.
Но думаю, если действительно нужно то немного почитав можете разобраться)
А если не разобрались, то не сильно то и нужно наверное)
в продолжении темы — вопрос по подключению нескольких датчиков:
Специфика ситуации, в том, что нужно показать принцип работы для дальнейшей полноценной разработки.
Кому интересно — некоторое время игрался с датчиками оценивая точность измерения ( с шагом 1 см). Итог:
— в 90% случаев, начиная от 4 см погрешность ~ -1 см. Т.е как-бы с запасом, что совпадает с одним из предыдущих ораторов
— если датчики рядом друг с другом и есть пересечение направлений работы — данные скачут.
— если расстояние до цели больше 60-70 см резко увеличивается частота появления нулевых результатов. Это для меня стало понятно не сразу, но оказалось причиной «зависания» — т.е. сенсор долго ждет сигнала, что воспринимается как зависание, а не получив его выдает 0. Интересный факт: если датчик один, но это «навсегда», если подключено 2 датчика, мало того, что это не влияет на результат второго датчика, но и поле 1-2 циклов оживает и первый
Есть задача: Нужно подключить около 50-ти таких датчиков.
В связи с чем, не обладая глубокими познаниями, пока что пытаюсь решить следующие вопросы:
1) Т.к. нужно много входов — берется Arduino Mega. Возможен ли такой вариант работы: каждый выход Echo на каждом датчике получает свой вход на ардуине. В то же время, для экономии выходов — все входы Trig получают сигнал от одного выхода на ардуине. Пробовал с 2-мя датчиками — работает. Жду прихода остальных 48 — к каким проблемам готовиться? В итоге на 50 датчиков: занят 50 входов + 1 выход.
2) Предполагаю, что на такое количество датчиков будет нужно доп питание для сенсоров — из каких пропорций исходить? Что посоветуете?
3) Уже потратил время на входные сдвиговые регистры. Принцип работает, но с датчиками типа 0/1. Для hs-sr04 в таком виде не подходит — выдает 0 (при минимальном расстоянии)/1. НО! Т.к. при стандартном подключении используются цифровые входы — предполагаю что и в случае со сдвиговыми регистрами есть способ заставить это работать… при наличии головы)) Так ли это?
4) выше решение найдено через мультиплексоры. Вопрос — почему через стандартный способ подключения, используя цифровые входы на сдвиговых регистрах не работает/не понятно как делать, а на аналоговых — работает?
5) какие минусы решение за счет увеличения количества портов (-> mega 2560) имеет по сравнению с использованием мультиплексоров/СР… или можно так работать?
А вам насколько часто эту толпу опрашивать надо?такой например и вешать все датчики на него (не забыв объединить земли с дуиной). Кстати а входное питание у вас какое предполагается?
1)плохой вариант — у вас будут «щёлкать» одновременно все датчики мешая друг другу, да и существенный бросок потребления будет впустую. Лучше наоборот — объеденить входы и каждому по выходу… Правда в этом случае вы будете «слышать» щелчёк одного всеми датчиками сразу — тоже не вариант=/
2)посоветую брать DC-DC,
3)У регистров слабо прогнозируемая задержка(в случае использования ардуины и библиотек), покаааа по SPI все битики протолкнуться, а вам время надо точно мерить — не пойдёт. Способ есть, но несколько заморочный — придётся разобраться в работе и датчиков и регистров и написать скетч не используя библиотеки — так, чтобы вы начинали мерить время именно от защёлкивания в регистры пропихнутого значения — каждому датчику по пину дуины для Echo, а Trig через регистры. Но там всё равно возникает масса вопросов — надо экспериментировать, и опять же учитывать задержки или, возможно, поставить одновибраторы на выход регистров… и опять учитывать задержки=)
4)Мультиплексор это (крайне грубо) — как галетный переключатель — после выставления адреса, пин дуины и датчика соединены «напрямую» — нет значимых задержек.
5)Можно и так работать.
Рекомендую капать в сторону мультиплексоров — причём мультиплицировать оба пина датчика.
Хотелось бы как можно чаще. Приемлемо 1 сек. На счет эха от соседних датчиков, думаю с этим можно справиться. Предполагается расставлять датчики в линию, что позволит опрашивать датчики не сразу все, а через 1(2,3…) и возвращаться к пропущенным. Думаю, — это позволит избежать чужого эха.
По напряжению, предполагаю отдельный блок питания на 5в от сети для датчиков. И Ардуина от компа — для обработки результатов. Задача примитивная, поэтому планирую обрабатывать все на Visual Basic.
Да, точность работы СР и манипуляции с этим делом явно выходят за пределы моего понимания 🙂
Буду экспериментировать с мультиплексором.
Алиэкспресс вчера отписался, что груз отправлен — посмотрим что выйдет.
Конечно, по уму — нужно это дело доверить грамотным людям за деньги для дальнейшего вывода на, хотя бы, мелкосерийное производство. Но где их найти?:)
сбрасывайте ТЗ на [email protected], обсудим.
Спасибо! Разобрался! Но в библиотеке Ultrasonic обнаружил одну ошибку. Функция Ranging возвращает только целочисленные значения сантиметров или дюймов длинной long. На самом деле, можно получать значения float, при условии если делить значения duration на 29.0 и 2.0 для сантиметрового значения и на 74.0 и 2.0 для значения в дюймах.
Или же, если не лезть в библиотеку, то просто в скетче написать:
Спасибо огромное за библиотеку.
Среди всего зоопарка — единственная нормально работала с двумя HC-SR04’ми.
Для точности измерения, махал перед ними рядом с линейкой.
Погрешность +-5см добился при таких делителях:
… почему так, не смог понять.
Один вопрос: как можно уменьшить задержку ожидания импульса. А то тормозит весь код, когда датчики не могут поймать (или передать оО) сигнал.
Сам столкнулся с такой проблемой с трех датчиков задержка доходила до 3 секунд
Решается так
Библиотека Ultrasonic файл Ultrasonic.cpp
строка
Читаем документацию
pulseIn(pin, value)
pulseIn(pin, value, timeout)
Параметры
pin: номер порта вход/выхода, на котором будет ожидаться сигнал. (int)
value: тип ожидаемого сигнала — HIGH или LOW.
timeout (опционально): время ожидания сигнала (таймаут) в микросекундах; по умолчанию — одна секунда. (unsigned long)
Просто меняем на
и все нормально, можно поменять и на меньшее значение 38мс — 38000
Помогите, пожалуйста, ламеру! 🙂
Использую датчик HC-SR04, Arduino micro и источник питания 12в (с него питаются ленты светодиодов)
Пытаюсь сделать плавную регулировку яркости от расстояния. тестирую на 13м светодиоде. Код fade-а выглядит примерно так
Но проблема в том, что если мерить свыше 50см, то при работе от источника питания диод горит постоянно. При условии до 50см, все нормально. При работе от USB все тоже хорошо. куда копать?! Голову всю сломал уже…
функцияanalogWrite() работает только на определённых пинах, поддерживающих вывод в режиме ШИМ