roboforum.ru

Технический форум по робототехнике.


Алгоритм работы с УЗ локатором HC-SR04

Автомат, адаптивный автомат ... разум

Алгоритм работы с УЗ локатором HC-SR04

Сообщение Radist » 11 июн 2024, 20:25

Наверняка вы уже знаете этот локатор – стоит дешево, работает хорошо. В интернете много написано, как работать с этим локатором. Хотелось бы более подробно рассказать об этом, тем более что нюансов там хватает.
На модуле находятся четыре контакта, к двум из них подается питание +5В, один контакт управляет работой передатчика, по оставшемуся контакту приходит сигнал дальности.
Чтобы запустить процесс измерения – надо на контакт «trig» выдать импульс положительной полярности длиной 10 мкс. С этим справится любой вывод порта. Это первый аппаратный ресурс. Информация о расстоянии заключена в длине импульса положительной полярности, который приходит с контакта «echo». Этот сигнал я рекомендую подать на вход внешнего прерывания.
Теперь немного теории. Во многих описаниях работы с этим локатором говорится примерно следующее: «если длину импульса, выраженную в микросекундах, разделить на 58 (некоторые более дотошные предлагают делить на 58.3), то получится расстояние до препятствия в сантиметрах». Я не любитель готовых формул, поэтому сейчас я ее выведу.
Как мы помним со школы, путь – это скорость, умноженная на время (не забываем, что единицы измерения должны быть учтены). В нашем случае сигнал прошел путь до препятствия и обратно, а это значит, что в формуле путь удвоенный. Скорость звука в воздухе принимают равной 343 м/с. Переводим скорость в см/мкс, время в микросекундах у нас будет; формула приобретает вид:
S = (34300*t)/(2*1000000) = t*0.01715 = t/58.3
В этой формуле все прекрасно, но мне она не нравится по следующим причинам:
– скорость нельзя считать константой, она равна 343 м/с при 20 градусах;
– считать время в микросекундах не всегда возможно;
– работать с дробными числами крайне время затратно и не удобно;
– я не люблю делить, я люблю умножать;
– инженеры не любят сантиметры, зато любят миллиметры.
Ну а сейчас пробежимся по всем пунктам и попробуем их улучшить.
Скорость звука в воздухе в диапазоне плюс/минус 50 градусов практически линейна (не верите – найдите таблицы и аппроксимируйте сами). Уравнение у нас будет следующее: V(t) = 0.6*t + 331 [м/с], температура в градусах. Сейчас во многих микросхемах (микроконтроллеры, внешние АЦП, акселерометры) есть датчики температуры. Если при инициализации программы измерить температуру и вычислить скорость звука в воздухе, то точность определения расстояния сильно повысится. К этому я еще вернусь.
Прикинем, какой нужен ресурс для подсчета времени. Понятно, что считать надо с малым тиком, иначе сильно вырастет погрешность. Поэтому кварц нужен большой, 8 или 16 МГц. При 8 МГц и делителе СК восьмибитный таймер насчитает всего 32 мкс, а это меньше одного сантиметра. При СК/8 насчитает 256 мкс, а это около 5 см. А локатор может работать до 400 см. Использовать 16 разрядный таймер я не хочу – у робототехников его два ШИМ канала обычно задействованы для управления моторами. Поэтому нужен регистр-расширитель таймера. Если использовать кварц 8 МГц и СК/8, то наш таймер как раз будет считать в микросекундах. А если нам нужен кварц для поддержки скоростей УАРТа? Например, 7.3728 МГц. Поэтому я ушел от понятия «реальное время в микросекундах» к понятию «время в условных попугаях, которые я назвал «тики»». Как с этим работать я поясню на этапе вывода формулы.
Ну а три остальных пункта я также поясню при выводе формулы, которым сейчас и займусь.
Исходная формула: S = (V*t)/2, путь пока в метрах, скорость в м/с, время в секундах.
Хочу, чтобы путь был в мм, скорость в мм/мкс, время в мкс (но задавать его в тиках). Формула преображается (смотрите, что осталось старого, а что добавилось):
S = (V*1000*t*8)/(7.3728*2*1000000) = (V*t)*(8000/14745600)
S = (V*t*0.00054253472222222)
Чтобы избавиться от такого неудобного числа, умножим и разделим это выражение на (65536*65536). Окончательная формула имеет вид:
S = (V*t*2330169)/(65536*65536).
Красота: никаких дробных чисел, никакого деления. В формуле скорость задается в м/с, время задается в тиках. Сперва два байта скорости умножаются на два байта тиков – получаем 4 байта (или меньше). Потом эти четыре байта умножаем на три байта коэффициента – получаем 7 байтов. Отбрасываем четыре младших байта (но смотрим на старший бит отбрасываемого хвоста – если он равен единице – к результату прибавим единицу, это у нас такое округление будет). Результат в мм остается в трех старших байтах, при этом самый старший будет равен нулю (4000 мм умещаются в два байта).
Вот такая вот математика.
Теперь к алгоритмам.
Счетчик настраивается на СК/8, имеет регистр-расширитель, в прерывании просто инкрементирует его.
Подпрограмма обработки внешнего прерывания тоже простая. При инициализации надо настроить срабатывание по фронту. Вот произошло внешнее прерывание. Смотрим, какое было условие срабатывания. Если по фронту, то надо обнулить таймер и расширитель, включить таймер, настроить срабатывание внешнего прерывания по спаду и выйти. Если условие срабатывания прерывания было по спаду, надо остановить таймер, переписать его содержимое в озу, поставить флаг «время посчитано», настроить условие срабатывания внешнего прерывания по фронту и выйти.
Все расчеты делаются в основной программе. Она ловит флаг «время посчитано», производит расчет и сбрасывает флаг.
Используемые переменные:
– байт расширителя таймера;
– байт из таймера;
– флаг, что измерение времени завершено;
– два байта скорости звука;
– один байт температуры воздуха в дополнительном коде (целые градусы, опционально);
– два байта для измеренного результата.
Если решите, что скорость звука в воздухе надо вычислять через температуру, то нужно модифицировать формулу (я ее уже округлил: коэффициент до десятых, свободный член до целых). Сперва все умножим и разделим на 10:
V = (6*t + 3310)/10
А теперь числитель и знаменатель умножим на 6553.6, получится
V = (6*t + 3310)*6554/65536. Дальнейшие комментарии не нужны.
Ну и напоследок я прикину, а стоит ли вообще заморачиваться с определением скорости.
Допустим, вы взяли скорость 343 м/с, она будет такой при 20 градусах. Наступило лето, солнце, жара, 30 градусов. Значит реальная скорость будет уже 349 м/с. Смотрим отношение скоростей, переводим в проценты: 349*100/343 = 1.75%. Посмотрим абсолютную погрешность для диапазона 4000 мм: 70 мм. 7 мм на один градус!!! Что-то мне такая погрешность не нравится.
Что можно сделать, чтобы не считать скорость и быть счастливым:
– задать скорость константой, но посчитать ее самому для своих условий (может у вас дома кондиционер и стабильная температура зимой и летом);
– не заморачиваться (ведь отношение к погрешности зависит от решаемой задачи).
Также задачу измерения времени можно решить при помощи таймера с режимом захвата. Я намеренно не стал этого делать. Этот таймер много чего умеет, но в нем нас больше волнуют два аппаратных ШИМ, нужных для управления моторами. Поэтому лучше им не пользоваться.
Аватара пользователя
Radist
 
