Embedded HandbookПриложения
Все разделы › XI. Датчики: подключение, схемы, драйверы
STM32F103, STM32F407 · уровень средний · 7 мин чтения
Открыть в интерактивном справочнике

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: время полёта

Дальномер и датчик движения: делитель на ECHO, выход HC-SR501 — прямо на вход

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 мм: таймер точнее самого датчика.

Вход ШИМ на TIM2: фронт эха защёлкивает счётчик в CCR1 и обнуляет его, спад защёлкивает в CCR2 длительность 5824 мкс; с битом URS сброс не поднимает флаг обновления, без него — поднимает


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 Итоги

Дальше: раздел 100а «Присутствие человека радаром 24 ГГц: HLK-LD2420 — дальность по воротам, протокол UART и настройка порогов» — радар, который видит и неподвижного человека: ворота дальности, кадры команд и два порога.

Открыть в интерактивном справочнике