21届智能车竞赛结束后的第三天,我在出租屋把最后一块PCB的立创EDA工程文件拖进仓库。soberup战队的“疯狂电路组”从这天起不再是一个队内的小班底,而是一个面向所有参赛者的开源目录——里面有电路图、PCB、单片机代码、调参记录,还有我们这一年踩过的几乎所有坑。说句实话,组队那会儿我们根本没想过“开源”这两个字,满脑子都是怎么让车在赛道上少冲出一次护栏。真正让人改变想法的,是比赛结束前那一周,隔壁兄弟院校的学弟把我们围在调试区,拿着手机对着我们的车拍个不停,问得最多的一句话是:“能不能把你们的电路和代码发给我们看看?”那是21届智能车赛场上最打动我的瞬间。
这篇帖子就是那个开源目录的使用说明,也是我们整个赛季的完整复盘。从硬件电路设计、PCB布局,到软件上的串级PID、角速度内环、赛道元素状态机,再到机械装配和现场调试,我都按目录里的顺序讲一遍。无论你是即将参加下一届比赛的新队伍,还是单纯对智能车、嵌入式控制感兴趣的初学者,都可以拿这份目录当起点。我不敢说里面的方案最优,但每一行代码、每一处布线后面都有原因。
1. 为什么叫“疯狂电路组”:21届智能车的出题逻辑与我们组的组队思路
1.1 这届比赛到底比什么:被时间压缩的硬件设计周期
先说个背景。第二十一届全国大学生智能车竞赛的赛道元素相比往年又堆了不少新花样,环岛、坡道、十字这些“老朋友”还在,但规则细则里那几处改动,让所有队伍连夜改了方案。更麻烦的是正式规则公布到校内选拔赛之间留的时间非常紧,不少队伍连基础三轮车的底板都还没调稳,就要开始考虑新元素带来的是传感器布局问题还是软件标志位问题。
很多人把智能车竞赛理解成“写代码比赛”,其实不对。整辆车的性能上限在硬件上就被焊死了——电源纹波大,摄像头画面就会抖;电机驱动散热不够,跑两圈就热保护;电感放大电路噪声压不住,差比和就永远在跳。这就是为什么我们组内部非要把自己叫“疯狂电路组”。我们没有官方组别那种“电路组”的编制,只是队内对硬件方向修行者的统称,核心工作就是电力、驱动、传感器、主控板四件事,软件组需要什么接口我们就给什么接口,机械组需要什么安装孔位我们就提前在PCB上画好。
基于这个现实,21届的备赛逻辑其实很清晰:谁先把硬件系统稳定下来,谁就有更多时间跑算法。我们队测试过,硬件定型早的队伍,光线性CCD和编码器数据融合就能多调两周,而晚的队伍一直在被奇怪的低频抖动折磨。开源目录里所有电路,都是围绕“压缩硬件修改周期”这个目标设计的。
1.2 从三个人到一个系统:Team soberup的内部协作
先说我们的队伍构成。soberup战队不是那种几十人的大联盟,核心成员就三个人,一个管机械、一个管算法、一个是我,主要负责电路。三个人听起来少,但配合好了效率很高。机械同学负责底盘、轮距、舵机拉杆;算法同学负责摄像头图像处理和赛道元素识别;我则守着主控板、电机驱动、电源模块和传感器信号调理。
这样的分工决定了我们不会走“买现成整板”路线。市面上的智能车主板很成熟,但模块化的板子永远存在接口冗余和引脚浪费的问题,而且出了问题你只能对着厂家文档猜。我们决定从零画板,每块板子的功能单一、接口明确、测试点预留充分。说白了,自己画板子最大的好处不是性能,而是“这板子出了问题,你能第一时间判断是哪一段”。这在比赛现场是能救命的。
为了协作顺畅,我们立了个规矩:任何硬件改动必须同步更新三份文档——原理图、PCB注释、调参手册。刚开始觉得麻烦,到后期发现这其实是整个赛季效率最高的投资。开源目录里的硬件文件夹,就是按这个规范整理出来的。
2. 开源目录的骨架:仓库结构、版本管理与人情味文档
2.1 仓库目录总览与阅读顺序
我先把开源目录的结构完整展示出来,你拿到手之后至少不会迷路。
soberup-21st-circuit/ ├── README.md ├── docs/ │ ├── 01_规则解读与整车参数.md │ ├── 02_硬件设计说明.md │ ├── 03_软件架构说明.md │ ├── 04_调参手册.md │ ├── 05_赛道元素处理记录.md │ └── 06_赛前检查清单.md ├── hardware/ │ ├── PowerModule/ # 电源板:7.2V转5V/3.3V,含电池电压检测 │ ├── MotorDriver/ # 电机驱动板:DRV8701+H桥MOS │ ├── SensorBoard/ # 传感器板:电磁电感放大与检波电路 │ ├── CameraBoard/ # 摄像头接口板:线性CCD/总钻风转接 │ └── MainBoard/ # 主控板最小系统与引脚分配 └── software/ ├── rt1064_ctrl/ # 基于NXP RT1064的控制代码 ├── sensor_proc/ # 传感器数据调理与滤波 ├── pid_lib/ # 串级PID与角速度内环 └── tools/ # 上位机调参脚本与串口解析工具我的建议阅读顺序是:先看 README,然后直接跳到 docs/04_调参手册.md。因为调参手册里写了每辆车都能用的参数边界,比如转向死区、舵机PWM频率、PID初始值。参数这玩意儿单独看一个数字没意义,但如果你知道我们的机械结构和传感器安装位置,再对照自己的车去调,就非常有参考价值。看完调参手册再回头翻硬件原理图,你会理解很多设计选择——比如为什么舵机供电要单独从电源板引一条线,为什么电感放大电路的增益电阻选10K而不是4.7K。
2.2 版本管理的教训:我们曾经用“最终版v12”命名PCB
这里多讲一点版本管理,因为年轻队伍最缺的就是这个。很多队伍画PCB喜欢用“最终版”“最终版v2”“真最终版”这种文件名,我们早期也犯过这个毛病。赛季第三个月,我改了一版电源板的反馈电阻,文件名叫“电源板_最终版_v3”,结果两天后发现有位段覆铜间距要调整,老文件早被覆盖了,只能从头改。
痛定思痛,我们后来定了几条硬性规定:PCB工程名用“日期+板卡名+版本号”的格式,比如20220416_PowerModule_V2_1;每版修改必须写一个CHANGELOG,哪怕只改了一个电容封装,也要记录为什么改;所有生成的生产文件(Gerber、BOM)和设计源文件放同一目录,文件名完全对应。这个习惯延续到软件代码,git分支命名也统一成feature/xx和fix/xx。到比赛前两周,我们要回退某个旧版电路时,只需翻一遍日期目录就能找到,完全不用猜。
版本管理还有一个容易忽略的维度:元器件替代料。比赛期间经常遇到“原本选型的MOS管买不到货”的情况。我们在硬件文件夹里放了一个alternatives.csv表格,记录每个关键元器件的替代型号和参数差异,比如耐压值、导通电阻、封装兼容性。比赛前夜,隔壁队来借R100采样电阻,我们直接看这个表格告诉他哪个料位可以换,省去大半天的临时选型时间。
3. 硬件侧的核心矛盾:把每一毫安都算清楚的供电与驱动
3.1 电源树的拆分:从7.2V动力电池到3.3V逻辑电
智能车电池最常见的规格是7.2V镍氢电池或7.4V锂电池包。很多入门队伍直接用一个LM2596模块降到5V,再接一个AMS1117-3.3给单片机,简单是简单,但一上赛道就出幺蛾子——摄像头画面出现水波纹,电磁信号叠加了几十毫伏的噪声,舵机打死时单片机复位。
问题本质在于没有一个清晰的电源树设计。我们的开源仓库里,电源板PowerModule采用“三级架构”:
第一级是电池电压直接进电机驱动功率地,这一路不经过任何降压芯片,电流能力由MOS管和电池本身决定,避免动力大电流与逻辑电路抢电压。 第二级用一颗DC-DC降压芯片(我们选的TPS563201)把7.2V降到5V,给舵机、摄像头、编码器这些对电压纹波不敏感的负载供电。DC-DC效率高,发热小,不会像线性稳压器一样把2.2V压差白扔成热量。 第三级是5V进一颗低噪声LDO(RT9013或类似品)降到3.3V,专门给MCU、运放、传感器基准供电,纹波可以做到10mV以内。
这三级划分对应的就是工程上常说的功率地、模拟地、数字地分区。地线的处理比很多人想得更讲究:我们不能把三套地在PCB上随便连成一个网。具体做法是功率地单独铺铜,在电池接口附近单点接入系统地;模拟地和数字地则通过一颗0欧电阻或磁珠单点连接。这样做的原因是防止电机换向瞬间的大电流在地平面上形成电压梯度,把噪声耦合进传感器采样。开源目录的PowerModule工程里,这几个地平面分区都有丝印标注,你打开PCB图就能看到。
还要提一句电池电压检测。我们在电源板上用两个精密电阻对电池电压分压,进MCU的ADC引脚,同时在ADC引脚前加一颗RC低通滤波,时间常数大约1ms。这个值不是随便拍的,它是根据电池负载变化周期算出来的——电机堵转时的电压跌落很快,但滤波太狠又会掩盖真实电量的突然掉电,所以取1ms折中。调参手册里写了完整的电阻分压计算过程。
3.2 电机驱动与“发热”这个隐形杀手
电机驱动电路是很多队伍容易“能跑但跑不稳”的重灾区。我们用过一体化驱动芯片BTN7970,也用过分离方案,最终稳定下来的是DRV8701栅极驱动芯片加两颗半桥MOS的方案。这样做的好处是可以通过更换不同规格的MOS管来适配不同功率的电机,选型灵活,而且DRV8701的内部电荷泵能保证上管充分导通,不像某些驱动方案会在电池电压下降时出现上管压降过大、电机无力的问题。
驱动板上有几个细节,是我最想在开源文档里强调的:第一,栅极驱动电阻不能省。MOS管的栅极是一个电容,直接接芯片输出会让开关瞬间电流过大,产生振铃。我们实测10欧栅极电阻在1A驱动电流下能把Vgs振铃从2V压到0.4V,代价只是纳安级的静态功耗。第二,续流二极管一定要选快恢复或者肖特基,普通1N4007这种慢管在电机刹车瞬间会吞掉大量能量,管子直接烫手。第三,大电流路径必须铺铜且开窗加锡,PCB上别只走一根细线就当功率线,我们第一版就是这里偷懒,跑三圈后过孔发黑。
发热问题的根源在于MOS管的导通损耗和开关损耗。选型时重点关注两个参数:导通内阻Rds(on)和栅极电荷Qg。Rds(on)越小,持续电流时的发热越低;Qg越小,开关切换时损耗越低。开源目录的MotorDriver文件夹里有一张选型对比表,列出了我们自己测试过的六款MOS管在10kHz PWM下的小核温度,供参考。需要提醒的是,MOS管的散热焊盘一定要按手册画足,并且打过孔到背面的辅助散热铜区,否则静态参数再好看,实际装车还是会热保护。
3.3 传感器调理电路:电磁与摄像头的信号链
我们同时做了电磁和摄像头两套传感器方案,最终比赛主力是电磁。原因是电磁信号链完全掌握在自己手里,调试起来更可控,不像摄像头会受到光照、反光、阴影的影响那么大。电磁传感器感知的是赛道中心导线产生的交变磁场,信号链一般是:工字电感谐振选频 → 运放放大 → 峰峰值检波 → ADC采集。
在SensorBoard里,我们选择了10mH工字电感配6.8nF电容,谐振频率约60kHz左右,正好对应赛道电源的20kHz或60kHz(不同赛区可能不同,一定要先用示波器确认)。放大电路用四路运放OPA4377做同相放大,每一路的增益通过反馈电阻独立可调。这里有个经验:增益别一次性怼满,先用示波器观察电感原始信号幅度,再按“放大后峰值不超过ADC参考电压的80%”来算增益倍数。我们在调参手册里写了一个具体算例:原始信号120mV,目标ADC满量程3.3V,留20%余量即2.64V,则增益倍数22倍,计算得反馈电阻与输入电阻比值21。
检波电路用的是经典的二极管峰值检波,二极管选锗管或肖特基,因为硅管0.7V的压降会吃掉小信号;检波电容的取值要匹配信号频率,太大会响应迟钝,太小则纹波大。这些电路我全部给了仿真文件和实测波形截图,放在SensorBoard的sim/目录下,有Multisim和立创EDA两种格式。你下载下来之后,可以直接改元件参数看结果,比自己拿焊枪盲试快得多。
至于摄像头方案,仓库里也放了一套线性CCD的转接板和通信代码。我没有把摄像头方案写得那么细,是因为它在我们的系统中只是备选,但接口、引脚定义、时序代码都完整,你想在此基础上改成“总钻风”数字摄像头,可以在CameraBoard的引脚映射表上直接替换。
4. 软件侧的算法闭环:PID、角速度内环和赛道元素的协同
4.1 从“方向环输出角速度”说起:串级PID的环路设计
开源目录里最常被问的是pid_lib文件夹里那段核心代码,尤其是为什么方向环的输出是角速度而不是直接给舵机PWM。这个问题值得好好讲。
普通单环PID的思路是:摄像头或电感给出道路偏差→PID算出舵机角度→舵机打过去。听起来没问题,但实际效果是车走起来发飘,尤其在进入环岛时,因为道路偏差本身变化很快,单环PID对偏差的导数非常敏感,一个噪声点就可能让舵机抖动。
我们采用串级PID,外层是方向环,输入是道路偏差,输出是期望角速度;内层是角速度环,输入是期望角速度与实测角速度的差,输出才是舵机PWM。角速度实测值可以由陀螺仪或编码器差分得到,我们选择用陀螺仪(IMU的Z轴角速度),因为它不受车轮打滑影响。这样设计的好处是:外环只管“怎么把偏差拉正”,内环负责“执行时别太冲动”,相当于给方向控制加了一个阻尼器。车身的真实动态响应更平滑,路径跟踪的过冲明显减少。
代码结构大致是:
float calc_direction_pid(float error) { // 方向环PD:P矫正偏差,D抑制振荡 float der = error - last_error_direction; float target_omega = Kp_dir * error + Kd_dir * der; last_error_direction = error; // 限幅,防止期望角速度超出物理能力 if (target_omega > OMEGA_MAX) target_omega = OMEGA_MAX; if (target_omega < -OMEGA_MAX) target_omega = -OMEGA_MAX; return target_omega; } float calc_steering_pid(float target_omega) { // 内环:角速度反馈闭环,输出舵机PWM float omega_actual = imu_read_z(); float omega_error = target_omega - omega_actual; static float integ = 0; integ += omega_error * DT_CTRL; integ = constrain(integ, -INTEG_LIMIT, INTEG_LIMIT); float pwm = Kp_omega * omega_error + Ki_omega * integ; return constrain(pwm, SERVO_MIN, SERVO_MAX); }内环的积分项我用得比较克制,只在直线行驶段、偏差较小的时候起作用,防止环岛中积分累积造成出环瞬间的拖拽感。具体怎么处理积分分离,我写在了pid_lib/README.md里,这里就不展开公式了。
实测效果:单环PID跑直道频繁修正,车速2.5m/s时车身横向摆动约12cm;改成串级PID后,同样速度横向摆动降到3cm以内,进环岛的最大侧倾角度也小了近一半。所以,当你觉得车“转向不够顺”,先别急着加积分,试试多做一个角速度内环,很多时候一条代码就能解决。
4.2 环岛、坡道与十字:有限状态机的处理思路
赛道元素处理是智能车软件最大的坑,也是最容易“鬼打墙”的地方。我们用有限状态机统一管理,而不是在循环里堆一堆if判断。状态机的好处是,你能明确知道车当前处于哪个阶段,每个阶段该看哪个传感器,以及异常情况下该如何回退。
以环岛为例,我们定义了这几个状态:STRAIGHT(直线)、DETECT_ISLAND(检测进入口)、IN_ISLAND(弧线内行驶)、EXIT_ISLAND(检测出口)、RESTORE(出环恢复直线)。每个状态的切换条件都写在docs/05_赛道元素处理记录.md里,并且对应了特征值的门槛。
进入环岛的判断,我们是用电磁差比和的突变:正常直线行驶时左右电感差比和在一个窄区间内波动,一旦进入环岛入口,一侧电感信号会明显增强,差比和超过设定阈值连续若干毫秒,就触发DETECT_ISLAND。这里有一个容易忽略的点:触发不能看一帧信号,要用“连续N帧超过阈值”做防抖,否则一个噪声尖峰就会让车误判。N的取值取决于控制频率,RT1064跑200Hz控制时,我们取8帧,也就是40ms的连续确认窗口。
坡道处理则更依赖速度控制。我们会在坡道前通过图像或电感特征判断出前方坡度,提前把速度从3m/s降到2.2m/s,同时方向环增益临时加大,因为坡道上轮胎垂直载荷变化,同样的P值打出来的转向角会更小。这个“临时变增益”的思路在代码里是单独一个set_dynamic_gain()函数,状态机进入坡道时调用一次,出坡后恢复。
强调一点:状态机里一定要设计一个“超时看门狗”。比如进入IN_ISLAND状态后500ms还没有检测到出口,就强制回到STRAIGHT状态。我们第一版没做这个,结果车在环岛内绕了两圈后直接冲进草地,把前轮拉杆撞弯了。后来加了这个保护逻辑,就算传感器误判,车至少不会疯跑。
4.3 调试工具链:从串口打印到无线调参
软件没有调试工具就是盲人摸象。我们在仓库的software/tools/里放了一套非常轻量的串口调试协议:单片机把关键变量打包成固定帧头发送,上位机用Python脚本解析并实时绘图。这套东西没有用复杂的通讯协议,就是帧头0xA5 + 数据类型 + 数据体 + 校验和,解析脚本也就一百多行,但很好用。
无线调试部分,我们用了一对2.4G透传模块接到主控的UART口。跑赛道时,电脑上能看到实时车速、偏差、角速度期望值、舵机PWM,这样即便车在远处你也能判断控制逻辑是否正常。更重要的是,我们把PID参数放在EEPROM或SD卡里,通过无线指令修改,无须每次拔插下载器。这个功能听起来高大上,实现其实很简单,就是串口中断里判断特定命令字,然后调用参数写入函数。
调参的具体步骤我在手册里写得很细:先调内环角速度环,把车架空,给一个阶跃角速度指令,看响应有没有超调;再调外环方向环,低速跑直线看修正频率;最后把二者接成串级,慢慢提速。很多人一上来就调外环,结果外环参数和实际车速严重不匹配,速度一旦变化就得全部推翻。正确顺序应该是先固定内环,再动外环参数,并且每次只动一个参数、记录波形。
5. 机械与装配:赛车是拧螺丝拧出来的
5.1 重心、轮距与舵机拉杆的三个参数
电路和代码再强,机械上有一个肉眼可见的“歪”,整车所有努力白费。我们的车模用的是基础三轮车,前轮转向、后轮驱动。吃透这套车的机械特性之后,三个参数是我们最重点调的。
第一是重心位置。重心太靠前,转向会过于敏感,直线稳定性差;重心太靠后,后轮附着力增大,加速更稳,但转向响应会钝。最终我们把电池放在底盘中部偏后10mm的位置,并用3D打印支架固定。这个位置是通过一组简单实验得出来的:在直线测试道上分别放三种配重位置,记录相同P值下的横向摆动幅度,选最小的那组。
第二是前轮外倾角。原厂车模的前轮往往有一点外倾,跑起来会吃内侧胎,影响直线寻迹精度。我们用垫片微调前轮轴座,让前轮接近垂直地面,同时保持0.5度左右的微小内倾,目的是增加直线稳定性。这里没有量产车的四轮定位仪,全靠塞尺和一块平板玻璃测,简单但有效。
第三是舵机拉杆的长度和角度。拉杆长度决定了舵机中位是否对应车轮正中,角度决定了转向是否左右对称。我们校准的方法是:给舵机发一个中位PWM,量前轮偏差,再分别打左右最大角,比较两个方向的极限角度是否一致。拉杆球头的螺纹虚位要尽量调到最小,但也不能锁死,否则舵机会憋转。拧拉杆螺母时用螺纹胶,这已经是常识中的常识了。
5.2 一场比赛里最容易松的东西
机械装配的可靠性,直接决定你是去比赛还是去修车。我们赛前有一个固定流程,叫“三查三紧”:查所有螺丝、紧所有接头、查所有线束。比赛现场震动比实验室大得多,以下这些东西是最容易松的:
- 电机座螺丝:跑完一圈回来,先摸电机座温度,再检查螺丝是否松动。电机高频振动最容易让螺丝退扣。
- 舵机摇臂螺丝:一旦松半圈,转向虚位就大到离谱,而且很难在视觉上发现。
- 电池插头:XT60插头如果公母头配合过松,受振动时会有瞬断风险。我们会在插头外侧缠一层电工胶带,或者用扎带固定在底板孔位上,防止拉扯。
- 编码器联轴器:光电编码器与电机轴的固定螺丝必须上螺纹胶,跑高速时松动会导致速度反馈突然跳变,PID瞬间失控。
我们还在开源目录docs/06_赛前检查清单.md里列了一份表格,把每一个检查项、检查方法、合格标准都写清楚了。临场时照着清单打勾,比自己脑子记靠谱得多,尤其是比赛前一晚那种又困又紧张的状态。
6. 踩坑,然后把这些坑写进文档
6.1 上电之前:万用表和示波器才是最好的队友
焊完板子之后,我的手都会先放在电源开关上愣几秒。不是因为激动,而是因为大多数烧板事故都发生在这几秒。我们的规矩是:上电前用万用表量电源输入端对地阻值,确保没有直接短路;再量各关键电源轨的对地阻值,3.3V轨应该有几百欧以上,如果只有个位数,大概率是电解电容装反或芯片焊接短路。
然后上电,不急着接单片机,先空载测量各路电压值,确认在额定范围内。再拿示波器量电源纹波:DC-DC输出纹波应该小于50mV,LDO输出纹波小于20mV。如果纹波超标,先检查输出电容位置是不是离芯片引脚太远,或者反馈电阻的采样点是不是走线太长。这一套流程看起来繁琐,但一次能省下后面好几个小时的查错时间。
还有一个细节:焊接顺序。我的习惯是先焊电源部分的芯片和滤波电容,再焊MCU,最后焊不需要调试的接口件。这样每焊完一个模块就能单独上电测试。千万不要一口气把所有元件全焊完再上电,一旦有问题,排查范围巨大,初学者很容易直接放弃。
6.2 我们最痛的三个Bug
讲三个真实案例,全部在开源目录的docs/02_硬件设计说明.md里留有记录,方便后来者对照。
第一个Bug是电磁信号被电机电流干扰。现象是电机一加速,差比和数值就整体上漂。排查了一整天才发现是地环路问题:电感放大板的模拟地,和电机驱动的功率地共了一段细走线,电机换向电流在这个公共阻抗上产生压降,直接叠加进ADC参考地。解决方法是重新切板,把模拟地单独铺铜,只在电池负极接口处单点汇合。改板之前还试过在ADC引脚加软件滤波,效果只能说治标不治本,地回路不切断,噪声永远都在。
第二个Bug是电池电压检测的电阻封装问题。我们选了0603封装的精密电阻做分压,但电池电压检测点的走线从电源接口跨到板边,跨度太大,压降和温度漂移都不小。后来改成了0805封装、温漂系数50ppm的电阻,并把采样点移到电池接口正极附近,信号质量明显改善。这里要说的是,0603和0805的差别不只是大小,而是功率和温度特性在地端长期负载下体现出来的稳定性差异。
第三个Bug是软件层面的。上电瞬间舵机猛打一边,原因是初始化顺序写错了:程序先使能了外环,再使能陀螺仪内环,导致刚启动时角速度反馈为0,内环误以为需要疯狂输出。修复很简单,把IMU初始化提到PID使能之前,并给舵机输出加一个500ms软启动斜坡。这个Bug让我们在模拟赛道白撞了三次路肩,但我现在回头看,它其实是很好的教学案例——系统上电时序比很多人想象的更重要。
6.3 怎么把“判断失误”变成“经验”
比赛结束后,很多人把代码文件往网盘一扔就结束了。我们多做了一个动作:写AAR(After Action Review)。这不是什么高深管理学,就是四个人围在一起,把赛前赛中赛后所有关键决策列出来,逐个问“我们当时为什么这么选”“如果重来一次会改什么”。每一个结论都会被写回文档,比如“下次进环岛的速度阈值降低0.3m/s”“电源板LDO换成低噪声型号”。
开源目录里的很多注释,就是这些AAR的产物。你会发现pid_lib里的函数注释都很啰嗦,有些甚至写“这里不要用原来的Ki值,原因见AAR”。这样做的价值是:下一届接手的人不会在同样的坑里再摔一次。我相信这就是开源目录和普通代码压缩包最大的区别——它不只是提交结果,还提交了决策过程和失败经验。
7. 给下一届的接力棒:开源目录的使用说明与扩展思路
7.1 拿到这个仓库之后应该先看什么
如果你是因为比赛来的新队员,我建议你拿到仓库后先别急着改代码。花一个晚上把README.md和04_调参手册.md从头看一遍,把里面提到的元器件型号整理到自己的购物清单里,然后对着02_硬件设计说明.md的框图在纸上画一遍电源树和信号流。这个“画一遍”的过程,能帮你建立起整辆车的系统观。
千万不要直接打开MainBoard工程文件就动手改引脚。你首先要确认自己的主控型号和封装是否和我们一致,21届我们用的是NXP RT1064,但下一届规则可能允许更新的主控。引脚动态配置本来就是嵌入式开发的日常,我们的引脚映射表只是一个参考,所有外设的初始化代码在board_init.c里,工程结构其实是解耦的,你替换主控时,只需要改board_init层和对应的驱动库,算法层可以完全保留。
另外,把元器件清单和现有库存对比一遍再下单。我们踩过最坑的采购问题是:画板时用的封装是引脚间距0.5mm的排针,但买来的模块是2.54mm间距,焊不上。为了这次开源,我把硬件文件夹里所有板卡都附了一个“采购建议”备注,提醒你优先选哪种封装、哪种替代料兼容,这个细节能帮你省掉快递往返的时间。
7.2 可以怎么扩展:从“跑下来”到“跑得快”
我们的方案定位是稳定完赛,如果你野心更大,想在速度上继续突破,可以从三个方向扩展。
第一,优化能量管理。现在电源板还只是被动降压,你可以加一组超级电容缓冲模块,放在电池和电机驱动之间,吸收制动回馈能量,支持短时间内更高的加速电流。这个改动对极速的提升非常明显,但要注意电容的充电电流限制和泄放电阻,否则会变成一颗“炸弹”。
第二,算法层面引入模型预测或前馈控制。串级PID已经比单环好很多,但在大曲率弯道里,纯反馈还是有天然滞后。你可以根据赛道地图离线生成一个目标速度表和转向前馈表,在进入弯道前提前减速、提前打角,这是速度上限能否再跨过一个台阶的关键。开源目录里tools/文件夹下有一个简单的赛道分段标记脚本,可以帮你把一圈赛道离散段之后估算曲率。
第三,仿真和虚拟调试。我们赛季后期用了一个简单的单轮动力学模型,在PC上做PID参数预筛选,然后再把参数灌到真车。这样省了不少场地时间。仓库里有一份sim框架,虽然简陋,但它是一个可行的起点。
7.3 开源不是终点:保持持续贡献
我建这个开源目录的初衷,是想让下一届的学弟学妹少走几次弯路,所以我在许可证上特意选了非商业用途的CC协议,允许自由使用、修改和再分享,只要注明出处且不商用。任何人使用中发现bug,或者有自己的改进思路,都可以通过仓库的issue和PR跟我们交流。我会定期回来维护文档和代码,尤其是把24届新规则相关的适配问询整理进FAQ。
如果你也在准备智能车竞赛,或者在做类似的嵌入式项目,我最想说的其实只有一点:开源目录里的代码和电路图不重要,重要的是每一层决策背后的“为什么”。当你理解了为什么电源要分三路、为什么方向环输出角速度、为什么状态机里要放看门狗,你就已经不是一个“调参侠”,而是真正能独立设计一个小型机器人系统的工程师了。这份开源目录如果能帮你把“为什么”这一层打通,它被传到谁手里都值了。