☰
2024电赛H题小车方案复盘:MSPM0+陀螺仪融合控制实战
2026/9/25 5:16:00 网站建设 项目流程

做2024年电赛H题的这段经历,到现在我回想起来,最值钱的不是那块省一的奖状,而是把“MSPM0 + 陀螺仪融合控制”这套方案从一团乱麻里真正跑通的那几天。H题“自动行驶小车”,听名字好像就是“小车跑起来”,但真上手你会发现,难点根本不在跑,而在“怎么知道自己在哪、该往哪偏、用什么角度拐弯”。如果你今年也要备赛,或者正准备用陀螺仪做控制,这篇复盘值得你花十分钟看完。我会把方案选型、硬件设计、融合算法、调试排障的全过程都拆开讲,重点是那些容易被忽略、却能让你少走一星期弯路的细节。

1. 赛题理解与整体设计:把H题拆成可执行的工程问题

1.1 H题表面在考小车,实际在考什么

电赛的题历来有几个特点:题目描述很简洁,但隐含的考核点特别多。2024年H题自动行驶小车,表面上看是让小车沿着指定路线跑、红绿灯停车、环岛绕行、入库停车这些动作,但评委真正想看到的是你的系统是否具备“感知—决策—执行”的完整闭环能力。也就是说,你不能光靠一堆if else去碰运气,而是要让小车在不确定性中自主修正。

举个例子,赛道上的直角弯、十字路口、斑马线、环岛,这些元素如果只靠灰度传感器循迹,在光照变化、地面反光、轮胎打滑的时候,小车很容易冲出赛道。而陀螺仪的引入,本质上是在给小车加了一个“方向感 ”——它让小车不光知道“我现在偏了多少”,还能知道“我拐弯拐了多少度”“我走上环岛后转了几圈”。这就把单纯的反应式循迹,升级成了有“体感”的闭环控制。

还有一个很关键的点:H题的评分里通常没有“完美版”,只有“完成度越高分越高”。所以我们的方案从一开始就不追求炫技,而是追求“稳定性优先、可复现性优先”。这也是我后面选型、写代码、调参数时一直遵守的原则。

1.2 为什么用MSPM0和陀螺仪这套组合

先说主控。MSPM0是TI推出的基于ARM Cortex-M0+内核的MCU系列,我在2024年备赛时选择的是MSPM0G3507,主频80MHz,Flash有128KB,RAM有32KB。这块芯片最吸引我们的地方是:性价比高、生态资料更新快,而且电赛期间TI本身提供了不少参考设计和例程。对比我们队伍之前用过的其它Cortex-M0+片子,MSPM0的定时器资源丰富,PWM输出通道多,跑两路电机调速加四路灰度采集完全够用,GPIO翻转速度也不拖后腿。

再说陀螺仪,我们用的是MPU6050。这颗芯片在电赛圈子里几乎是“标配六轴传感器”,内部集成了三轴陀螺仪和三轴加速度计,I2C接口就能通信。它最大的价值是能同时输出角速度与加速度,给姿态融合提供了原始数据来源。很多人觉得MPU6050是旧器件,但我恰恰认为,成熟方案的稳定性和资料丰富度,在比赛这种高压场景下远比“新型号”重要。

那“融合控制”到底融合的是什么?简单说,就是把MPU6050陀螺仪的角速度数据、加速计的倾角数据,以及编码器测得的轮速数据,经过滤波与加权融合后,共同作为小车转向和速度控制的反馈。为什么要融合?因为单一传感器都有硬伤:陀螺仪有温漂、积分会累积误差;加速度计对振动敏感、动态响应差;编码器只能测轮速、测不了车体姿态。三组数据互补,才能得到既平滑又有实时性的角度与速度估计。

1.3 整体系统架构和数据流

我们的系统架构其实可以拆成四层:

  • 感知层:MPU6050获取角速度和加速度、三路或四路灰度传感器获取地面赛道信息、正交编码器获取左右轮实际转速。
  • 决策层:MSPM0G3507内部运行状态机,根据灰度值和陀螺仪角度判断当前处于直道、弯道、环岛、斑马线、停车区等场景。
  • 执行层:两路直流减速电机,由MOS管驱动或TB6612驱动模块控制,PWM输出经PID计算后调节占空比。
  • 交互层:一个OLED屏幕显示状态信息、按键切换调试模式,方便赛场现场修改参数。

