Официальный сайт компании Arduino по адресу arduino.cc
Эхолот
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пт, 21/10/2011 - 10:12
Здравствуйте!
Есть у меня плата приемопередатчика от буржуйского старого эхолота, я ее восстановил и хочу поэкспереметировать. А вот в програмировании я начинающий по сему прошу помочь. плата имеет два выхода , импульс посылки (посылки плата генерирует сама) и импульс отраженный.В теории надо измерять время между этими импульсами и из этого получать расстояние. Также несложно сделать посылку импульса вручную ( то есть ардуиной) . Ну и собственно вопрос кто как видит программу которая это сможет сделать измерение времени между сигналами приходящими на 2 разных пина,или установка пина в "1" на допустим 10 мкс и отсчет времени до прихода высокого уровня на пин IN. Будем считать что приходящий сигнал имеет стандартный ттл уровень.
Интуиция мне подсказывает что нужно использовать таймер запускаемый импульсом посылки и считать время до получения ответного сигнала но как это отразить програмно я незнаю :)
>измерение времени между сигналами приходящими на 2 разных пина
При приходе сигнала на первый пин - запомнить текущие время, При приходе сигнала на второй пин - запомнить текущие время.
Из второго времени вычесть первое.
>установка пина в "1" на допустим 10 мкс и отсчет времени до прихода высокого уровня на пин IN
Установить пин в "1", запомнить текущие время (время 1). Прибавить к нему 10мкс и сохранить как "время 3" (время когда пин нужно будет выключить). Ждать прихода высокого уровня на пин IN, запомнить текущие время (время2). От второго, отнять первое - искомая длительность.
Во время "Ждать прихода высокого уровня на пин IN" все время проверять "текущие время", если оно стало больше чем "время 3" (то есть от момента включения уже прошло 10мкс) - погасить первый пин.
Что-бы понять "как это все закодить", нужно почитать http://arduino.ru/Reference/Millis,arduino.ru/Reference/Micros,http://arduino.ru/Reference/AttachInterrupt
В фунциях-обработчиках прерываний (функция stop()), лучше не держать "ничего лишнего" (. Serial.print, все делаи и проч. лучше выносить в главный loop. В обработчике только самый необходимый минимум - захватили время, установили какой-нибудь флаг (что-бы loop знал что "пора что-то делать").
Так же глобальные переменные которые используются в обработчике прерывания лучше объявлять с модификатором volatile
http://arduino.ru/Reference/Volatile
спасибо, поробую,отпишу что получилось
установили какой-нибудь флаг (что-бы loop знал что "пора что-то делать") а можно на примере ?
Ну так в ссылке на документацию,которую я дал, есть же пример. Уставливают переменную state в обработчике, а используют ее в loop.
В вашем случае можно либо завести отдельную переменную (так код будет наглядней), например так:
При желании можно и без переменной stopRised обойтись. В качестве "признака" использовать Time2==0;
Этот скетч будет "запоминать" время прихода сигнала, но оборабатывать его только по окончании "посылки импульса".
Если за время "посылаем импульс" пришло несколько "ответок", то в Time2 попадет время последней ответки. Если нужно что-бы "первый", то в Stop() нужно проверять: если stopRised уже 1, то новое время запоминать не нужно.
Если треубется обработать "все пришедшие импульсы", ничего не пропуская, то нужно сделать какой-то буффер и в него скидывать "все запомненные времена".
Если нужно что-бы "обработка импульса" не дожидалась окончания "посылаем" импульс, то нужно пользоватся не delay, а "включили излучатель", запомнили время когда его "нужно выключить", и дальше крутимся в loop. Все время проверяя: если настало время "пора выключить" - выключили, если stopRised==1 - обработали. Тогда они будут меньше "друг другу мешать", да еще на что-то другое у проца время останется.
большое спасибо буду пробовать
Кстате, в моем примере есть еще один косяк - delay(100). Delay нельзя использовать в прерываниях.
вот поправил маленько, теперь вроде правильно считает, пока в теории без подключения к железу
на железе проверил я, только у меня ультразвуковой эхолот.
прога ловит прерывания от себя: в момент активации элолота, приёмник эхолота ловит передатчик, после на какое-то время эфир чист, потом приходит отражение.
в итоге она мерить то мериет, но делает это неправильно.
так как идёт засветка приёмника в момент передачи.
отключать и включать прёмник будет сложно, так как он требует достаточно длительного времени для включения.
а так
завтра проверю, и отпишу результат. Я пытался использовать команду detachInterrupt, но в голову почему-то не пришло то, что можно просто делать проверку на результат. Завтра напишу конкретные цифры которые она шлёт в сериал.
484 2284 2288 2996 2992 3000 3020 384 2996 2996 2996 3024 2996 3004 3024 3012 3028 464 2992 128 3012 356 3004 3008 188 2992 3008 3024 3020 2616 2996 3008 2996 3036 548 3012 3008 3016 3008 108 2896 164 3000 3024 3016 3000 2968 1244
1.
Я тоже начинающий программист, но думаю что могут быть ещё и следующие ошибки. Программа крутится в цикле нереально быстро, там 16мгц.
следовательно, ещё не успев словить отражённое прерывание, программа вернётся в начало и запустит передатчик ещё несколько раз, сделав несколько циклов, и каждый раз будет ждать прерывание, и в оконцовке, она его словит, выдаст расстояние. Но следующее прерывание будет раньше чем нам надо.
надо где-то использовать delay на максимальное расстояние, но delay это очень плохо, так как в этот момент у меня "танк" едет вперёд. А delay делает тупое зависание всего контроллера, кроме прерывания. В общем надо думать.
2.
Как каждый раз в начале цикла в loop сбрасывать значение micros в ноль.
Как после включения передатчика, ничего не делать, а просто ждать прерывание. Видется вариант маленького цикла в цикле, который опрашивает прерывание определёное время, равнное максимальному расстоянию, и после идёт обратно в loop.
как я и говорил, при резком обнаружении препятствия, она обрабатывает не те прерывания, которые нам надо.
>Я тоже начинающий программист, но думаю что могут быть ещё и следующие ошибки
Хоть вы и "начинающий", но интуиция вас не подвела :) Они есть в любой программе больше 10-ти строчек ;) Более того, вы их еще и увидеть правильно смогли. Так что дай бо что-бы все "начинающие" были такими.
>но delay это очень плохо, так как в этот момент у меня "танк" едет вперёд
Плохо, но по другим причинам. За то время пока сигнал мотнется "туда-сюда" танк далеко уехать не успеет. Все-таки скорости у них довольно разные ;) Так что за это можно не переживать.
>надо где-то использовать delay
Вы правы. Нужно. После "digitalWrite(4,LOW); //Прекращаем подачу импулса", но до ""if(stopRised== true){"
Тут не "танк", а сам контроллер "уедет дальше" не успев дождаться отражения импульса. Между ними "нужно немного подождать" и, вы опять правы, лучше это делать не через delay(), а как-то так
Получается это тот же "delay", но до "ожидания сработки импульса". Возможно в него нужно будет добавить какой-то счетчик-ограничение. Если импульс уйдет "в белый свет" и не отразится вообще, что-бы он не зависал на этом. Что-то типа "если 300 милисекунд ответа не дождались, то все сбрасывать и начинать все сначало" ( не зря вы про ""delay на максимальное расстояние" думали )
Warn на каком железе проверяете? Чтото самодельное ?
Проверяю на ультразвуковом самодельном дальномере. Передатчик на ne555, приёмник на операционнике.
Переписал чуть чуть, но всё-равно как-то не так работает, но уже лучше. И от delay пока не избавился.