Следующим шагом для небольшого проекта стал модуль измерения расстояния HC-SR04.
Попробуем завести эту штуковину с помощью микроконтроллера PIC16f628a 🙂
Начнем, пожалуй, с даташита.
Девайс имеет 4 пина: Vcc, Gnd, Trig, Echo. Если с первыми двумя все понятно, то с остальными не совсем. Если их рассматривать по простому,то по Trig мы управляем датчиком, а по Echo – снимаем результаты.
Вот как это выглядит в даташите:
Мы поднимаем линию Trig на 10 мкс и ждем сигнала на Echo. Тут надо сказать, что меня немного поставило в тупик две вещи: картинка выше и следующая выкладка в даташите:
You can calculate the range through the time interval between sending trigger signal and receiving echo signal.
Налицо два противоречивых указания: в одном говорится что, длина импульса пропорциональна расстоянию, во втором, что пропорционально время от посылки сигнала до получения отклика по пину Echo. Оказалось что первое утверждение правильное, так что если кто будет по моей статье разбираться учтите 🙂
Чтобы получить расстояние в сантиметрах:
Расстояние (см) = Время импульса (мкс)/58
Ну вроде все понятно, пробуем получить хоть что-нибудь:
if (!RB1) { __delay_ms(100); if (!RB1) { RMeas = 0; RMeas = 1; __delay_us(10); RMeas = 0; }//if (!RB1) inner }//if (!RB1)
RMeas – пин, на который подключен вывод Trig, он настроен на выход, ну а по коду все просто – обычый короткий 10 мкс импульс по нажатию кнопки.
Собираем тестовую установку:
Примерно 13 см от платы до препятствия, +можно накинуть 1 см на расстояние от платы, до непосредственно датчика, пробуем:
630/58 = 11 см, таким образом ошибка составляет 1-1.5 см, для наших целей вполне терпимо.
Алгоритм обработки тоже видится достаточно прозрачным:
- Засекаем нарастающий фронт и запускаем таймер
- Засекаем спадающий фронт и снимаем показания таймера
- Переводим значение таймера в микросекунды и производим все необходимые вычисления
Функция снятия значений выглядит примерно так:
void GetRange() { tempTmr1 = 0; StRMeas = 0; //Инициализируем модуль RMeas = 0; RMeas = 1; __delay_us(10); RMeas = 0; StRMeas = 0; __delay_us(100); RBIE = 1; //Включаем прерывания по изменению состояния порта RBlowFlag = 0; //Статусная переменная while (!RBlowFlag) //Цикл пока не закончится импульс от Echo { if (RBhighFlag) //По возрастающему фронту { InitTimer1(); //Запускаем таймер1 RBhighFlag = 0; } } TMR1ON = 0; tempTmr1 = TMR1H; //Сливаем значение таймера в локальную переменную tempTmr1 <<= 8; tempTmr1 |= TMR1L; lcd_clear(); //и выводим инфу на дисплей lcd_goto(0x00); Range = tempTmr1/174 + 2; //Поправочный коэффициент - 2 см lcd_puts("Range, cm"); display_digit(Range, 0x40); }
Ну и небольшая часть обработчика прерываний по выводу Echo:
void interrupt isr() { if (RBIF) { if (!Recho) { RBlowFlag = 1; RB5 = 0; } if (Recho) { RB5 = 1; RBhighFlag = 1; } RBIF = 0; }//if (RBIF) } //isr()
Здесь поправочный коэффициент 2 выбран экспериментальным путем. Ну собственно и все, напоследок видео с результатом работы:
молодец!не хватает в твоей лаборатории опыта с давлением воды и датчиком освещенности
Спасибо, в первом как то необходимости не возникало, а вот со вторым как раз жду с китая фоторезисторы и буду делать регулировку подсветки экрана для небольшого проекта 🙂
а в лаборатории выложишь про освещенность ?
Там к мк отношения девайс иметь не будет, так что опишу только в проекте, который надеюсь в скором времени закончить.
сабж,а напиши пожалуйста марку фотодатчика
5516 фоторезистор обычный 🙂
извиняюсь,Сарж!