1. 项目概述与设计思路
这个基于STM32的扫地机器人仿真系统,本质上是一个嵌入式开发综合实践项目。作为从事嵌入式开发多年的工程师,我认为这类项目最能锻炼开发者对硬件接口、传感器融合和实时控制的理解。整个系统采用模块化设计思路,将复杂功能分解为多个可独立开发和测试的子系统。
核心控制器选用STM32系列单片机,具体型号可以根据项目复杂度选择STM32F103C8T6(中端性能)或STM32F407VET6(高性能)。选择STM32主要基于三点考虑:首先,其丰富的外设接口(多达8个定时器、多个ADC通道、I2C/SPI/USART接口)完美适配本项目需求;其次,成熟的HAL库和CubeMX工具链能大幅降低开发难度;最后,性价比极高,批量采购单价可控制在20-50元区间。
2. 硬件系统架构详解
2.1 传感器选型与布局
避障系统采用多传感器融合方案:
-
HC-SR04超声波传感器(正前方1个):测量距离范围2-400cm,精度±3mm。安装在机器人正前方,倾斜15°向下安装可避免地面反射干扰。实际测试发现,当距离小于20cm时测量最准确,因此设置15cm为紧急制动阈值。
-
红外避障传感器(左右各1个):选用E18-D80NK光电开关,检测距离3-80cm可调。通过实验对比,将检测距离设置为15cm效果最佳。安装时要注意传感器离地高度(建议5-8cm),避免误检地面纹理。
-
MPU6050姿态传感器:通过I2C接口连接,采样频率设置为100Hz。实测发现,当X或Y轴角度超过30°时应触发防倾倒保护。特别注意:MPU6050需要严格的校准流程,上电后需静置2秒进行自校准。
2.2 驱动系统设计
电机驱动采用L298N双H桥模块,关键参数配置:
c复制// 电机PWM配置(使用TIM3通道1、2)
htim3.Instance = TIM3;
htim3.Init.Prescaler = 71; // 72MHz/(71+1)=1MHz
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 999; // 1MHz/(999+1)=1kHz PWM频率
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
电源方案采用两级稳压:
- 18650锂电池组(7.4V)→LM2596降压至5V(供传感器)
- 5V→AMS1117-3.3V(供STM32)
实测整机工作电流:空闲时约150mA,运动时峰值可达1.2A,建议电池容量不低于2000mAh。
3. 核心算法实现
3.1 避障决策逻辑
开发出三级避障策略:
- 当超声波检测到障碍物<30cm时,减速至50%速度
- 距离<20cm时停止前进,启动转向决策:
- 左右红外同时检测到障碍:后退→右转120°
- 仅左侧检测到:右转45°
- 仅右侧检测到:左转45°
- 紧急情况(距离<10cm或倾斜>30°):立即刹停
c复制void Obstacle_Avoidance() {
float distance = Ultrasonic_Measure();
int left_ir = HAL_GPIO_ReadPin(IR_LEFT_GPIO_Port, IR_LEFT_Pin);
int right_ir = HAL_GPIO_ReadPin(IR_RIGHT_GPIO_Port, IR_RIGHT_Pin);
if(distance < 10 || MPU6050_GetTilt() > 30) {
Motor_Stop();
return;
}
if(distance < 20) {
if(!left_ir && !right_ir) {
Motor_Backward(50, 1000);
Motor_TurnRight(120);
} else if(!left_ir) {
Motor_TurnRight(45);
} else if(!right_ir) {
Motor_TurnLeft(45);
}
} else if(distance < 30) {
Motor_SetSpeed(50);
}
}
3.2 运动控制算法
采用差分驱动模型,建立运动学方程:
code复制左轮速度 Vl = V - (ω×L)/2
右轮速度 Vr = V + (ω×L)/2
其中:
V = 前进速度(cm/s)
ω = 角速度(rad/s)
L = 轮距(实测15cm)
通过PID控制器实现精准转向:
c复制typedef struct {
float Kp, Ki, Kd;
float integral, prev_error;
} PID_Controller;
float PID_Update(PID_Controller* pid, float error, float dt) {
pid->integral += error * dt;
float derivative = (error - pid->prev_error) / dt;
pid->prev_error = error;
return pid->Kp*error + pid->Ki*pid->integral + pid->Kd*derivative;
}
// 转向角度控制示例
void Motor_Turn(float target_angle) {
PID_Controller turn_pid = {0.8, 0.05, 0.1, 0, 0};
float current_angle = 0;
while(fabs(target_angle - current_angle) > 2.0) {
float error = target_angle - current_angle;
float output = PID_Update(&turn_pid, error, 0.01);
Motor_SetSpeed(-output, output);
HAL_Delay(10);
current_angle += MPU6050_GetYawRate() * 0.01;
}
Motor_Stop();
}
4. 系统集成与调试
4.1 外设初始化序列
正确的初始化顺序至关重要:
- 先初始化系统时钟和GPIO
- 接着初始化I2C(MPU6050)
- 然后初始化定时器(PWM输出)
- 最后初始化USART(调试输出)
特别注意:MPU6050初始化后需要200ms启动时间才能读取有效数据
4.2 多任务调度方案
虽然未使用RTOS,但通过状态机实现伪多任务:
c复制typedef enum {
STATE_IDLE,
STATE_CLEANING,
STATE_AVOIDING,
STATE_ERROR
} RobotState;
void Main_Loop() {
static RobotState state = STATE_IDLE;
static uint32_t last_clean = 0;
switch(state) {
case STATE_IDLE:
if(HAL_GetTick() - last_clean > 5000) {
state = STATE_CLEANING;
Relay_Control(1, 1); // 开启清扫
}
break;
case STATE_CLEANING:
Obstacle_Avoidance();
if(MPU6050_GetTilt() > 30) {
state = STATE_ERROR;
}
break;
case STATE_ERROR:
Motor_Stop();
Relay_Control(0, 0);
OLED_ShowError();
break;
}
}
5. 性能优化技巧
5.1 传感器数据滤波
针对超声波传感器的噪声问题,采用移动平均滤波:
c复制#define FILTER_WINDOW 5
float distance_filter[FILTER_WINDOW];
uint8_t filter_index = 0;
float Ultrasonic_Filter(float new_value) {
distance_filter[filter_index] = new_value;
filter_index = (filter_index + 1) % FILTER_WINDOW;
float sum = 0;
for(int i=0; i<FILTER_WINDOW; i++) {
sum += distance_filter[i];
}
return sum / FILTER_WINDOW;
}
5.2 低功耗设计
通过以下措施降低功耗:
- 传感器间歇工作模式(超声波每200ms激活一次)
- 当10秒无移动时自动进入休眠(电流降至20mA)
- PWM频率优化为1kHz(兼顾性能和功耗)
c复制void Enter_LowPower() {
HAL_GPIO_WritePin(SENSOR_PWR_GPIO_Port, SENSOR_PWR_Pin, GPIO_PIN_RESET);
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
HAL_RTCEx_EnableLowPower(&hrtc);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
6. 常见问题排查
6.1 超声波测距不稳定
- 检查VCC电压(需稳定5V)
- 确保Trig脉冲宽度≥10μs
- 添加100uF电容到电源引脚
- 避免测量表面吸音材料(如绒毛地毯)
6.2 电机异常抖动
- 检查PWM频率(建议500Hz-2kHz)
- 验证电机电源与逻辑电源隔离
- 在电机两端并联续流二极管
- 确保H桥散热良好
6.3 MPU6050数据漂移
校准流程必须包含:
- 水平静置2秒采集零偏
- 各轴旋转360°校准灵敏度
- 存储校准参数到Flash
7. 扩展功能建议
- 路径记忆功能:添加AT24Cxx EEPROM存储运动轨迹
- 手机APP控制:换用HC-05蓝牙模块实现真机交互
- 自动回充:增加红外接收管识别充电座信标
- 灰尘检测:加装GP2Y1010AU0F光学灰尘传感器
c复制// 蓝牙指令处理示例
void BT_CommandHandler(uint8_t* cmd) {
switch(cmd[0]) {
case 'F': Motor_Forward(atoi(cmd+1)); break;
case 'B': Motor_Backward(atoi(cmd+1)); break;
case 'L': Motor_TurnLeft(atoi(cmd+1)); break;
case 'R': Motor_TurnRight(atoi(cmd+1)); break;
case 'S': Relay_Control(cmd[1]-'0', cmd[2]-'0'); break;
}
}
这个项目最让我惊喜的是MPU6050的姿态解算稳定性。经过反复测试,发现将DMP(数字运动处理器)输出频率设置为100Hz,配合互补滤波,可以获得最佳效果。另外提醒初学者,电机驱动部分务必做好电源隔离,我在最初版本中就因为共地问题烧毁过两个STM32芯片。