Ультразвуковой датчик расстояния HC-SR04
Купить на Паркфлаере
Характеристики:
Напряжение питания: 5В Ток покоя : <15мА Эффективный угол обзора: 15° Диапазон измерения дальности : 2–300 см Разрешение датчика: 0.3см Вес: 8.5г | |
Подключение:
Vcc | напряжение питания 5 вольт
| Trig | вход запускающих импульсов для процесса измерения
| Echo | выход импульса длительность которого пропорциональна расстоянию | GND | общий провод питания |
Принцип действия: На
вход Trig подается импульс длительностью не менее 10 мкс. После этого
модуль выдает 8 ультразвуковых импульса и ждет эхо. После получения эхо
датчик рассчитывает расстояние и выдает на выходе импульс с шириной
пропорциональной расстоянию. Минимальный интервал между измерениями 50
мкс. Расстояние в сантиметрах рассчитывается как ширина полученного
импульса деленная на 58.
Тестирование: Ввиду
самого своего принципа действия датчик реагирует не только на
собственное излучение, но и на посторонние шумы. Поэтому чем дальше
датчик находится от предмета (до которого меряет расстояние), тем выше
погрешность измерения. На расстоянии свыше трех метров датчик начинает
непристойно врать. А расстояние свыше четырех метров измерять просто
отказывается. Надо сказать, что если датчик не видит перед собой
препятствие, то импульс на выходе будет бесконечной длинны и фронт 1
-> 0 будет с приходом команды на следующее измерение. Для тестирования я подключил датчик к ардуине (Trig-9; Echo-3) и подправил скетч из "считаем ширину импульса ШИМ (вариант 2)". В пределах метра результат оказался просто идеальным. Текст скетча ниже:
void setup() { // Все пины порта D кроме нулевого(TX) устанавливаем как входы DDRD = 1; // Настраиваем таймер 1 на отсчет 0.5 мкс TCCR1B = 0; TCCR1A = 0; TCNT1 = 0; TCCR1A = 0; TCCR1B = 0<<CS12 | 1<<CS11 | 0<<CS10;//0x1A; //start timer with 1/8 // Разрешаем прерывания порта D по изменению уровня PCICR |= (1 << PCIE2); // настраиваем маску прерывания - пины 2-7 PCMSK2 = 0xFC; // открываем UART для вывода результата Serial.begin(9600); pinMode(9, OUTPUT); }
typedef struct { unsigned long riseTime; // время перехода 0->1 unsigned int lastWidth; // ширина импульса } tPinTimingData; volatile static tPinTimingData pinData[6]; //массив каналов volatile static uint8_t PCintLast;
uint8_t bit; uint8_t curr; uint8_t mask; uint16_t currentTime; uint16_t time;
// обработчик прерывания порта D ISR(PCINT2_vect) { // текущее время по таймеру 1 в мкс currentTime = TCNT1>>1; // Получаем состояние интересующих нас пинов curr = PIND & 0xFC; // пины, изменившие состояние mask = curr ^ PCintLast; PCintLast = curr; // в цикле просматриваем каждый пин for (uint8_t i=0; i < 6; i++) { // маска текущего пина цыкла bit = 0x04 << i; if (bit & mask) { // если 0->1 if (bit & PCintLast) // сохраняем текущее время для канала pinData[i].riseTime = currentTime; else { // рассчитываем ширину импульса time = currentTime - pinData[i].riseTime; // и сохраняем ее, если результат в разумных пределах if (time <= 17500) { pinData[i].lastWidth = time/29/2; } } } } }
void loop() { // отправляем датчику импульс в 10 мкс digitalWrite(9, LOW); delayMicroseconds(2); digitalWrite(9, HIGH); delayMicroseconds(10); digitalWrite(9, LOW); // ждем результат delay(100); // Вывод результата в UART Serial.println(pinData[1].lastWidth); } |