一、系统架构设计
1、一发多收拓扑
发射探头
│
▼
┌─────────────┐
│ 超声波束 │
└──────┬──────┘
│
┌─────┼─────┐
▼ ▼ ▼
接收1 接收2 接收3
(Rx1) (Rx2) (Rx3)
│ │ │
└──┬──┴──┬──┘
│ │
时间差Δt1 Δt2
│ │
距离解算 → 目标位置
2、系统指标
| 参数 | 指标 |
|---|
| 工作频率 | 40kHz |
| 探测距离 | 0.2m ~ 5m |
| 角度覆盖范围 | 120° |
| 测距精度 | ±2cm |
| 响应时间 | < 50ms |
| 接收通道 | 3~8个 |
二、硬件设计方案
1、核心器件选型
| 器件 | 型号 | 说明 |
|---|
| MCU | STM32F407ZGT6 | 168MHz,17个定时器 |
| 发射驱动 | MAX232/TXS0108E | 高压驱动 |
| 接收放大 | LM358×2级联 | 带通滤波+放大 |
| 超声波探头 | TCT40-16T/R | 16mm,40kHz |
| 模拟开关 | CD4051 | 多路复用 |
| 电平转换 | TXS0108E | 5V/3.3V |
2、发射电路
STM32 PWM ── 74HC04 ── BS170 MOSFET ── 变压器 ── 发射探头
│
MAX232 (倍压)
3、接收电路(每个通道)
接收探头 ── 前置放大(LM358) ── 带通滤波(40kHz) ── 比较器 ── STM32
│
增益可调(电位器)
三、STM32 资源配置
1、定时器分配
TIM1 ── 发射PWM(40kHz,8个周期)
TIM2 ── 接收通道1捕获
TIM3 ── 接收通道2捕获
TIM4 ── 接收通道3捕获
TIM5 ── 系统时间基准
TIM6 ── 采样周期控制
2、GPIO 引脚定义
#define TRIG_PIN GPIO_PIN_8
#define TRIG_PORT GPIOA
#define ECHO1_PIN GPIO_PIN_0
#define ECHO2_PIN GPIO_PIN_6
#define ECHO3_PIN GPIO_PIN_6
#define SEL_A_PIN GPIO_PIN_12
#define SEL_B_PIN GPIO_PIN_13
#define SEL_C_PIN GPIO_PIN_14
四、核心代码实现
1、超声波参数定义
#ifndef ULTRASONIC_H
#define ULTRASONIC_H
#include "stm32f4xx_hal.h"
#define NUM_RECEIVERS 3
#define SOUND_SPEED 340.0f
#define TRIGGER_PULSE_US 10
#define MEASURE_TIMEOUT_MS 50
#define SAMPLE_RATE_HZ 20
typedef struct {
uint8_t channel_id;
uint32_t echo_time_us;
float distance_m;
uint8_t valid_flag;
uint32_t last_update;
} Receiver_t;
typedef struct {
Receiver_t receivers[NUM_RECEIVERS];
uint32_t trigger_time;
uint8_t measurement_done;
float target_x;
float target_y;
float confidence;
} Ultrasonic_System_t;
extern Ultrasonic_System_t us_system;
#endif
2、定时器初始化
void TIM1_Trigger_Init(void)
{
TIM_HandleTypeDef htim1;
TIM_OC_InitTypeDef sConfigOC = {0};
__HAL_RCC_TIM1_CLK_ENABLE();
htim1.Instance = TIM1;
htim1.Init.Prescaler = 84-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 25-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&htim1);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 12;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
void TIM_Receiver_Init(void)
{
TIM_HandleTypeDef htim2, htim3, htim4;
__HAL_RCC_TIM2_CLK_ENABLE();
htim2.Instance = TIM2;
htim2.Init.Prescaler = 84-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFFFFFF;
HAL_TIM_IC_Init(&htim2);
TIM_IC_InitTypeDef sConfigIC = {0};
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0x0;
HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}
3、发射控制
void Ultrasonic_Trigger(void)
{
uint32_t start_time;
us_system.trigger_time = HAL_GetTick();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
start_time = HAL_GetTick();
while(HAL_GetTick() - start_time < 1);
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
for(int i = 0; i < NUM_RECEIVERS; i++) {
us_system.receivers[i].valid_flag = 0;
us_system.receivers[i].echo_time_us = 0;
}
us_system.measurement_done = 0;
}
4、输入捕获中断处理
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint32_t ic_val1[NUM_RECEIVERS] = {0};
static uint8_t is_first_capture[NUM_RECEIVERS] = {1};
if(htim->Instance == TIM2 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
if(is_first_capture[0] == 0) {
uint32_t ic_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
uint32_t diff = ic_val2 - ic_val1[0];
us_system.receivers[0].echo_time_us = diff;
us_system.receivers[0].distance_m = (diff * 0.001f) * SOUND_SPEED / 2.0f;
us_system.receivers[0].valid_flag = 1;
us_system.receivers[0].last_update = HAL_GetTick();
is_first_capture[0] = 1;
} else {
ic_val1[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
is_first_capture[0] = 0;
}
}
}
5、一发多收距离解算
void Multistatic_Position_Estimation(void)
{
float distances[NUM_RECEIVERS];
uint8_t valid_count = 0;
for(int i = 0; i < NUM_RECEIVERS; i++) {
if(us_system.receivers[i].valid_flag &&
us_system.receivers[i].distance_m > 0.2f &&
us_system.receivers[i].distance_m < 5.0f) {
distances[valid_count++] = us_system.receivers[i].distance_m;
}
}
if(valid_count < 2) {
us_system.confidence = 0.0f;
return;
}
if(valid_count >= 2) {
float d1 = distances[0];
float d2 = distances[1];
float receiver_spacing = 0.3f;
float x = (d1*d1 - d2*d2 + receiver_spacing*receiver_spacing) /
(2 * receiver_spacing);
float y = sqrt(d1*d1 - x*x);
us_system.target_x = x;
us_system.target_y = y;
us_system.confidence = (float)valid_count / NUM_RECEIVERS;
}
us_system.measurement_done = 1;
}
6、主循环处理
void Ultrasonic_Task(void)
{
static uint32_t last_trigger = 0;
uint32_t current_time = HAL_GetTick();
if(current_time - last_trigger > 1000/SAMPLE_RATE_HZ) {
Ultrasonic_Trigger();
last_trigger = current_time;
}
uint8_t all_received = 1;
for(int i = 0; i < NUM_RECEIVERS; i++) {
if(us_system.receivers[i].valid_flag == 0) {
all_received = 0;
break;
}
}
if(current_time - us_system.trigger_time > MEASURE_TIMEOUT_MS) {
all_received = 1;
}
if(all_received) {
Multistatic_Position_Estimation();
if(us_system.measurement_done) {
printf("Target: (%.2f, %.2f)m, Confidence: %.1f%%\n",
us_system.target_x, us_system.target_y,
us_system.confidence * 100);
}
}
}
五、高级功能实现
1、自适应增益控制
void AGC_Control(void)
{
static uint8_t gain_level = 1;
for(int i = 0; i < NUM_RECEIVERS; i++) {
if(us_system.receivers[i].echo_time_us < 100) {
gain_level = (gain_level > 1) ? gain_level - 1 : 1;
break;
} else if(us_system.receivers[i].echo_time_us > 5000) {
gain_level = (gain_level < 8) ? gain_level + 1 : 8;
break;
}
}
HAL_GPIO_WritePin(SEL_A_PORT, SEL_A_PIN, (gain_level & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(SEL_B_PORT, SEL_B_PIN, (gain_level & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(SEL_C_PORT, SEL_C_PIN, (gain_level & 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
2、多目标识别
typedef struct {
float distance;
uint8_t amplitude;
uint8_t channel_mask;
} Echo_Target_t;
void Multi_Target_Detection(void)
{
#define MAX_TARGETS 5
Echo_Target_t targets[MAX_TARGETS];
uint8_t target_count = 0;
for(int ch = 0; ch < NUM_RECEIVERS; ch++) {
uint32_t *echo_times = Get_Echo_Timeline(ch);
uint8_t peak_count = Find_Echo_Peaks(echo_times);
for(int p = 0; p < peak_count && target_count < MAX_TARGETS; p++) {
targets[target_count].distance = echo_times[p] * 0.001f * SOUND_SPEED / 2.0f;
targets[target_count].channel_mask |= (1 << ch);
target_count++;
}
}
Cluster_Targets(targets, &target_count);
}
六、误差分析与补偿
1、温度补偿
float Get_Sound_Speed(float temperature_c)
{
return 331.4f + 0.6f * temperature_c;
}
us_system.receivers[i].distance_m =
(diff * 0.001f) * Get_Sound_Speed(current_temp) / 2.0f;
2、时间延迟补偿
#define HW_DELAY_US 2.5f
#define SW_DELAY_US 1.2f
float Compensate_Distance(float raw_distance)
{
float time_compensation = (HW_DELAY_US + SW_DELAY_US) * 0.001f;
float distance_compensation = time_compensation * SOUND_SPEED / 2.0f;
return raw_distance - distance_compensation;
}
参考代码 实现超声波传感器一发多收的测距功能 www.youwenfan.com/contentcsv/72819.html
七、性能优化
1、实时性优化
| 优化项 | 方法 |
|---|
| 中断处理 | 使用DMA减少CPU占用 |
| 数据缓存 | 环形缓冲区存储回波数据 |
| 算法优化 | 查表法替代浮点运算 |
| 并行处理 | 多通道同时采样 |
2、抗干扰措施
float Median_Filter(float *data, uint8_t len)
{
for(int i = 0; i < len-1; i++) {
for(int j = 0; j < len-i-1; j++) {
if(data[j] > data[j+1]) {
float temp = data[j];
data[j] = data[j+1];
data[j+1] = temp;
}
}
}
return data[len/2];
}
八、测试验证
1、测试项目
| 测试项目 | 方法 | 标准 |
|---|
| 单目标测距 | 固定距离测量 | ±2cm |
| 多目标分辨 | 前后放置障碍物 | 最小间距>15cm |
| 角度特性 | 旋转目标 | 120°覆盖 |
| 抗干扰性 | 添加噪声源 | 误检率<5% |
| 长期稳定性 | 连续运行24h | 漂移<3cm |
2、标定流程
1. 静态标定:在0.5m、1m、2m、3m、4m处测量
2. 温度标定:-10°C、0°C、25°C、50°C
3. 角度标定:0°、30°、60°、90°
4. 多目标标定:前后目标分离测试
所有评论(0)