100. Distance and presence: HC-SR04 and HC-SR501
Two cheap modules, both running on five volts. The HC-SR04 ultrasonic rangefinder answers with a pulse whose width is the time of flight of the sound, and the best way to measure it is not with software but with the timer itself. The HC-SR501 pyroelectric sensor reports the movement of a warm body — and only movement. The first has a five-volt output and a speed of sound that depends on the weather; the second already has a 3.3 V output.
Timer capture is in section 13, five-volt inputs in section 62, levels and connecting modules in section 95, pin interrupts in section 7.
Terms used in the documentation
Term Meaning ultrasonic ranging measuring distance with ultrasound time of flight the time the sound travels there and back trigger, echo the start pulse, the reply pulse input capture latching the counter on an input edge PWM input mode the timer itself measures the pulse width slave mode, reset mode the timer's slave mode; reset on an external event speed of sound how fast sound travels in air passive infrared (PIR) a sensor of infrared radiation changes retrigger restart of the hold time on new movement hold time how long the output stays active
100.1 Two five-volt modules
| HC-SR04 | HC-SR501 | |
|---|---|---|
| supply | 5 V | 5 V, own regulator on the module |
| output | ECHO pulse at 5 V, width is the distance | 3.3 V level: high means there was movement |
| to the STM32 input | through a 1 kΩ / 2 kΩ divider | directly |
| what it measures | distance to the surface that reflected the sound | movement of a warm body, not presence |
100.2 HC-SR04: time of flight
The STM32 sends a 10 µs pulse to TRIG. The module emits a burst of ultrasound and raises ECHO for the whole time the sound travels to the obstacle and back. The distance is that time multiplied by the speed of sound and divided by two. At 20 °C sound travels at 343.4 m/s, and 1 m gives an echo of 5824 µs — about 58 µs per centimeter; 4 m gives 23296 µs. If there is nothing to reflect from, ECHO on many modules stays high for about 38 ms; anything longer than a timeout of 25 ms is treated as no obstacle. Between measurements you need a pause so that the previous echo dies out.
100.3 The timer measures the pulse itself
You can catch the pulse width with interrupts on both edges, as with the DHT22
(section 97). But STM32 timers have a mode in which the hardware does it:
PWM input mode. Both capture channels listen to the same pin — the first
on the rising edge, the second on the falling edge — and slave mode resets the counter
on the rising edge. Then on the falling edge CCR2 holds the pulse width,
and the program only has to read it:
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;
}
The registers and bits are the same on F103 and F407; the difference is the pin: on F407
PA0 must be switched to alternate function AF1 (TIM2_CH1), on F103 the capture input
works on a pin in the input mode it has after reset. The URS bit matters:
without it the counter reset on the rising edge raises the update flag by itself, and the timeout
would "fire" on every measurement. With it only a real
overflow raises the flag — after 65 ms without a falling edge. That is why the counter
is cleared before a measurement: it runs in a circle, and without this the overflow can fall within
the 0.2–0.5 ms between the TRIG pulse and the rising edge of the echo — a false timeout in a fraction
of a percent of measurements. A write to CNT does not create an update event. Counting is
in microseconds, and one count is 0.172 mm: the timer is more precise than the
sensor itself.
100.4 Speed of sound and temperature
The speed of sound in air grows with temperature: 331.3 + 0.606·T m/s. At −20 °C it is 319.2 m/s, at 35 °C already 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;
}
What happens if you assume it is always 20 °C — the same meter in different weather:
| Temperature | Speed of sound | Echo for 1 m | With correction | As if at 20 °C |
|---|---|---|---|---|
| 0 °C | 331.3 m/s | 6037 µs | 1000 mm | 1037 mm |
| 20 °C | 343.4 m/s | 5824 µs | 1000 mm | 1000 mm |
| 35 °C | 352.5 m/s | 5674 µs | 1000 mm | 974 mm |
Without correction you get +3.7 % in frost and −2.6 % in heat. For a parking sensor
this does not matter, for a tank level gauge it is centimeters per meter. The cure is a thermometer
nearby (section 96) and the temperature passed to echo_mm.
100.5 Five volts on the echo
ECHO on the HC-SR04 outputs 5 V, while the microcontroller inputs are rated for 3.3 V. A 1 kΩ / 2 kΩ divider turns 5 V into 3333 mV — a solid high and a safe level; even on a 5 V tolerant pin a divider is more reliable (section 62). The opposite direction, TRIG from 3.3 V, most modules accept as high; if you get a picky one — a transistor switch or a level shifter (section 95).
100.6 HC-SR501: movement, not presence
A pyroelectric sensor notices a change in infrared radiation when a warm body moves from one zone of the lens to another. The module output is already 3.3 V, so it goes straight to a pin and the edge is caught with an interrupt (section 7):
int pir_active(void)
{
return (int)((GPIOA->IDR >> 2) & 1u);
}
The output stays high for a time set by a trimmer resistor, and a jumper selects whether new movement extends this hold time. Hence the main property: the sensor does not see a person sitting still. After power-up it needs time — about a minute — to settle; anything it shows during that minute is a false trigger.
100.7 Pitfalls
In frost the distance reads a few percent high. Temperature is not accounted for: a meter at 0 °C reads as 1037 mm.
The STM32 input heats up or glitches from the echo. ECHO at 5 V is connected directly. Use a 1 kΩ / 2 kΩ divider.
The timeout fires on every measurement. URS is not set: the counter reset
on the echo rising edge raises the update flag by itself.
Occasionally — a timeout for no reason. The counter is not cleared before a measurement, and its overflow fell between the TRIG pulse and the echo rising edge.
Two rangefinders interfere with each other. One hears the other's echo. Measure in turn.
Soft and slanted surfaces are "invisible". The sound does not return to the module or goes off to the side — the reading disappears or jumps.
The HC-SR501 does not see a seated person. It catches movement, not presence.
The HC-SR501 triggers by itself after power-up. It has not settled — do not trust it for the first minute.
100.8 Summary
- HC-SR04: 10 µs on TRIG, the ECHO width is the time of flight there and back; 1 m is 5824 µs at 20 °C.
- The timer measures the width itself in PWM input mode: reset on the rising edge,
CCR2on the falling edge, no interrupts;URSmakes the overflow an honest timeout. - The speed of sound is 331.3 + 0.606·T m/s: without temperature correction +3.7 % in frost and −2.6 % in heat.
- ECHO is 5 V: to the input through a 1 kΩ / 2 kΩ divider, 3333 mV.
- The HC-SR501 reports movement, not presence; its 3.3 V output goes straight to the input.
Next: section 100а "Human presence with a 24 GHz radar: HLK-LD2420 — range by gates, the UART protocol and threshold tuning" — a radar that also sees a person standing still: range gates, command frames and two thresholds.