100. Расстояние и присутствие: HC-SR04 и HC-SR501
Два дешёвых модуля, оба на пять вольт. Ультразвуковой дальномер HC-SR04 отвечает импульсом, длительность которого — время полёта звука, и мерить её удобнее всего не программой, а самим таймером. Пироэлектрический датчик HC-SR501 сообщает о движении тёплого тела — и только о движении. У первого пятивольтовый выход и скорость звука, которая зависит от погоды; у второго выход уже на 3,3 В.
Захват таймера — раздел 13, пятивольтовые входы — раздел 62, уровни и подключение модулей — раздел 95, прерывания от вывода — раздел 7.
Как это называется в документации
Оригинал Перевод ultrasonic ranging ультразвуковое измерение расстояния time of flight время пролёта trigger, echo запускающий импульс, ответный импульс input capture захват по входу PWM input mode режим входа ШИМ: длительность импульса меряет сам таймер slave mode, reset mode подчинённый режим таймера; сброс по внешнему событию speed of sound скорость звука passive infrared (PIR) пассивный инфракрасный датчик retrigger перезапуск выдержки при новом движении hold time время удержания выхода
100.1 Два модуля на пять вольт
| HC-SR04 | HC-SR501 | |
|---|---|---|
| питание | 5 В | 5 В, на модуле свой стабилизатор |
| выход | импульс ECHO на 5 В, длительность — расстояние | уровень 3,3 В: единица — было движение |
| на вход STM32 | через делитель 1 кОм / 2 кОм | напрямую |
| что меряет | расстояние до поверхности, отразившей звук | движение тёплого тела, а не присутствие |
100.2 HC-SR04: время полёта
STM32 подаёт на TRIG импульс 10 мкс. Модуль отправляет пачку ультразвука и поднимает ECHO на всё время, пока звук летит до препятствия и обратно. Расстояние — это время, умноженное на скорость звука и делённое пополам. При 20 °C звук летит со скоростью 343,4 м/с, и 1 м даёт эхо 5824 мкс — около 58 мкс на сантиметр; 4 м — 23 296 мкс. Если отражать нечему, ECHO у многих модулей держится около 38 мс; всё, что дольше таймаута в 25 мс, считают отсутствием препятствия. Между замерами нужна пауза, чтобы затихло прошлое эхо.
100.3 Таймер сам меряет импульс
Длительность импульса можно ловить прерываниями на оба фронта, как у DHT22
(раздел 97). Но у таймеров STM32 есть режим, в котором это делает железо:
режим входа ШИМ. Оба канала захвата слушают один и тот же вывод — первый
по фронту, второй по спаду, — а подчинённый режим сбрасывает счётчик
по фронту. Тогда в CCR2 по спаду оказывается длительность импульса,
и программе остаётся её прочитать:
void echo_timer_init(void)
{
pins();
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC = TIM2_PSC;
TIM2->ARR = 0xFFFFu;
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_1; /* оба канала слушают TI1 */
TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC2P; /* канал 1 — фронт, канал 2 — спад */
TIM2->SMCR = TIM_SMCR_TS_2 | TIM_SMCR_TS_0 | TIM_SMCR_SMS_2; /* по фронту эха — счётчик в ноль */
TIM2->EGR = TIM_EGR_UG;
TIM2->CR1 = TIM_CR1_URS | TIM_CR1_CEN; /* флаг обновления — только от переполнения */
}
#define ECHO_TIMEOUT_US 25000u /* 4 м — это 23,3 мс туда и обратно: дольше — препятствия нет */
int32_t hcsr04_us(void)
{
TIM2->CNT = 0; /* до переполнения — полные 65 мс */
TIM2->SR = 0;
GPIOA->BSRR = GPIO_BSRR_BS1; /* TRIG: импульс 10 мкс */
uint16_t t0 = (uint16_t)TIM2->CNT;
while ((uint16_t)(TIM2->CNT - t0) < 10u) { }
GPIOA->BSRR = GPIO_BSRR_BR1;
while (!(TIM2->SR & TIM_SR_CC2IF))
if (TIM2->SR & TIM_SR_UIF)
return -1;
uint32_t w = TIM2->CCR2; /* защёлкнуто по спаду эха */
if (w > ECHO_TIMEOUT_US) /* дольше 25 мс — препятствия нет */
return -1;
return (int32_t)w;
}
Регистры и биты у F103 и F407 одни и те же; разница — в выводе: у F407
PA0 надо перевести в альтернативную функцию AF1 (TIM2_CH1), у F103 вход
захвата работает на выводе в режиме входа после сброса. Бит URS важен:
без него сброс счётчика по фронту сам поднимает флаг обновления, и таймаут
«срабатывал» бы на каждом замере. С ним флаг поднимает только настоящее
переполнение — через 65 мс без спада. Поэтому перед замером счётчик
обнуляют: он бежит по кругу, и без этого переполнение может прийтись на
0,2–0,5 мс между импульсом TRIG и фронтом эха — ложный таймаут в доле
процента замеров. Запись в CNT события обновления не создаёт. Счёт идёт
в микросекундах, и один отсчёт — это 0,172 мм: таймер точнее самого
датчика.
100.4 Скорость звука и температура
Скорость звука в воздухе растёт с температурой: 331,3 + 0,606·T м/с. На −20 °C это 319,2 м/с, на 35 °C — уже 352,5:
uint32_t sound_x10(int32_t t_c10)
{
return (uint32_t)(3313 + 606 * t_c10 / 1000);
}
uint32_t echo_mm(uint32_t us, int32_t t_c10)
{
return (us * sound_x10(t_c10) + 10000u) / 20000u;
}
Что будет, если считать, будто всегда 20 °C, — один и тот же метр при разной погоде:
| Температура | Скорость звука | Эхо на 1 м | С поправкой | Будто при 20 °C |
|---|---|---|---|---|
| 0 °C | 331,3 м/с | 6037 мкс | 1000 мм | 1037 мм |
| 20 °C | 343,4 м/с | 5824 мкс | 1000 мм | 1000 мм |
| 35 °C | 352,5 м/с | 5674 мкс | 1000 мм | 974 мм |
Без поправки выходит +3,7 % на морозе и −2,6 % в жару. Для парктроника
это неважно, для уровнемера в баке — сантиметры на метр. Лечение — термометр
рядом (раздел 96) и температура в echo_mm.
100.5 Пять вольт на эхо
ECHO у HC-SR04 выдаёт 5 В, а входы микроконтроллера рассчитаны на 3,3 В. Делитель 1 кОм / 2 кОм превращает 5 В в 3333 мВ — это уверенная единица и безопасный уровень; даже на выводе, выдерживающем 5 В, делитель надёжнее (раздел 62). Обратное направление, TRIG от 3,3 В, большинство модулей принимает за единицу; если попался капризный — транзисторный ключ или преобразователь уровней (раздел 95).
100.6 HC-SR501: движение, а не присутствие
Пироэлектрический датчик замечает изменение инфракрасного излучения, когда тёплое тело переходит из одной зоны линзы в другую. Выход у модуля — уже 3,3 В, так что его ставят прямо на вывод и ловят фронт прерыванием (раздел 7):
int pir_active(void)
{
return (int)((GPIOA->IDR >> 2) & 1u);
}
Выход держится в единице на время, заданное подстроечным резистором, а перемычка выбирает, продлевает ли новое движение эту выдержку. Отсюда главное свойство: сидящего неподвижно человека датчик не видит. После включения ему нужно время — около минуты — чтобы успокоиться; всё, что он покажет в эту минуту, — ложные срабатывания.
100.7 Грабли
На морозе расстояние завышено на проценты. Не учтена температура: метр при 0 °C читается как 1037 мм.
Вход STM32 греется или сбоит от эха. ECHO на 5 В подан напрямую. Делитель 1 кОм / 2 кОм.
Таймаут срабатывает на каждом замере. Не выставлен URS: сброс счётчика
по фронту эха сам поднимает флаг обновления.
Изредка — таймаут без причины. Счётчик не обнулён перед замером, и его переполнение пришлось на время между импульсом TRIG и фронтом эха.
Два дальномера мешают друг другу. Один слышит эхо другого. Замерять по очереди.
Мягкие и наклонные поверхности «не видны». Звук не возвращается к модулю или уходит в сторону — показание пропадает или скачет.
HC-SR501 не видит сидящего человека. Он ловит движение, а не присутствие.
HC-SR501 срабатывает сам после включения. Не успокоился — первую минуту ему не верят.
100.8 Итоги
- HC-SR04: 10 мкс на TRIG, длительность ECHO — время полёта туда и обратно; 1 м — 5824 мкс при 20 °C.
- Длительность меряет сам таймер в режиме входа ШИМ: сброс по фронту,
CCR2по спаду, без прерываний;URS— чтобы переполнение было честным таймаутом. - Скорость звука — 331,3 + 0,606·T м/с: без поправки на температуру +3,7 % на морозе и −2,6 % в жару.
- ECHO — 5 В: на вход через делитель 1 кОм / 2 кОм, 3333 мВ.
- HC-SR501 сообщает о движении, а не о присутствии; выход 3,3 В — прямо на вход.
Дальше: раздел 100а «Присутствие человека радаром 24 ГГц: HLK-LD2420 — дальность по воротам, протокол UART и настройка порогов» — радар, который видит и неподвижного человека: ворота дальности, кадры команд и два порога.