数据流是这样的:灰度传感器和陀螺仪的数据先进入控制循环,MSPM0每1ms读取一次MPU6050的角速度和加速度,每5ms对姿态进行一次互补滤波更新,得到当前小车相对起始方向的偏转角。与此同时,编码器通过外部计数器或定时器捕获模式,累计左右轮脉冲数,用于计算实际车速。控制核心采用速度环和转向环并联的结构:速度环保证小车匀速巡航,转向环根据偏差实时调整两个轮子的PWM差量,实现差速转向。

这套架构的最大优势在于“模块化”:任何一个传感器出问题,都能在调试阶段单独定位,不至于整车罢工。

2. 硬件搭建与关键器件选型细节

2.1 车模和驱动:底盘决定了上限

电赛老话讲,“底盘决定上限,算法决定下限。”我们用的是四轮小车底盘,前两轮为万向轮、后两轮为直流减速电机驱动,轮子是普通橡胶轮。这种底盘结构简单、转向灵活,比两轮自平衡少很多调平衡的时间成本,也比三轮全向底盘更容易做差速控制。

电机选的是带霍尔编码器的直流减速电机,额定电压6V,减速比1:30。选这种电机的原因很明确:第一,减速比合适,小车速度范围在0.2m/s到0.8m/s之间,既能稳定爬坡又能快速跑直线;第二,自带编码器,直接输出AB相脉冲,省得另外加测速模块;第三,直流电机控制简单,两个GPIO口加一个PWM通道就能驱动,MSPM0刚好能轻松应付。

驱动模块我们用了TB6612FNG。对比老式L298N,TB6612的压降小很多,在6V供电下电机的实际扭矩更足,发热也明显更低。驱动逻辑很简单:AIN1/AIN2控制A电机正反转,PWMA控制A电机速度,B通道同理。要注意的是,TB6612的VM脚接电池电压,VCC脚接3.3V逻辑电压,两者不能接反,否则会烧芯片。我们第一天就烧了一块,血泪教训。

2.2 主控最小系统和Keil5开发环境搭建

MSPM0G3507我们用的是一块小板卡,集成了板载调试器,用USB线直接连电脑就能下载程序。串口用的是USB虚拟串口,非常方便调试,直接printf就能在电脑上看数据。这里我特别想提一个高频问题:Keil5怎么添加MSPM0芯片包?

网上很多新手一上来就在Pack Installer里搜MSPM0,结果找不到,然后就卡住了。正确做法是:去TI的官方资源页下载MSPM0的DFP包,下载完成后双击或者通过Keil的Pack Installer点击“Import”手动导入。导入之后新建工程时,在Device选择界面才能看到TI->MSPM0G系列。还需要把TI提供的CMSIS-Core相关的包一并装好,否则编译会报找不到设备头文件。另外,建议把芯片包和SDK解压到不含中文和空格的路径,我试过放在“桌面”都能引发莫名其妙的编译报错。这个坑看起来小,但备赛那几天真的会卡掉半天的耐心。

除此之外,MSPM0系列在烧录方面有两种方式:一种是使用板载的XDS110调试器,另一种是使用UART Bootloader。我们全程用板载调试器,一方面下载速度够快,另一方面可以在MDK里直接打断点查看变量,对调PID帮助很大。

2.3 传感器布局:陀螺仪的位置不是随便摆的

MPU6050的安装位置直接影响姿态数据的质量。我们尝试过把模块放在车尾、车头和车辆正中心三个位置。实测下来,放在车辆几何中心偏前一点的位置效果最好,因为转弯时这个位置的离心加速度最小,加速度计受到的水平干扰也最小。说白了,你把它放轮胎正上方,小车一颠簸,读出来的加速度全是振动噪声,滤波再好也白搭。

模块固定用的双面胶和扎带,但注意不能固定得太死,否则底盘形变会直接传导到传感器上。我们后来在模块下面垫了一层1mm厚度的泡棉胶,相当于做了一个简易减震,数据干净了很多。

灰度传感器我们用的是四路数字量输出的模块,比模拟量版本好调很多。安装在车头前方约3cm处,四个探头一字排开,间距大概1.5cm,这样正好覆盖赛道黑线的宽度。数字量输出直接接GPIO,读到高电平表示压到黑线,低电平表示在白底上。这样在程序里只需要组合判断四个引脚的0/1状态,就能识别直道、左转、右转、十字路口、环岛入口等场景。你可能会问,为什么不用模拟量?因为数字量在比赛时抗环境光干扰更好,现场调试快,不需要每个探头单独调阈值。

