Наверняка вы уже знаете этот локатор – стоит дешево, работает хорошо. В интернете много написано, как работать с этим локатором. Хотелось бы более подробно рассказать об этом, тем более что нюансов там хватает.
На модуле находятся четыре контакта, к двум из них подается питание +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 мм на один градус!!! Что-то мне такая погрешность не нравится.
Что можно сделать, чтобы не считать скорость и быть счастливым:
– задать скорость константой, но посчитать ее самому для своих условий (может у вас дома кондиционер и стабильная температура зимой и летом);
– не заморачиваться (ведь отношение к погрешности зависит от решаемой задачи).
Также задачу измерения времени можно решить при помощи таймера с режимом захвата. Я намеренно не стал этого делать. Этот таймер много чего умеет, но в нем нас больше волнуют два аппаратных ШИМ, нужных для управления моторами. Поэтому лучше им не пользоваться.