1. 项目概述
这辆基于STM32F411的电磁寻迹智能车是我最近完成的一个很有意思的项目。作为一个参加过多次智能车竞赛的老司机,我想分享一些在电磁寻迹车开发中的实战经验。不同于市面上常见的红外寻迹方案,电磁寻迹具有抗干扰强、稳定性好的特点,特别适合在复杂光照条件下运行。
整个项目采用模块化设计思路,硬件上自制了集成PCB底板,软件上基于STM32 HAL库开发,使用CubeMX进行外设配置。核心算法包括电感信号采集与处理、差比和计算、分段PID控制等。下面我会从硬件设计到软件实现,详细拆解这个项目的关键技术点。
2. 硬件设计解析
2.1 整体架构设计
智能车的硬件架构决定了系统的稳定性和扩展性。我的设计方案采用了"核心板+底板"的模式:
- 核心板:STM32F411CEU6最小系统
- 底板:集成电机驱动、电源管理、信号调理电路
这种设计有以下几个优势:
- 核心板可单独升级或更换
- 底板集成度高,减少连接线带来的干扰
- 模块化设计便于调试和维护
电源部分采用两级稳压设计:
- 第一级:7.4V锂电池降压至5V(用于舵机和外围电路)
- 第二级:5V降压至3.3V(用于MCU和传感器)
提示:电机驱动电路和模拟信号采集电路的地线要分开布局,最后在电源入口处单点共地,可有效减少电机噪声对信号采集的干扰。
2.2 电感阵列设计
电磁寻迹的核心是电感传感器阵列。经过多次实验,我最终选择了"三叉型"布局方案:
- 3个10mH工字电感呈120°夹角排列
- 中心间距35mm(适应2cm宽赛道)
- 安装高度15mm(离地距离)
这种布局相比传统一字型排列有以下优势:
- 提前感知弯道趋势(外侧电感先检测到信号变化)
- 冗余设计(任一电感失效仍可运行)
- 信号差分处理更稳定
电感选型要注意:
- 电感值:8-12mH为佳
- Q值:越高越好(建议>50)
- 尺寸:适合安装布局
2.3 PCB设计要点
底板PCB设计有几个关键点需要特别注意:
-
信号走线:
- 电感信号线要走差分对
- 远离电机驱动等大电流走线
- 必要时加屏蔽层
-
电源布局:
- 每个IC的VCC都要加去耦电容
- 电机电源单独走粗线
- 模拟部分供电可加π型滤波
-
接口设计:
- 调试接口(SWD)要引出
- 预留测试点
- 关键信号加LED指示灯
3. 软件实现详解
3.1 开发环境配置
使用STM32CubeMX进行基础配置:
-
时钟配置:
- HSE 8MHz
- PLL到100MHz主频
- APB1 50MHz
- APB2 100MHz
-
ADC配置:
- 12位分辨率
- 连续扫描模式
- DMA传输
- 采样周期56个ADC时钟
-
PWM配置:
- 定时器频率20kHz
- 通道1/2用于电机
- 通道3用于舵机
生成代码后,需要手动添加以下关键初始化:
c复制// ADC校准
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
// PWM启动
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
3.2 信号采集与处理
电感信号处理流程:
- ADC采集原始值
- 硬件滤波(RC低通)
- 软件滤波(滑动平均)
- 归一化处理
滑动平均滤波实现:
c复制#define FILTER_WIN 5 // 滤波窗口大小
uint16_t ADC_Filter(uint32_t ch) {
static uint16_t buffer[3][FILTER_WIN] = {0};
static uint8_t index = 0;
uint32_t sum = 0;
buffer[ch][index] = HAL_ADC_GetValue(&hadc1);
for(uint8_t i=0; i<FILTER_WIN; i++) {
sum += buffer[ch][i];
}
index = (index+1)%FILTER_WIN;
return sum/FILTER_WIN;
}
归一化处理:
c复制// 动态归一化
void Normalize_Sensors(void) {
static uint16_t base_val[3] = {0};
// 初始化基准值
if(base_val[0] == 0) {
for(uint8_t i=0; i<3; i++) {
base_val[i] = ADC_Filter(i);
}
return;
}
// 计算归一化值
for(uint8_t i=0; i<3; i++) {
sensor_val[i] = (ADC_Filter(i) - base_val[i]) / (float)base_val[i];
}
}
3.3 差比和算法实现
差比和算法是将电感信号转换为路径偏差的核心算法:
c复制float Get_Track_Deviation(void) {
float L = sensor_val[0]; // 左侧电感值
float R = sensor_val[1]; // 右侧电感值
float F = sensor_val[2]; // 前向电感值
// 差比和计算
float ratio = (L - R) / (L + R + 0.001f);
// 前向电感加权
if(F > 0.3f) {
ratio *= (1.0f - F*0.5f);
}
return ratio;
}
算法特点:
- 输出范围-1.0到1.0,0表示居中
- 加入前向电感加权,改善弯道性能
- 防止除零的小数0.001f
3.4 分段PID控制
分段PID根据偏差大小动态调整参数:
c复制typedef struct {
float Kp;
float Ki;
float Kd;
float integral;
float last_err;
} PID_Param;
void PID_Controller(float deviation) {
static PID_Param pid = {0};
// 参数分段
if(fabs(deviation) < 0.3f) { // 小偏差
pid.Kp = 15.0f;
pid.Ki = 0.01f;
} else { // 大偏差
pid.Kp = 25.0f;
pid.Ki = 0.0f; // 大偏差时关闭积分
}
// 积分限幅
pid.integral += deviation;
if(pid.integral > 100.0f) pid.integral = 100.0f;
if(pid.integral < -100.0f) pid.integral = -100.0f;
// PID计算
float output = pid.Kp * deviation
+ pid.Ki * pid.integral
+ pid.Kd * (deviation - pid.last_err);
pid.last_err = deviation;
// 输出限幅
output = fmaxf(fminf(output, 500.0f), -500.0f);
// 舵机控制
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1500 + (int16_t)output);
}
4. 系统调试与优化
4.1 电感信号调试
使用SWD接口和IDE的实时变量查看功能,观察电感原始信号:
-
静态测试:
- 车体居中时,左右电感值应接近
- 偏离时,差值应线性变化
-
动态测试:
- 匀速通过弯道,观察信号曲线
- 检查信号延迟情况
注意:如果信号噪声大,可以:
- 增加滤波窗口大小
- 检查PCB接地
- 调整电感谐振电容值
4.2 PID参数整定
PID参数整定步骤:
-
先调P:
- 设I=0,D=0
- 逐渐增大P直到出现振荡
- 然后取80%的值
-
再调D:
- 适当增加D抑制振荡
- 注意D太大会引入高频噪声
-
最后调I:
- 小偏差时加入积分
- 积分系数通常很小
4.3 常见问题排查
-
电感无信号:
- 检查电感连接
- 测量谐振电容两端交流电压
- 确认ADC配置正确
-
车体跑偏:
- 检查电感安装对称性
- 校准传感器基准值
- 检查电机PWM对称性
-
响应迟钝:
- 检查滤波参数是否过大
- 提高控制频率
- 调整PID参数
5. 工程代码结构
完整的工程采用分层架构设计:
code复制/Drivers // HAL库驱动
/Middlewares // 中间件
/Application // 应用层
├── adc_ctrl // 信号采集
├── motor_ctrl // 电机驱动
├── pid_ctrl // 控制算法
├── sensor // 传感器处理
└── main.c // 主逻辑
/PCB // 电路设计文件
├── Schematic // 原理图
└── Layout // PCB布局
关键设计思想:
- 硬件抽象层隔离底层依赖
- 模块化设计便于功能扩展
- 全局变量最小化
- 完善的注释和文档
移植到其他平台时���主要需要修改:
- hw_config.h中的引脚定义
- 底层驱动初始化
- 平台相关的延时函数
6. 性能优化技巧
经过多次实测,总结出以下优化经验:
-
动态基准值:
c复制// 每100ms更新一次基准 if(tick % 100 == 0) { for(uint8_t i=0; i<3; i++) { base_val[i] = base_val[i]*0.9 + ADC_Filter(i)*0.1; } } -
速度自适应:
- 根据车速动态调整PID参数
- 高速时降低P增益
- 低速时增加I增益
-
预测控制:
- 根据历史偏差预测趋势
- 提前调整舵机角度
-
能耗优化:
- 动态调整PWM频率
- 空闲时降低主频
这套方案在2cm宽的漆包线赛道上实测,可以达到1.8m/s的稳定速度,弯道通过性良好。关键是把电感信号处理和控制算法有机结合,充分发挥STM32F411的性能优势。
