2024年电赛H题的智能小车我用MSPM0G3507做主控8路灰度循迹加上MPU6050姿态辅助这套方案从备赛到最后完赛一路跑下来老实说踩了不少坑也总结出一些真正管用的经验。如果你正准备做控制类题目或者正在纠结怎么让小车既跟得住线又不爬不了坡这篇东西应该能帮你省掉好几个通宵。先说结论8路灰度负责平面上的“横向位置”MPU6050负责空间里的“俯仰姿态”两者各管一摊配合起来才能应对直道、弯道、十字路口和坡道混合的赛道。MSPM0G3507作为主控性能、外设、开发环境在电赛场景下都够用性价比也合适。下面我从方案选型、硬件布局、软件算法到调试踩坑一条条拆开讲。1. 赛题拆解与控制方案选型背后的逻辑1.1 2024年H题到底在考什么电赛控制类题目这几年有个很明显的趋势不再单纯考你“能不能让电机转起来”而是考一个完整的闭环系统能不能在复杂环境下稳定工作。2024年H题自动行驶小车核心是让小车沿指定的路径自动行驶完成循迹、路口识别、指定位置停车、坡道通行这些动作。说白了就四件事跑得稳、认得线、停得住、爬得上坡。很多第一次做小车题的同学容易陷入误区觉得只要把灰度传感器数据读出来、PID一调车就能跑完全程。但实际上赛道里只要加一段坡道纯灰度方案就抓瞎了。灰度传感器测的是“地面反射率”它只知道车子和黑线的左右偏移量完全不知道车子现在是平路还是上坡。如果上坡时没提前减速车速会掉得很厉害甚至直接溜坡如果下坡速度过快弯道根本拐不过来。这就是为什么今年 H 题必须加姿态传感器的原因。另外H题真正拉开差距的点是“稳定跑完全程”而不是“某一段跑得飞快”。赛场上只要有一次冲出赛道基本就告别高分了。所以方案设计的第一原则不是堆速度而是把“识别”和“控制”这两个环节做扎实。1.2 为什么选MSPM0G3507做主控先聊主控选型。电赛这些年比较流行用STM32资料多、例程丰富但2024年控制类题目明确规定主控只能用TI的单片机不同年份和赛区要求略有差异但TI平台是常见方向所以MSPM0G3507就成为了非常合适的选择。MSPM0G3507是TI基于Arm Cortex-M0内核推出的新一代MCU主频最高80MHzFlash和SRAM分别是128KB和32KB。在小车这个场景下程序量也就几十KBFlash和RAM都绰绰有余。外设方面它有多个定时器、ADC、SPI、I2C、UART以及一个很关键的硬件MATHAMath Accelerator可以硬件加速三角函数、除法、开方这些运算。这一点在做MPU6050姿态解算、PID计算时非常有用虽然M0内核本身计算能力一般但配合MATHA跑角度融合并不吃力。开发环境上TI提供了SysConfig图形化配置工具可以在界面里勾选外设、配置引脚自动生成初始化代码然后配合Keil或者CCS Theia使用。习惯用Keil的同学也能快速上手只要装好MSPM0的Device Pack就行。对比项MSPM0G3507传统STM32F103内核Cortex-M0 80MHzCortex-M3 72MHz硬件数学加速有MATHA无主要开发工具SysConfig Keil/CCSKeil/CubeMX小车场景够用程度足够且余量大足够电赛H题适配推荐受题目限制我的实际感受是MSPM0G3507在小车控制中的响应速度、外设能力完全能够覆盖需求。相比STM32最大的区别在于你拿不到那么多现成的“拿来主义”代码很多外设初始化、驱动函数得自己根据SDK来写这反而逼着你把底层吃透对比赛是有好处的。1.3 为什么是“8路灰度MPU6050”的组合而不是更少传感器我之前见过不少队伍用4路灰度或者5路灰度也见过有人只用MPU6050做惯性导航结果赛道稍微复杂一点就翻车。原因很简单4路灰度的问题是“信息量不够”。它只能告诉你线大概在左边还是右边但无法精细分辨弧线弯道、直角弯、十字路口的区别。比如车子走到十字路口时4路灰度可能所有探头都压线你根本分不清这是路口还是大弯道控制策略容易乱。8路灰度就不一样。8个探头并行排列几乎覆盖了车头下方的整个横向区域不仅能看到“线在哪”还能通过多个探头的组合判断“这条线是怎么弯的”。在直道上中间几个探头压线在弯道上偏侧的几个探头压线到了十字路口几乎全部探头压线。有了这些细节PID才能提前响应而不是等到车子偏离了才猛打方向。但灰度传感器再强也解决不了“空间姿态”问题。灰度看到的是地面信息当车子进入坡道时地面特征没有变化灰度读数跟平路跑完全一样可这时候车子的受力、速度需求已经变了。MPU6050就是用来补这一块短板的。它通过三轴加速度计和三轴陀螺仪输出姿态信息我们可以计算车体的俯仰角。一旦检测到俯仰角超过阈值系统就知道进入坡道了进而调整基础速度、改变PID参数甚至进行坡道驻车/启动的特殊处理。所以“8路灰度MPU6050”的搭配本质上是“平面位置感知空间姿态感知”的双通道融合各有各的不可替代性。这也是今年H题比较主流、也最稳的解法。2. 硬件设计与传感器布局的实操要点2.1 整体硬件框架与电源分配一个完整的小车系统核心器件大概有这些MSPM0G3507主控板、电机驱动模块、两个带编码器的直流减速电机、8路灰度传感器、MPU6050、电源模块、蜂鸣器和LED指示灯。先聊电源这是最容易翻车的环节。小车用的是7.4V锂电池电压经过降压成5V给灰度传感器和电机驱动逻辑供电再经过3.3V LDO给主控和MPU6050供电。听起来简单但实际接线时一定要注意“电源分配”和“信号隔离”电机电流大启停瞬间会有尖峰如果主控和电机共用一条电源回路单片机非常容易被拉复位。建议电机驱动直接吃电池电压主控板和传感器用独立的降压模块供电但所有电源的地要共地否则传感器信号参考电位不一致读数会乱跳。在电机驱动电源输入端并联一个大容量的电解电容比如470uF再并一个104瓷片电容滤高频能明显减少电机对整车的干扰。主控板我直接用了MSPM0G3507的官方LAUNCHXL开发板来做原型验证等整个系统调通后再把核心板拆下来焊到自制的底板小板上。当然你也可以直接设计一块包含最小系统、电机驱动接口、传感器排针的集成底板这样整车更紧凑散热和走线也更好。电机驱动模块推荐用TB6612FNG或者DRV8833这类集成H桥驱动芯片比L298N功耗低、体积小最大持续电流对普通N20电机来说足够。如果用大扭矩电机还是上双路的BTS7960或者大功率MOS方案更稳但电赛小车一般用不到那么大的电流。2.2 8路灰度传感器布局与阈值调节技巧8路灰度传感器模块在市面有很多成品大多是TCRT5000红外反射传感器的阵列版可以输出模拟量或者数字量。我强烈建议用模拟量输出的版本因为数字量输出的阈值是用电位器调死的一旦现场环境光、地面颜色有变化就失效而模拟量读回来之后可以做软件自动校准适应性好得多。安装位置有讲究。灰度传感器阵列要安装在车头正前方并且离地高度尽量一致。离地太高传感器的光线发散对黑线的分辨率下降离地太低地面稍微不平就会蹭到甚至把传感器撞歪。一般来说离地高度保持在1厘米到1.5厘米之间比较合适。安装时要注意8个探头的排列方向必须与车轴垂直否则横向误差的计算就会偏。再说阈值调节。白底黑线的赛道黑线的反射率低灰度探头读到的电压或者ADC值也与白底明显不同。可以在程序里写一个自动校准函数上电后先让小车停在白底区域读取8个通道的ADC值作为“白色基准”再人工把车推到黑线上读一组“黑色基准”取中间值作为判定阈值。这样比手动拧电位器精准得多也方便现场适应不同的场地。假如传感器模块已经内部集成了比较器也能调出数字量但也要保留模拟量输出。原因很简单模拟量除了可以做二值化判断还能根据“黑线的深浅程度”计算更精细的误差值让PID输入更平滑。这一块下面软件部分会详细说。2.3 MPU6050在车体上的最佳安装位置MPU6050虽然小但装的位置不对后续姿态解算会吃大亏。我的建议是把模块尽量安装在车体的几何中心正上方并且让模块的一个轴比如Y轴严格朝前Z轴垂直向上。为什么要靠近几何中心因为MPU6050里的加速度计测量的是“比力”如果模块离旋转中心比较远小车转弯时会产生额外的向心加速度分量导致加速度计读数不稳定进而影响俯仰角计算。装在中心附近虽然无法完全避免但能把这种误差降到最低。安装方向也要固定。如果模块的X轴朝左、Y轴朝前、Z轴朝上那俯仰角就对应Y轴和Z轴分量如果安装反了姿态角的计算公式全得调整。建议第一次接线后先写个测试程序把三轴加速度原始值打印出来小车平放时应该看到Z轴约等于1gX/Y接近0g反向推动小车时对应轴向有变化确认方向和预期一致再往下做。另外一个小细节MPU6050模块和主控之间的连接线尽量短使用I2C通信时SDA和SCL线不要和电机电源线绑在一起走否则电机转动时I2C非常容易被干扰出现读取失败或者数据跳变。2.4 电机与编码器的选型思路小车的“脚”同样是决定成绩的那一半。最好用的是带霍尔编码器的N20微型减速电机它体积小、功耗低而且自带AB相编码器输出可以测速、做速度闭环。电赛小车速度不需要太快但要扭力足够、能够爬坡。我用的电机减速比大概在1:30左右空载转速大约300多转每分钟配合65mm直径的轮子小车最高速度大约能到1m/s以上应对比赛足够。为什么特别强调“编码器”因为只靠PID开环控制小车在电池电压下降、坡道负载变化时速度会明显波动。有了编码器就能做闭环控制读取单位时间内的脉冲数得到实际速度和期望速度做差再用一个速度PID把误差压回去。这样即便上坡负载增大系统也会自动加大PWM占空比把速度稳住。如果你的电机不带编码器也并不是做不了题目灰度姿态辅助的控制也能够跑完全程但速度控制的精细程度会差不少。预算允许、时间允许的话尽量选择带编码器的版本。3. 软件架构与核心算法的落地方法3.1 主程序状态机与任务调度小车程序不要直接写成一个“从头到尾跑一遍”的流水账而是用状态机来管理这样可以清晰处理“平路、坡道、路口、停车”四种场景的切换。我的框架大概是这样状态一初始化。等待按键触发执行灰度传感器自动校准、MPU6050静止校准、电机使能。状态二循迹行驶。根据灰度误差做PID方向控制同时持续监测MPU6050俯仰角。状态三坡道处理。当俯仰角超过阈值时切换为坡道控制参数适当增大电机输出防止溜车。状态四路口/停车点处理。当灰度全白或者特定探头组合出现时执行减速、停车、蜂鸣器提示。状态五结束。小车到达终点后关闭电机等待重新启动。状态之间通过定时中断来调度。我一般在定时器中断里执行“采集灰度MPU6050、计算误差、执行PID、更新PWM”这整套控制流程中断周期设为10毫秒也就是控制频率100Hz。主循环只负责按键检测、状态切换、OLED或者串口日志输出。这样控制周期稳定不会被打印和延时卡顿影响。3.2 灰度传感器数据处理如何把8个点变成一个误差值很多人把灰度简单理解成“压线/没压线”的数字量实际上8路灰度真正好用的方式是“连续误差计算”。我给每个探头设定一个位置权重黑线越靠左误差越负越靠右误差越正用加权平均的方式算出当前车体和黑线的相对偏移量。这里的关键是不能只统计压线的探头还要考虑“压线程度”// 灰度误差计算简化版 float line_error 0.0f; float total_weight 0.0f; int pos_map[8] {-4, -3, -2, -1, 1, 2, 3, 4}; for (int i 0; i 8; i) { // gray[i] 是第 i 路灰度 ADC 值数值越小代表越接近黑线 if (gray[i] threshold[i]) { float weight threshold[i] - gray[i]; line_error pos_map[i] * weight; total_weight weight; } } if (total_weight 0.001f) { line_error / total_weight; } else { // 全部丢线需要特殊处理 line_error last_line_error 0 ? 6.0f : -6.0f; }当误差连续变化时PID的输出也会平滑变化小车走线会很线性和顺滑而不是左右猛摆。丢线处理是重点当8路全部是白底时说明车冲出了赛道或者正处于特殊区域。这时可以保持上一次的误差并且给一个较大的方向修正值让车自己转回来。但这里一定要加保护如果丢线持续超过几百毫秒说明确实跑飞了应该直接停车防止满油门乱撞。十字路口的判定也不难主要是看是不是“几乎全部探头都压线”。如果8路中有6路以上都检测到黑线并且持续超过2到3个控制周期就认为小车进入了十字路口这时可以保持直行不做过多的转向干预。3.3 MPU6050姿态解算不要一上来就调DMP很多同学拿到MPU6050第一反应就是移植DMP库直接用官方固件算四元数、欧拉角。这个思路在STM32上确实成熟但在MSPM0G3507上DMP库的移植并不像想象中那么顺利库文件版本、I2C时序、内存需求都可能出问题。我调了两天后果断放弃改成自写互补滤波效果也不差。互补滤波的思路很朴素加速度计长期稳定但短期噪声大陀螺仪短期精确但长期会漂移。那好把两者融合用陀螺仪的角速度来做短期姿态更新再逐步用加速度计算出的角度去“拉”回来防止陀螺仪积分漂移。公式大致是// 数据读取简化 float dt 0.01f; // 100Hz float gyro_y read_gyro_y(); // 单位 °/s float accel_pitch atan2(accel_y, accel_z) * 57.3f; // 俯仰角 // 互补滤波 float angle_pitch 0.95f * (angle_pitch gyro_y * dt) 0.05f * accel_pitch;这段代码里0.95和0.05的系数说明陀螺仪占主导加速度计慢慢修正漂移。系数不是固定的如果噪声大可以加大加速度计权重如果觉得响应太慢可以减小。实际调试时我常在倾斜角度变化时观察angle_pitch的跟随速度把系数调到“跟得上、又不抖”的程度。这里特别要提一个容易踩的坑坡道判断不能只用某一个时刻的俯仰角而要做平滑滤波或者连续几个周期都超阈值才算。因为小车起步、加速时车体的惯性会让加速度计出现短暂的“假俯仰角”如果只判断一次很容易在平地误触发坡道模式。我一般要求连续10到20个控制周期俯仰角都超过15度才判定为坡道。光靠加速度计的静态角度来判断坡度其实是够用的因为比赛坡道的坡度是固定的不像翻车那样需要快速响应。真正需要陀螺仪的是“瞬时变化”的场景比如从平路进入坡道的瞬间角度跳变并不像想象中那样剧烈加速度计的低通特性会拖后腿这时陀螺仪的短时积分能提前感知趋势。互补滤波结合的正是这个优点。3.4 PID控制策略直道、弯道、坡道怎么调方向控制我用了标准的位置式PID输入是灰度计算出的line_error输出是左右电机的差速补偿。但这里有个经验不要从头到尾用一套PID参数。直道上误差变化平缓可以只用P控制P值小一点车走得更稳弯道上误差跳变很大如果P值太小车子来不及转需要在检测到弯道时自动切换成“大P适度D”的参数组。做到这一点不复杂根据误差绝对值大小判断当|line_error|超过某个阈值就认为进入弯道切换为弯道PID参数出弯后恢复直道参数。基础速度的设定也跟赛道元素有关。我通常这样分配直道速度可以放到60%-70%的占空比对应速度进入弯道前通过误差变化率提前预判降速到40%-50%坡道时根据俯仰角大小动态增加基础PWM抵消重力沿坡道的分力下坡时反过来减小基础PWM防止越冲越快。如果想要更好的速度稳定性再加上编码器测速闭环。速度环的PID和方向环PID是串级关系外层方向环输出的是“期望速度差”内层速度环分别控制左右轮转速。实现上不用写特别复杂只要把左右轮期望速度设置成“基础速度±方向修正”再各自用PID去追实际速度就行。4. 实车调试中的常见问题与排查技巧4.1 上电就复位或者跑着跑着重启这个问题90%出在电源上。电机启动瞬间电流很大电池电压会被瞬间拉低如果主控的稳压器输入低于最低工作电压MCU就复位了。解决办法有这么几个电机驱动模块的电源不要经过主控板的降压电路直接接电池。在电池输出端并联一个大容量电解电容470uF以上吸收瞬态压降。给主控板加一个低功耗的复位监视芯片或者延迟上电。起跑时不要直接满占空比启动软件里做软启动让PWM占空比在几百毫秒内从0逐步升到目标值。还有一个容易忽略的编码器那条线的排线偶尔会和灰度传感器线束缠在一起电机转动时线上的感应电动势会干扰灰度ADC值导致系统误判。把线束分开、必要时给编码器信号线加下拉电阻能好很多。4.2 灰度传感器在阳光下、灯光下的干扰电赛现场灯光情况复杂有的地方亮有的地方暗灰度传感器如果只靠固定阈值很容易失灵。我的处理方式是这样首先把模块的模拟量接到ADC不依赖模块上的电位器。 然后在程序初始化时做一个“动态捕捉”让小车在起始位置停留两秒这两秒里不断刷新白色基准值取平均值作为当前光照下的基准。跑动过程中如果发现某一路读数不断变化还可以动态更新阈值但更新速度要慢防止把黑线当成基准。实在对光特别敏感的环境可以在灰度传感器阵列上方加一块遮光海绵或者黑色塑料片只留出朝下的检测窗口。这个小改动能把环境光的干扰降掉一大半。4.3 MPU6050数据漂移和坡道误判MPU6050静止放置时角度很稳但运行一段时间后角度可能会慢慢飘这是陀螺仪零漂造成的。解决办法是上电静止校准小车放在水平地面上电后采集1000次陀螺仪输出取平均作为零偏存起来之后每次读取时先减去这个零偏再积分。另外芯片需要一个比较长的稳定时间刚上电就校准效果不好建议等待500ms到1s再校准。坡道误判之前的软件部分也提了核心就是“加阈值延迟”连续N个控制周期俯仰角超过阈值才确认坡道。确认后把角度锁存为“坡道基准角”之后的控制都以这个角度作为偏差计算负荷而不是直接用绝对角度值。出坡后也要连续N个周期俯仰角回落阈值以内才退出坡道模式。4.4 编译链接报错undefined symbol MPU6050这个报错在热搜词里反复出现说明很多人卡在这里。报错原文一般是“.\objects\project.axf: Error: L6218E: Undefined symbol mpu6050 (referred from main.o)”意思是在main.c里调用了和mpu6050相关的函数但链接器在整个工程里找不到函数实现。排查方法按顺序检查看看工程树里的Source Group有没有MPU6050.c文件。如果只有头文件源文件没加进去链接器当然找不到函数实现。打开Project对话框确认MPU6050.c是否打上了编译勾选。检查头文件中的函数声明和源文件中的函数定义函数名大小写是否完全一致。C语言区分大小写尤其注意像“MPU6050_Init”和“mpu6050_init”这种差异。检查Include路径是否添加到了工程里否则编译阶段就会报找不到头文件而不是链接报错。如果还是找不到看生成的.map文件搜索“mpu6050”相关符号是否存在能帮你判断是没编译这个文件还是函数命名不一致。这个报错本质不复杂但很耗费新手时间。我的习惯是外设驱动代码单独建一个“Hardware”分组一个.c配一个.h命名统一文件放好之后就先点击编译验证一次而不是把所有代码堆在一起再排查。4.5 PID参数整定心得PID参数调起来很磨人但有一个相对实用的步骤第一步把I和D先设为0只留P。给一个很小的P推车看走线如果车左右摆、来回震荡说明P偏大如果车压线后回正很慢说明P偏小。逐步调整到“有一点轻微回正动作但不震荡”的状态。第二步加入D项抑制过冲。弯道上如果车转向“打得太猛”D可以起刹车作用。D从0开始慢慢加加到过弯顺滑、直道不抖就停。第三步我基本不用I项。 方向控制里I容易累积误差导致小车持续朝一个方向偏。除非是速度闭环需要消除稳态误差否则方向环不建议开I。最后分享一个调试习惯不要光靠肉眼判断尽量把误差值、PID输出、灰度状态通过串口或者无线模块回传到上位机画成曲线看。这样你能清楚地看到车是在弯道边界才转向还是提前很早就开始修正了。这个方法能帮你节省大量的调参时间。总的来说这套“MSPM0G3507 8路灰度 MPU6050”的方案是我跑完2024电赛H题之后最想推荐给后来人的组合。硬件成本不高、逻辑清晰、抗干扰能力强也足够应付赛场上的大多数复杂元素。如果你正打算做类似题目希望这篇经验帖能让你少走一点弯路——尤其是PID参数整定和传感器安装这两块尽量提前多花点时间赛场上最关键的反而是那些看起来最不起眼的细节。