Сообщения: 2254
Зарегистрирован: 01 июл 2009, 08:59
Откуда: Екатеринбург
прог. языки: асемблер AVR

Re: Алгоритм работы с УЗ локатором HC-SR04

Сообщение Radist » 27 июл 2024, 12:30

После проведения натурных экспериментов определились некоторые нюансы, которые надо учитывать.
Для начала: я не упомянул о некоторых особенностях модуля, упомянутых в описании. Если локатор «не видит» препятствие, то максимальная ширина импульса составит 36 мс. Новый запуск зондирующего импульса можно проводить не ранее чем через 10 мс после окончания импульса «эха». Также крайне полезно предусмотреть ситуацию, когда импульс эха по какой-то причине не придет на вход прерывания (датчик сломался, выпал из робота, нарушился контакт), чтобы программа не зависла.
Ну а теперь о недостатках этого модуля.
У модуля достаточно широкая диаграмма направленности. Если он стоит на роботе, который находится в середине спортзала, а датчик показывает расстояние в один метр – это значит, что он видит пол. То есть смотреть в даль – та еще проблема. Локатор надо крепить на робота высоко от пола, или крепить его так, чтобы он смотрел чуть вверх. Но тут тоже не угадаешь – перестанет видеть пол и остальные предметы своего роста. Диаграмма направленности нестабильна: я ставил робота недалеко от края стола, за этим краем через 20 см стена. Вот робот стоит на месте, а датчик показывает расстояние то до стола (под углом), то до стены. Вот если препятствие сунешь датчику под нос – вот тут стабильность хорошая. Сильно влияет отражающая поверхность и размер объекта, а также его форма и положение в пространстве относительно датчика. В общем, датчик отвечает на вопрос: около меня есть какие-то препятствия, ближайшее из них находится на таком-то расстоянии. Что делать с этой информацией роботу – даже предположить не могу. Пока думаю ограничить программно дальность «зрения» сантиметров до 30 (чтобы не видел пол перед собой). А применения этому датчику на роботе я вижу пока следующие: следование за рукой, убегание от руки, не врезаться в стены. Если все-таки смотреть на пол, то датчик может позволить «ездить по столу и не падать с него» Как датчик для определения кеглей в кегельринге не годится – может смотреть между кеглями и видеть отражение.
Плюсы у датчика тоже есть. С ним очень просто работать. Он придает роботу эстетичность в виде «головы с двумя глазами и монобровью-кварцем».
Аватара пользователя
Radist
 
Сообщения: 2254
Зарегистрирован: 01 июл 2009, 08:59
Откуда: Екатеринбург
прог. языки: асемблер AVR


Вернуться в Алгоритмы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3