编码器接线要特别注意:霍尔编码器输出是开漏信号,需要上拉电阻。MSPM0的GPIO内部有上拉,但如果引线过长,还是建议在编码器模块上加一个4.7kΩ的外部上拉。我们第一次测速时发现脉冲经常丢,后来用示波器看波形才确认是上拉电阻没加,电平斜率太缓导致计数丢失。

2.4 电源分配:一个容易翻车的细节

电源是电赛小车最容易被忽视的坑,甚至比算法更容易翻车。我们用的是一块7.4V、1800mAh的2S锂电池,然后做了两级供电:

  • 第一级:电池电压直接给TB6612的VM引脚,给电机供电。电机瞬间启动时电流能到2A以上,如果共用稳压源,会造成系统电压跌落。
  • 第二级:电池电压经过AMS1117-5.0稳压到5V,再经AMS1117-3.3稳压到3.3V,给MCU、MPU6050、灰度模块和OLED供电。

这里有个非常致命的问题:两个AMS1117串联时,如果5V和3.3V的负载同时较大,3.3V端会因为输入压差不足而掉出稳压范围。我们调试中遇到过好几次MSPM0突然重启,后来排查到就是电池电压在中途降到5.5V以下,AMS1117-5.0输出只有4.0V,3.3V就更不稳了。解决办法是:把MPU6050和OLED等小电流器件直接接3.3V,灰度模块接5V,并且把5V的负载尽量减小。如果条件允许,直接换成降压电路效率高的DC-DC模块,从根源上解决发热和压差问题。

还有一个细节:信号线和电源线要尽量分开走。电机线和大电流线不要和I2C线、编码器信号线捆在一起,否则电机换向时的电感脉冲会耦合进信号线,导致MPU6050读数异常。我们在原型阶段吃过亏,后期重新排线后问题才消失。

3. 融合控制的核心原理与软件实现

3.1 陀螺仪原始数据怎么读才不坑

MPU6050通过I2C接口与MSPM0通信,默认I2C地址是0x68(AD0引脚接地)。读数据的核心流程是:初始化I2C、唤醒芯片、设置陀螺仪量程和加速度计量程、配置数字低通滤波器,然后循环读取六个轴的原始数据。

我们的量程设置为:陀螺仪±2000°/s,加速度计±2g。为什么选这么大的量程?因为小车转弯时角速度可能瞬间超过500°/s,如果量程设成250°/s,数据会直接溢出,出来的角度就全乱了。加速度计量程设小一点,是为了提高精度,因为小车在平面上跑,重力加速度在垂直方向上的分量变化不大,±2g足够。

这里重点说“数字低通滤波器”,也就是MPU6050里面的DLPF配置。这个寄存器可以直接过滤掉高频噪声,但会引入时间延迟。我们配置在20Hz带宽,效果是数据明显平滑,同时转弯响应延迟还能接受。如果你发现角度延迟太明显、小车总感觉“慢半拍”,可以考虑把DLPF调到42Hz,牺牲一点平滑度换实时性。

读到的原始数据是16位有符号整数,要转换成实际物理值需要除以灵敏度。比如陀螺仪量程±2000°/s时,LSB灵敏度是16.4,也就是说原始值除以16.4才是角速度(°/s)。这个换算关系一定要记牢,后面互补滤波和PID调参都要用。

最终我建议用一个定时器,以1ms为周期去读数据。千万不要用阻塞延时去读,否则整个控制循环会被拖死。MSPM0的定时器中断完全够用,1ms触发一次,在中断里拉取数据、更新姿态,主循环只负责状态机和PID输出,这样结构清爽很多。

3.2 姿态角度融合:互补滤波为什么够用

一提姿态解算,很多人马上想到卡尔曼滤波、四元数、欧拉角,听起来高大上。但对电赛小车来说,我只推荐互补滤波。原因很实在:卡尔曼滤波在MSPM0这种Cortex-M0+上也可以跑,但计算量相对较大,而且调协方差矩阵的过程非常痛苦,现场改参数根本来不及。互补滤波的计算量极小,效果已经足够,而且好调,直观。

互补滤波的核心思路是:陀螺仪积分得到角度,短时间准确但会漂移;加速度计直接算角度,长期准确但高频噪声大。那就把它们互补起来:高频段信任陀螺仪,低频段信任加速度计。标准实现如下:

