1. 项目概述
这个智能测距报警小车项目是我最近完成的一个嵌入式系统设计,核心功能是通过超声波测距实现障碍物检测和报警,同时整合了温度监测、蓝牙远程控制和电机驱动等功能。作为一个典型的嵌入式系统课程设计项目,它完美展现了如何将多种传感器和执行器集成到一个完整的系统中。
我选择STM32F103C8T6作为主控芯片,主要考虑到它强大的处理能力、丰富的外设接口和适中的价格。这个芯片的72MHz主频完全能够满足实时测距、数据处理和系统控制的需求。整个系统的硬件成本控制在200元以内,非常适合学生和嵌入式爱好者练手。
提示:STM32F103C8T6俗称"蓝莓派",是STM32F1系列中最受欢迎的型号之一,具有64KB Flash和20KB RAM,支持多种通信接口。
2. 硬件设计与选型
2.1 核心模块选择
2.1.1 主控芯片:STM32F103C8T6
选择这款芯片主要基于三点考虑:
- 性价比高:相比Arduino,STM32性能更强且价格更低
- 开发资源丰富:有完善的HAL库和大量开源项目参考
- 外设接口齐全:支持PWM输出、USART、I2C等必要接口
2.1.2 超声波测距模块:HC-SR04
这个模块的测距范围是2cm-400cm,精度可达3mm,完全满足小车避障需求。我实测发现,在室内环境下,它的测量误差通常在±1cm以内。需要注意的是,模块的Trig和Echo引脚需要分别连接到STM32的GPIO口,Trig用于触发测距,Echo用于接收回波信号。
2.1.3 温度传感器:DS18B20
选用DS18B20主要看中它的单总线接口和±0.5℃的精度。这个传感器对超声波测距的温度补偿至关重要,因为声速会随温度变化(v=331.4+0.6T m/s)。实际使用中发现,如果不做温度补偿,在极端温差环境下测距误差可能达到5%以上。
2.2 电路设计要点
2.2.1 电源设计
系统采用7.4V锂电池供电,通过AMS1117-3.3稳压芯片为STM32和传感器提供3.3V电源。电机驱动模块直接使用电池电压。这里有个坑要注意:AMS1117的最大输入电压是12V,但瞬态电压可能超过这个值,建议在输入端加一个16V的TVS二极管做保护。
2.2.2 电机驱动电路
使用SDC9150电机驱动模块,它内置双H桥电路,可以同时驱动两个直流电机。接线时特别注意:
- PWM输入信号需要串联100Ω电阻
- 电机电源和逻辑电源要分开
- 每个电机输出端要并联续流二极管
3. 软件设计与实现
3.1 系统主流程
程序采用前后台架构,主循环中依次处理各个功能模块:
c复制while(1) {
key_scan(); // 按键扫描
get_distance(); // 超声波测距
get_temperature(); // 温度测量
alarm_check(); // 报警判断
oled_show(); // 数据显示
bluetooth_proc(); // 蓝牙通信
motor_ctrl(); // 电机控制
HAL_Delay(50); // 50ms周期
}
3.2 超声波测距实现
测距核心代码如下,关键是要处理好时序:
c复制void get_distance(void) {
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
delay_us(10);
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) == GPIO_PIN_RESET);
uint32_t start = HAL_GetTick();
while(HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) == GPIO_PIN_SET);
uint32_t end = HAL_GetTick();
float time = (end - start) * 1e-3; // 转换为秒
distance = (331.4 + 0.6 * temperature) * time / 2 * 100; // 单位cm
}
3.3 温度补偿算法
由于声速随温度变化,必须进行补偿。我采用的补偿公式如下:
code复制补偿距离 = 原始距离 × (1 + 0.00183 × (当前温度 - 25))
这个公式基于声速与温度的关系推导而来,实测可以将温度引起的误差降低到1%以内。
4. 系统调试与优化
4.1 常见问题排查
-
超声波测距不稳定
- 检查电源是否稳定,建议在VCC和GND之间加10uF电容
- 确保测量面平整,避免漫反射
- 适当增加两次测量的间隔时间(建议≥60ms)
-
蓝牙连接不稳定
- 检查天线是否完好
- 确保波特率设置一致(通常为9600或115200)
- 避免强电磁干扰环境
-
电机驱动异常
- 检查PWM频率是否合适(建议5-10kHz)
- 测量电机工作电流,确保不超过驱动芯片限值
- 检查电机两端是否并联了续流二极管
4.2 性能优化技巧
-
中断优化
将超声波Echo信号检测改为外部中断方式,可以更精确地测量回波时间。配置方法:c复制GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = ECHO_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(ECHO_GPIO_Port, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTIx_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTIx_IRQn); -
滤波算法
对距离测量值进行滑动平均滤波,可以有效消除偶然误差:c复制#define FILTER_SIZE 5 float distance_buf[FILTER_SIZE]; float filter_distance(float new_val) { static uint8_t index = 0; distance_buf[index++] = new_val; if(index >= FILTER_SIZE) index = 0; float sum = 0; for(int i=0; i<FILTER_SIZE; i++) { sum += distance_buf[i]; } return sum / FILTER_SIZE; }
5. 功能扩展建议
这个项目还有很大的扩展空间,以下是我实践过的几种改进方案:
-
增加红外避障
在车体两侧加装红外避障传感器,可以检测超声波盲区的障碍物。推荐使用E18-D80NK光电开关,检测距离3-80cm可调。 -
实现PID速度控制
通过编码器反馈和PID算法,可以让小车速度更稳定:c复制void PID_Control(float target_speed) { static float err_sum = 0, last_err = 0; float err = target_speed - current_speed; err_sum += err; float output = Kp*err + Ki*err_sum + Kd*(err-last_err); last_err = err; set_motor_speed(output); } -
添加摄像头模块
配合OpenMV或ESP32-CAM模块,可以实现图像识别和跟踪功能。不过这会显著增加系统复杂度,需要更强的处理器支持。
在实际调试过程中,我发现几个值得注意的细节:
- 超声波模块的安装角度要略微向下倾斜,避免地面反射干扰
- 电机驱动电路的地线要足够粗,否则可能导致控制信号异常
- OLED显示屏刷新率不宜过高,否则会出现闪烁现象
- 蓝牙模块天线的位置会影响通信距离,建议远离金属部件
这个项目从硬件设计到软件调试大约花了两周时间,最大的收获是对嵌入式系统整体设计有了更深入的理解。特别是如何平衡实时性要求和资源限制,这是在理论课上学不到的实战经验。
