1. 项目概述
电磁寻迹小车是智能车竞赛中的经典项目,也是工业AGV小车的简化版原型。这个基于STM32C8T6的方案,可以说是目前最经济实惠的电磁寻迹实现方案。我去年带队参加智能车竞赛时,就是用这套方案拿下了分区赛一等奖。相比动辄几百元的F4/F7系列,C8T6这颗十块钱出头的芯片完全能满足基础电磁寻迹的需求。
核心原理其实很简单:通过电感线圈检测交变磁场信号,经过运放电路处理后,由STM32的ADC采集电压值,最后用PID算法控制电机转向。听起来容易,但实际调试时会遇到各种"玄学"问题——比如电感安装角度差1°,赛道识别效果就天差地别。
2. 硬件设计解析
2.1 主控选型考量
STM32C8T6这颗芯片我用了不下50片,性价比确实无敌:
- 72MHz主频完全够用(实测PID计算周期能控制在1ms内)
- 12位ADC精度(比51单片机的10位强太多)
- 3个USART(调试、蓝牙、无线模块都能接)
- 价格只要F4的1/5(批量拿货11元/片)
注意:一定要买正版芯片!去年有队伍用了翻新片,ADC采样值跳得跟心电图似的。
2.2 电感选型与安装
推荐使用10mH工字电感(淘宝3元/个),关键参数:
- 谐振频率:20kHz左右(与赛道信号匹配)
- Q值:>50(越高灵敏度越好)
安装时有个独家技巧:用热熔胶把电感固定在PCB板边缘,然后整体倾斜45°安装。实测这种"歪头"安装方式,对S弯道的识别率提升30%以上。具体角度需要根据赛道实测微调,我的经验值是42°-48°之间最佳。
2.3 运放电路设计
必须用二级放大:
- 第一级:电压跟随器(阻抗匹配)
- 第二级:反向放大(增益约100倍)
电路图里有个容易踩坑的点——反馈电阻一定要用1%精度的金属膜电阻。我最早用5%的碳膜电阻,结果不同电感的输出能差出0.5V,根本没法统一标定。
3. 软件架构详解
3.1 ADC采样策略
采用间隔采样法,每个电感采样5次取中值:
c复制#define SAMPLE_TIMES 5
int get_median_value(uint8_t ch)
{
uint16_t values[SAMPLE_TIMES];
for(int i=0; i<SAMPLE_TIMES; i++){
values[i] = ADC_Read(ch);
delay_us(50); // 必须加延时!
}
// 中值滤波算法...
}
血泪教训:不加延时的话,采样值会受到前次转换残留电荷影响。曾经因为这个bug调了三天PID...
3.2 位置解算算法
用加权平均法计算偏差:
code复制偏差 = (V左*1 + V中左*2 + V中*3 - V中右*2 - V右*1) / (V总和)
这个公式的妙处在于:
- 中线权重最高(3倍)
- 两侧线性递减
- 自动归一化处理
实测比简单差值法过弯更平滑,特别适合"三电感"布局的方案。
3.3 PID参数整定
先说个反常识的结论:电磁寻迹的PID参数和摄像头方案完全不同!因为电磁信号变化更平缓,我们的参数经验值是:
- Kp: 0.8~1.2(太小转不过弯,太大会振荡)
- Ki: 0.001(积分项要非常小)
- Kd: 12~15(微分项反而是最大的)
调试时有个小技巧:先用纯P控制跑直线,然后突然用手推小车制造偏差,观察恢复速度。理想的响应应该是快速回正且不超调。
4. 实战调试记录
4.1 信号标定流程
上电后必须做自动标定:
- 小车放在赛道中央
- 按下校准按钮
- 左右摆动电感记录最大值/最小值
- 保存到Flash(避免每次上电重标)
标定时有个细节:要在不同位置多测几次。有次比赛前没标定好,结果赛道的金属接缝处被误判为引导线,小车直接冲出赛道。
4.2 常见故障排查
遇到最多的问题就是信号跳变:
- 检查电感外壳是否接地(不接地会引入工频干扰)
- 用示波器看运放输出(正常应该是20kHz正弦波)
- 确认所有模拟地单点连接(曾经因为地环路导致ADC值乱跳)
最奇葩的一次故障:队友的金属水杯放在小车上,导致电感Q值下降50%...所以现在我们都用塑料水杯。
4.3 赛道适应技巧
不同材质赛道要调整参数:
- 铁质赛道:信号强,可降低P值
- 铝制赛道:信号弱,需提高放大倍数
- 拼接赛道:要在接缝处降速(用光电管检测接缝)
省赛时就栽在这个坑——练习赛道是铁的,正式赛换成铝的,结果预赛直接扑街。后来我们增加了赛道类型自动检测功能。
5. 性能优化方案
5.1 动态PID调节
直道和弯道用不同参数:
c复制if(偏差 < 100){ // 直道模式
pid.Kp = 0.8;
pid.Kd = 10;
}else{ // 弯道模式
pid.Kp = 1.5;
pid.Kd = 15;
}
这个简单的逻辑让我们的圈速提升了1.5秒。关键是要找到模式切换的阈值点,可以通过历史数据统计确定。
5.2 前瞻控制算法
加入速度前馈控制:
code复制最终PWM = PID输出 + 前馈量
前馈量 = 当前速度 * 经验系数
这个方案在长直道加速时特别有效,能避免"看到弯道才刹车"的尴尬。系数需要实测调整,我们的经验值是0.03左右。
5.3 最小系统功耗
几个省电技巧:
- 关闭未用外设时钟(比如ADC不用时关时钟)
- 电机PWM频率降到1kHz(够用且省电)
- 进入低速段时关闭部分电感供电
去年国赛时有队伍因为没做功耗优化,跑完预赛电池就没电了。我们这套方案实测能连续跑2小时以上。
6. 完整代码解析
6.1 主循环逻辑
c复制while(1){
get_adc_values(); // 采集电感值
calculate_position();// 计算位置偏差
pid_calculate(); // PID运算
motor_control(); // 电机输出
delay_ms(1); // 1ms周期
}
这个1ms的控制周期是经过实测的最优值——再快会增加CPU负担,再慢会影响控制响应速度。
6.2 关键数据结构
c复制typedef struct{
float Kp,Ki,Kd;
float err,last_err;
float integral;
}PID;
typedef struct{
uint16_t adc_val[5]; // 5个电感值
int position; // 当前位置
int speed; // 当前速度
}CarState;
用结构体封装状态变量是个好习惯,特别是要参加比赛时,可以快速保存/恢复小车状态。
6.3 中断配置要点
必须配置的三大中断:
- 定时器中断(PID计算周期)
- ADC中断(DMA传输完成)
- 外部中断(起跑线检测)
配置ADC时有个坑:STM32的ADC时钟不能超过14MHz!我见过有人设成36MHz,结果采样值全是乱的。
7. 进阶改进方向
7.1 多传感器融合
可以增加:
- 光电编码器(测速更准)
- IMU(检测急弯打滑)
- 摄像头(辅助识别特殊元素)
去年国赛冠军方案就是电磁+摄像头的融合方案,不过对C8T6来说跑图像算法有点吃力,建议换F4。
7.2 无线调试接口
推荐用HC-05蓝牙模块:
c复制printf("P=%.1f,I=%.3f,D=%.1f\r\n",pid.Kp,pid.Ki,pid.Kd);
手机端用Serial Bluetooth Terminal这个APP就能实时调参。比用按键调参效率高10倍不止。
7.3 赛道记忆算法
高级玩法:记录每圈赛道特征,第二圈就能预判弯道。需要外接Flash存储数据,算法复杂度较高,适合研究生组别。
8. 全套BOM清单
最后分享下我们的物料清单(2023年价格):
| 部件 | 型号 | 单价 | 备注 |
|---|---|---|---|
| 主控 | STM32C8T6 | 11元 | 要买LQFP48封装 |
| 电感 | 10mH工字 | 3元 | 直径8mm最佳 |
| 运放 | LM358 | 0.8元 | 也可以用TL082 |
| 电机 | N20减速 | 15元 | 6V/200转 |
| 电池 | 18650 | 12元 | 两节并联 |
总成本可以控制在150元以内,比官方指定的K60方案便宜多了。所有元件都能在淘宝买到,建议多买几套备用——特别是电感,调试时容易烧。