#define alpha 0.98f angle = alpha * (angle + gyro_Y * dt) + (1.0f - alpha) * acc_angle;

其中gyro_Y是Y轴角速度,dt是积分时间(单位秒),acc_angle是加速度计算出的倾角。alpha一般取0.95到0.99之间,越大越信任陀螺仪、角度越平滑但跟随越慢,越小越信任加速度计、响应快但噪声大。我们最终取0.98,这是经过现场绕桩测试的出的结果。

加速度计算角度的公式也不复杂,在水平面运动的小车,横滚角或者偏航角可以基于垂直方向的重力分量去算。如果你采用MPU6050的DMP库,可以直接得到四元数和欧拉角,输出yaw角度来用。我们为了减少代码量,第一版用的是DMP,但DMP库在MSPM0上移植需要一些工作量,而且我发现DMP解算的yaw在长时间运行后同样会有漂移,需要额外的校准逻辑。第二版改成自己写互补滤波,依赖更小、代码更透明,出问题了也更好查。

3.3 从PID单环到串级控制:转向环和速度环的分工

我们的控制结构并不是简单的“看到偏了就打死方向”,而是采用了“速度环内环 + 转向环外环”的分工。

速度环:目标速度由状态机给定,比如直线1.2m/s、入环0.5m/s、出环加速1.0m/s。编码器读到的实际速度作为反馈,通过增量式PID计算输出PWM差值,保持车速稳定。

转向环:输入是“目标方向”与“当前方向”的偏差。目标方向来自赛道元素判断:直道为0°,弯道可能是90°,环岛则是一段连续变化的弧线角度。当前方向来自互补滤波后的角度值。转向环PID计算得到一个转向修正量,叠加到左右轮的速度差上。

用公式描述就是:

left_pwm = base_pwm + steering_pid_output; right_pwm = base_pwm - steering_pid_output;

其中base_pwm由速度环给出,steering_pid_output由转向环给出。这样实现的好处是:即便左右轮的机械特性不完全一致,速度环也能自动补偿;而转向环独立于速度,调参的时候互不干扰。前期我们曾试图用一个双输入单输出的模糊控制器,效果虽好但调试时间不够,最后还是选择了简洁可靠的PID。比赛嘛,完成比完美重要。

3.4 关键代码思路和调参流程

这里我放一段简化后的控制代码框架,大家感受一下整体流程:

// 1ms中断里: void TIMER_IRQHandler(void) { mpu6050_read_raw(&gyro_raw, &acc_raw); // 读原始数据 gyro_deg = gyro_raw_y / 16.4f; // 转成°/s acc_angle = atan2f(acc_raw_x, acc_raw_z) * 57.3f; // 转成度 angle = 0.98f * (angle + gyro_deg * 0.001f) + 0.02f * acc_angle; // 融合 encoder_left = TIMER_READ(ENC_LEFT); // 读编码器 encoder_right = TIMER_READ(ENC_RIGHT); run_control_loop(); // 控制运算 }

调参流程我强烈建议按下面这个顺序来:

  1. 先把转向环PID的三个系数全部设为0,只给固定的base_pwm,让小车跑直线。这时候如果跑偏,用肉眼观察是左偏还是右偏,先调机械和左右轮PWM的平衡比例。
  2. 调速度环。给定一个目标速度,给小车一个很直的现场环境,看速度波形是否收敛、有没有抖动。速度环Kp先大后小,Ki用来消除静差,Kd一般可以不用或者很小。
  3. 最后调转向环。从Kp开始,慢慢加,直到小车在弯道里能稳住;再调Kd抑制超调;Ki可以给一个小值用来消除环岛出口的角度偏差。

有一个重要的心得:MPU6050的零偏校准一定要上电后做,而且是“静止校准”,在起始区域静止2~3秒,采集角速度的均值作为零偏,然后在运行时把这个零偏减掉。否则你起步瞬间角度就会以每秒几度的速度往一个方向漂,转弯精度无从谈起。

4. 常见问题与赛场排错实录

4.1 高频问题速查表

我把备赛和比赛现场遇到过的典型问题整理成了一张表,方便大家直接排查。

