单片机:实现HC-SR04超声波测距带温度补偿
1. 项目背景与目标
HC-SR04是一款常用的超声波传感器,用于测量距离。它通过发射超声波脉冲并接收回波来计算物体的距离。在理想情况下,超声波的传播速度是恒定的,但实际上超声波的传播速度会受到环境温度的影响,导致测量误差。因此,带温度补偿的测距方案能够提高测量精度,尤其是在温度变化较大的环境中。
本项目的目标是利用STM32单片机实现HC-SR04超声波模块的测距,并结合温度补偿,调整超声波传播速度,从而提高测量准确性。
2. 硬件设计
2.1 硬件组件
- HC-SR04超声波模块:包括发射端和接收端,能够发射超声波信号并接收反射信号。它通过触发引脚(Trig)发送信号,Echo引脚接收回波信号。
- 温度传感器:通常使用DHT11、DHT22或DS18B20等温度传感器来获取环境温度,进而计算温度对超声波传播速度的影响。
- STM32单片机:控制HC-SR04模块的工作、读取温度传感器的数据,并进行计算。
- 电源:为单片机和模块提供电源。
2.2 硬件连接
- HC-SR04:
- Trig引脚连接到单片机的GPIO输出引脚。
- Echo引脚连接到单片机的GPIO输入引脚,检测回波信号。
- 温度传感器(如DHT11):
- 数据引脚连接到单片机的GPIO输入引脚。
3. 软件设计
3.1 原理
超声波在空气中的传播速度受温度影响,可以通过公式计算:
其中,v为声速(单位:m/s),T为环境温度(单位:°C)。
通过获取当前温度,我们可以计算出实际的声速,并将其用于计算超声波的传播时间,从而得到更精确的测距结果。
3.2 测距原理
- Trig引脚:发送一个高电平脉冲(持续约10微秒)以触发HC-SR04发射超声波信号。
- Echo引脚:等待接收到超声波回波。回波持续时间(高电平时间)与超声波传播的时间成正比,回波时间ttt可通过定时器计算。
- 距离计算:
- 其中,v为声速,t为回波的时间,距离单位为米。除以2是因为回波是从目标物体反射回来的,因此测量的是往返距离。
3.3 代码实现
以下是基于STM32的示例代码,用于实现HC-SR04超声波测距并带有温度补偿:
#include "stm32f4xx_hal.h"
#include "stdio.h"
#include "dht11.h" // 假设使用DHT11温度传感器库
#define TRIG_PIN GPIO_PIN_0
#define ECHO_PIN GPIO_PIN_1
#define GPIO_PORT GPIOA
#define SOUND_SPEED_20C 343.2 // 在20°C下声速(m/s)
// 定义变量
uint32_t pulse_duration = 0;
float distance = 0.0;
float temperature = 0.0;
float sound_speed = SOUND_SPEED_20C;
// 定时器初始化
void Timer_Init(void) {
__HAL_RCC_TIM2_CLK_ENABLE();
TIM_HandleTypeDef htim2;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 8399; // 1kHz时钟(1ms中断)
htim2.Init.Period = 10000; // 自动重装载周期
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
HAL_TIM_Base_Start_IT(&htim2); // 启动定时器中断
}
// 超声波发射和接收函数
void HC_SR04_Init(void) {
// 配置Trig为输出模式,Echo为输入模式
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Trig引脚初始化
GPIO_InitStruct.Pin = TRIG_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct);
// Echo引脚初始化
GPIO_InitStruct.Pin = ECHO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIO_PORT, &GPIO_InitStruct);
}
// 触发超声波信号
void Trigger_HC_SR04(void) {
HAL_GPIO_WritePin(GPIO_PORT, TRIG_PIN, GPIO_PIN_SET);
HAL_Delay(10); // 保持10微秒
HAL_GPIO_WritePin(GPIO_PORT, TRIG_PIN, GPIO_PIN_RESET);
}
// 计算超声波回波持续时间
void Measure_Echo(void) {
pulse_duration = 0;
while (HAL_GPIO_ReadPin(GPIO_PORT, ECHO_PIN) == GPIO_PIN_SET) {
pulse_duration++;
HAL_Delay(1); // 每1ms计数
}
}
// 温度获取函数(假设使用DHT11传感器)
void Get_Temperature(void) {
temperature = DHT11_ReadTemperature(); // 从DHT11读取温度
sound_speed = 331.3 + 0.606 * temperature; // 根据温度计算声速
}
// 距离计算
void Calculate_Distance(void) {
distance = (sound_speed * pulse_duration) / 2000.0; // 距离 = 声速 × 时间 / 2
}
// 主函数
int main(void) {
HAL_Init();
// 初始化GPIO和定时器
HC_SR04_Init();
Timer_Init();
// 主循环
while (1) {
// 获取温度,计算声速
Get_Temperature();
// 触发HC-SR04发射超声波信号
Trigger_HC_SR04();
// 测量Echo引脚的回波持续时间
Measure_Echo();
// 计算距离
Calculate_Distance();
// 处理测量结果(例如输出到串口显示)
printf("Temperature: %.2f°C, Distance: %.2f meters\n", temperature, distance);
HAL_Delay(500); // 每隔500ms测量一次
}
}
4. 代码解释
-
定时器初始化:
- 使用
TIM2
定时器以1ms的频率进行计时,用于测量Echo引脚的高电平持续时间,进而计算超声波传播时间。
- 使用
-
GPIO初始化:
HC_SR04_Init()
函数配置了GPIO引脚,Trig引脚为输出模式,用于触发超声波的发射;Echo引脚为输入模式,用于读取回波信号。
-
超声波触发和回波测量:
Trigger_HC_SR04()
函数用于向HC-SR04的Trig引脚发送一个10微秒的高电平脉冲,触发超声波信号的发射。Measure_Echo()
函数用于检测Echo引脚的高电平持续时间,即超声波从发射到反射回来的时间。
-
温度获取与声速计算:
Get_Temperature()
函数通过DHT11传感器获取当前温度,并使用公式v = 331.3 + 0.606 * T
计算出实际的声速。
-
距离计算:
Calculate_Distance()
函数根据超声波的回波时间和实际声速,计算出目标物体的距离。
-
输出结果:
- 每次测量后,通过串口(
printf()
)输出温度和测得的距离。
- 每次测量后,通过串口(
5. 总结
本项目通过结合HC-SR04超声波模块和温度传感器,使用STM32单片机实现了带温度补偿的超声波测距功能。通过实时测量环境温度,计算超声波的传播速度,并据此调整测得的距离值,从而提高了在不同温度环境下的测量精度。这种方法能够适应温度变化,保证测距的稳定性和准确性。