现象可能原因解决方法
MPU6050 I2C读不到数据接线错误或地址不对检查AD0引脚,确认地址0x68或0x69;用I2C扫描程序测试
角度随时间持续漂移零偏未校准或温度漂移上电静止校准;考虑融合alpha调大;必要时隔几分钟自动校零
小车走直线时左右蛇形转向环Kd过大或过大Kp降低Kp,加入Kd,观察角度波形是否振荡
小车转弯时掉线(冲出赛道)入弯速度过快,转向环响应延迟提前根据灰度状态减速;提高DLPF带宽;加大转向环Kp
编码器计数明显少上拉电阻缺失或信号线过长增加4.7kΩ外部上拉;缩短信号线;确认共地
红绿灯识别不稳定光照变化或传感器安装角度偏更换传感器位置,加遮光罩,程序做防抖处理
MCU随机重启电源瞬间跌落,低压复位独立电机电源;增大电容;改用更低内阻电池
Keil编译找不到芯片头文件MSPM0芯片包没装或版本不对从TI官网下载最新DFP包,手动Import;确认Device选择正确

4.2 用串口把数据“可视化”再调参

PID调参最忌讳“盲调”。我们的做法是:把angle(融合后的角度)、target_angle(目标角度)、pid_output(PID输出)、left_pwm、right_pwm这些变量通过printf每秒输出100行,在电脑上用串口助手记录,再导入Excel或者用简单的数据波形显示工具查看。

比如有一次小车在环岛出口总是走偏,我从串口波形里看到转向PID输出已经饱和到最大值,说明角度的偏差一直很大。问题不是PID参数,而是状态机判断到“出环岛”的时刻晚了三帧,导致小车已经快要撞路肩才开始回正。后来把出环岛的判断条件从“单个灰度探头连续三帧在黑线”改成“连续五帧”,加上一个提前量之后,问题就消失了。如果没有串口波形,这种逻辑问题很难定位。

另外提一个技巧:MPU6050的原始角速度可以在静止时打印出来,观察它的基线噪声。如果噪声峰值大于±3°/s,说明供电或线路有问题,不要急着调PID,先把数据弄干净。我在备赛时一度以为滤波不够,后来发现是I2C线跟电机电源线并行走了一截,重新布局后噪声一下小了很多。

4.3 比赛现场的修改策略

电赛现场的时间非常紧张,能带去的冗余方案都要带去。我们的策略是:

  • 把常用参数全部存放在MSPM0的Flash模拟EEPROM区域,通过按键就能在线修改PID参数,不用每次都重新编译下载。
  • 准备三套参数预设:高速版(追求速度)、稳定版(追求过线率)、雨天地面防滑版(减小加速度和转向力度)。赛前根据场地灯光和地面材质选择。
  • 现场改代码只改一个函数,其他代码冻结。这样可以最大限度避免引入新bug。
  • 最好准备一个备用主控板,万一电源接反烧了板子,能快速换板继续调试。

这里还要提醒一件事:比赛现场通常不允许长时间占道调试,所以白天只能通过观察小车跑的过程来微调,晚上回到备赛教室再用串口复盘。也就是说,你的现场调参手段必须足够高效。按键调参加OLED显示参数,是我觉得最实用的一套现场调试方式。

5. 备赛路线与长期积累建议

如果你是从零开始准备电赛,我不建议一上来就啃算法、啃官方手册。比较靠谱的路线是:先让小车“能动”——做通PWM电机控制和编码器测速;再让小车“能感知”——接好MPU6050和灰度模块,把数据通过串口打印出来,观察数据在直道、弯道、光照变化下是不是合理;最后才进入闭环控制,一步步搭建速度环和转向环。整个过程大概需要两周的课余时间,每天三四个小时。备赛时我们把任务拆成了四个里程碑:

  • 第1~2天:电机驱动、编码器测速。
  • 第3~5天:MPU6050读取、互补滤波输出角度。
  • 第6~9天:速度环闭环、直线稳定行驶。
  • 第10~14天:转向环闭环、赛道元素识别、整体联调。

这套路线最大的价值就是降低挫败感。很多队卡在最开始的环境搭建上,花了三天还没能让电机转起来,后面就彻底乱了。MSPM0的资料在TI官方社区和几家国内电子论坛上都比较全,遇到具体问题直接搜“MSPM0G3507 + 关键词”基本能解决,搜不到就去看SDK里的例程,例程永远是最准确的参考。

比赛最终成绩只是结果,真正让人成长的是“发现问题—定位问题—解决问题”的循环。希望这篇复盘能帮你少踩一些我们踩过的坑。如果你后续在小车调试上遇到具体问题,欢迎随时交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询