智能车电磁组完整方案:从电感选型到PID调参全解析 📅 发布时间:2026/9/1 7:46:21 👁 浏览次数: 简介面向第二十届全国大学生智能车竞赛缩微电磁组参赛者这份压缩包提供了竞赛核心方案与配套代码仓库入口帮助选手快速理解赛题解析、机械结构设计、硬件选型、PID控制及差比和算法等关键内容适合正在备赛、需要系统梳理调车思路的嵌入式开发学习者。资源包共2个文件主体为inscode项目文件与HTML说明页压缩包仅5KB轻量易用inscode文件可直接查看代码结构HTML文档则主要用于方案浏览与信息索引。已有245人学习下载。除方案综述外内容还覆盖动态权重调整、转向环串级控制等核心技术在直角弯、十字路口等复杂赛道的应用并给出接线说明、元件清单与开源库资料能够有效减少赛前摸索成本值得在备赛阶段反复查阅。 每年智能车竞赛的电磁组都是最考验团队综合能力的一个项目。我带队参加了第21届全国大学生智能车竞赛电磁组从最初的电感选型到最后赛道调试前后折腾了将近四个月。这个组别有意思的地方在于它把模拟电路、数字信号处理、自动控制原理和嵌入式开发全部浓缩到一辆小车上任何一个环节拖后腿车就跑不稳。这篇博文把我们的完整方案整理出来从硬件链路到代码逻辑再到调参踩坑的细节给后面参赛的队伍一个可以直接参考的底子。1. 整体方案设计思路1.1 赛题核心与电磁信号的本质电磁组的赛道核心规则不复杂赛道中心线下方铺设一条通有20kHz交变电流的导线电流通常为100mA左右。车模在赛道上行驶时依靠车头安装的电感线圈感应导线产生的交变磁场通过检测磁场强度来判断车身相对赛道中心线的偏离程度。这里需要先理解一个物理基础电感线圈在交变磁场中会产生感应电动势电动势的大小与磁场强度有关。对于一条无限长直导线在距离导线r处的磁感应强度B约等于μ₀I / (2πr)也就是说磁场强度与到导线的距离近似成反比。这就是电磁寻线的物理根基。我们做的所有事情本质上都是要把这个距离信息转换成单片机可读的数字量再换算成转向控制量。理解了这一点就知道为什么电磁组不像摄像头组那样能看到远处它只能感知车头前方一小片区域的磁场强度。所以电磁组的控制策略天然偏向快速响应对传感器的实时性和控制的灵敏度要求很高。1.2 系统架构与信号链路我们的整体方案采用经典的五电感水平布局。主控选用STC8H8K64U这是一款51内核的单片机主频最高40MHz左右ADC采样速度足够IO资源也够用关键是好上手环境配置快。整个信号链路是赛道导线中的20kHz交变电流 → 工字电感感应产生微弱的20kHz正弦信号 → 谐振电路选频放大 → 运放放大 → 二极管检波变成直流电平 → 单片机ADC采样 → 归一化处理 → 计算偏差 → 方向PD控制与速度PID控制 → 输出PWM驱动舵机和电机这个链路里前四步属于模拟电路部分也是最容易出问题的部分。很多队伍上来就写代码调PID结果发现车怎么调都抖最后排查发现是信号链路有问题——电感焊反了、谐振点偏了、检波后信号带毛刺全是硬件问题。所以电磁组一定要先保证信号质量再谈控制算法。2. 核心细节解析与实操要点2.1 传感器选型与谐振电路计算电感选择方面我们用的是10mH的工字电感配合6.8nF的电容构成并联谐振电路。这里有一个关键公式需要记住谐振频率f 1 / (2π√(LC))。把L10mH、C6.8nF代入算出来f ≈ 19.3kHz非常接近20kHz的赛道频率。为什么要让谐振频率对准20kHz因为并联谐振电路在谐振频率点阻抗最大输出电压也最大同时能对其他频率的干扰信号起到衰减作用。如果你的谐振点偏了哪怕只偏1kHz信号幅度都会明显下降这时候车在弯道上的响应就会变迟钝。选电容时建议用CBB电容或涤纶电容温度稳定性比瓷片电容好一些。我们第一次用瓷片电容早上调车和中午调车时信号幅度会漂后来换CBB电容后这个问题基本消失。每个电感都要实测谐振点做法是接信号发生器扫频或者直接在赛道上用车上的ADC读取不同电感的原始值看哪一路信号明显偏弱。2.2 运放与检波电路配置谐振电路输出的信号大约在几十到几百毫伏量级直接用单片机ADC采样分辨率不够需要先放大。运放我们用了LMV358这是一款轨到轨运放单电源3.3V供电时也能输出比较好的动态范围。放大倍数设置在10倍左右通过反馈电阻配比实现。注意运放供电一定要做好去耦每个运放的电源引脚旁边加一个0.1μF的瓷片电容否则高频噪声很容易串进来。检波环节我推荐用峰值检波而不是简单的半波整流。峰值检波电路由一个二极管和一个电容组成二极管选用1N4148这种开关速度快的小信号二极管电容取10nF左右即可。检波后的直流信号会有一定的纹波可以让它直接进ADC但在代码里要做软件滤波后面会讲到。2.3 传感器布局的工程经验传感器布局直接决定了车的视野。我们最终采用的是水平五电感方案五个电感横向排列在车头间距约6cm中间电感对准车模纵向中轴线两边对称分布。整体安装在车头前方约10cm处离地高度2cm左右。为什么要离地2cm这个高度对赛道导线的磁场响应比较灵敏太低容易刮到赛道太高信号衰减太厉害。布局调整时有一个实用技巧先把所有电感固定好然后把车放在赛道正中央用串口把五路ADC原始值打印出来观察应该是中间电感最大两边对称递减。如果数据不符合这个规律说明布局或焊接有问题需要先解决。3. 代码实现与算法流程3.1 归一化处理让传感器之间平等对话理论上每个电感的物理特性完全一致但实际上工字电感的感值和内阻会有离散性放大电路的增益也可能有细微差异。如果不做归一化同样的偏移量在赛道的左边和右边产生的偏差值可能不一样车跑起来就会左右不对称。归一化的目的就是把每路ADC值映射到0到1的范围内消除传感器之间的个体差异。归一化公式我们用的是典型的线性映射// 每路电感的归一化raw为ADC原始值min和max为该路实测的最小值和最大值 float normalize(int ch, uint16_t raw) { float val (float)(raw - sensor_min[ch]) / (sensor_max[ch] - sensor_min[ch]); if (val 0.0f) val 0.0f; if (val 1.0f) val 1.0f; return val; }重点在于sensor_min和sensor_max怎么标定。我们的做法是跑道上电后先把车放到赛道正中央读取并记录中间电感的ADC值注意这个值不是max然后把车分别向左右偏移到即将出界的临界位置记录各路电感的极值最后选一段包含大弯和直道的赛道把车推过去持续记录各路的最大值和最小值。取多次测量的极限值作为最终的min和max。一个容易忽略的细节是要在车跑起来后让电机和舵机都通电的情况下测因为电机和舵机工作会产生电磁干扰会影响ADC读数。3.2 位置偏差计算差比和算法常见的偏差算法有加权平均和差比和两种。加权平均的公式是error (Σ val[i] × position[i]) / Σ val[i]其中position是每个电感的固定位置坐标比如从-15cm到15cm。这个方法直观但在电磁组有个问题当车在赛道中央时中间电感值最大两边对称计算出的偏差值接近0这是对的。但如果车偏向一侧外侧电感的绝对值很大计算出的偏差会偏大导致控制量非线性。相比之下差比和算法对信号幅度的变化更鲁棒尤其是在距离导线较远、整体信号都较弱的情况下优势更明显。我们用的是水平电感的差比和变形// 五路电感归一化值分别为 n[0] ~ n[4]从左到右排列 float error ( (n[4] - n[0]) 0.5f * (n[3] - n[1]) ) / (n[0] n[1] n[2] n[3] n[4]);分子上越靠近外侧的电感权重越大外侧两路权重是1内侧两路是0.5这样做的目的是增加偏差对横向位移的灵敏度。分母是所有电感和相当于自动做了归一化让偏差值不受整体信号强度影响。这套算法在直道上偏差值接近0在弯道上会根据曲率产生对应极性的偏差而且曲率越大偏差越大天然带有一定前瞻性。要注意的是差比和存在一个软肋如果所有电感同时饱和比如车压到导线上方所有电感都达到最大值分母会变得很大偏差被压缩到接近0表现为丢线。针对这个问题我们加了一个判断如果中间电感的归一化值大于0.95且两侧电感值都大于0.7就直接把前一个有效偏差值保持一小段时间而不是清零。3.3 方向PD与速度PID控制电磁组的转向控制我们最终定的是PD控制器没有加积分。原因是电磁信号波动较大积分项容易积累误差导致车头左右低频摆动。PD公式int16_t steer_pwm base_pwm (int16_t)(KD * (error - error_last) KP * error); error_last error;这里的base_pwm是舵机的中位PWM值KP和KD需要实车调。PD控制里D项的作用是抑制偏差的变化速率让转向平缓不会因为偏差突变而猛打方向。在高速通过S弯时D项尤其重要它相当于一个阻尼让车头保持稳定。速度控制我们是增量式PID直接用编码器测速反馈int speed_pid(int target_speed, int current_speed) { int error target_speed - current_speed; integral error; if (integral INTEGRAL_LIMIT) integral INTEGRAL_LIMIT; if (integral -INTEGRAL_LIMIT) integral -INTEGRAL_LIMIT; int derivative error - last_error; last_error error; return KP_sp * error KI_sp * integral KD_sp * derivative; }速度PID的输出加到电机PWM上作为油门值。积分限幅很关键电磁组赛道上经常要减速过连续弯如果不限幅积分项可能在长时间减速后积累到很大的值导致出弯加速特别猛车直接飞出去。目标速度怎么给很多队伍用固定速度跑简单但上限低。我们的方案是根据当前偏差和偏差变化率动态调整目标速度偏差小时目标速度提高偏差大时目标速度降低。这样车在直道上能冲刺弯道自动减速既稳定又在整体速度上不吃亏。3.4 主循环架构与代码组织电磁组的代码结构相对清晰我们采用的是前后台架构主循环里按顺序执行采集、滤波、解算、控制不需要上RTOS。关键代码框架如下void main() { system_init(); while (1) { // 1. ADC采集五路电感值 for (int i 0; i 5; i) { raw[i] read_adc(channel[i]); // 滑动平均滤波窗口长度为5 filtered[i] sliding_average(i, raw[i]); } // 2. 归一化 normalized[i] normalize(i, filtered[i]); // 3. 计算偏差 error calc_error(normalized); // 4. 方向PD控制 steer_pwm steer_pd(error); set_servo_pwm(steer_pwm); // 5. 速度PID控制 speed encoder_read(); target_speed calc_target_speed(error); motor_pwm speed_pid(target_speed, speed); set_motor_pwm(motor_pwm); // 6. 串口调试数据发送 send_debug_info(); delay_ms(2); } }这里有几个细节要提滑动平均滤波窗口长度取5对应的延时大约是10ms。这个延时对电磁组来说可以接受它换来的是ADC值的平滑性。更先进的做法是卡尔曼滤波或互补滤波但在这个场景下滑动平均已经足够而且计算量小代码简单可靠。主循环周期控制在2ms左右也就是500Hz频率。这个频率对于舵机控制通常刷新频率50-300Hz来说足够高了。其实不需要main loop跑得更快因为电磁组信号本身的响应速度有限跑太快反而会让控制量过于敏感车会抖。主循环的delay要配合调速最好是直接用定时器做固定周期调度而不是简单的delay这样在不同优化等级下编译出来的代码控制频率都能保持一致不会因为主频配置变化导致控制参数失效。4. 调试流程与参数整定实录4.1 硬件上电自检每次上电后第一件事我们不会直接跑车而是用串口监视器观察五路ADC原始值。标准的自检流程是赛道上电把车放在赛道正中央打印五路ADC值。正常情况下应该是中间电感最大两边依次递减。如果数据异常先用万用表量各电感的输出电压从源头上排查。用手横移小车观察五路ADC值是否平滑变化有没有跳变。跳变一般是接触不良或者检波二极管焊虚了。把舵机PWM输出设为固定值听舵机有没有异响或发热。舵机如果在静止状态下发热明显多半是中位PWM频率不对或者PWM周期和舵机要求的50Hz不匹配。我见过不少队伍在代码里调了半天最后发现是自检没做某个电感的线断了一半信号时有时无那整个控制逻辑都是在猜测数据怎么调都白搭。4.2 PID参数的整定顺序与方法PID参数整定我们有一套固定的流程顺序很重要第一步先调方向环。把速度设得很低比如0.5m/s先只调KP。从小往大加直到车在直道上能居中、在弯道上能顺利过弯但会出现小幅左右摆动。这时记录一个KP值然后往回调低20%左右得到一个安全KP。第二步加KD。从小往大加观察车在入弯和出弯时的表现。D项太大会让转向动作变得僵硬甚至在高频振荡D项太小则车在S弯中会显得软响应慢。最终调到车过S弯时车头没有明显横向摆动整体轨迹平滑。第三步加大速度重新微调KP和KD。速度提高后同样的偏差变化率对应的动态响应需求更高所以KD往往需要适当增大同时KP可能需要略降一些避免过冲。第四步调速度PID。首先只加KP_sp让车在直道上能稳定加速到目标速度然后加KI_sp消除稳态误差最后加KD_sp平抑速度波动。需要注意的是积分项的限幅一定要在调试初期就设定好不然在你还没开始调速度环的时候积分项就可能已经顶满导致电机全速输出。4.3 特殊元素处理与策略调整第21届竞赛的赛道上电磁组会遇到十字交叉、起跑线、坡道等元素。这里最难的是十字交叉因为十字处导线在交叉点附近会产生两个方向的磁场叠加水平电感组会检测到一个假的赛道中心信号车可能直接冲出去。我们的处理方案是在检测到偏差值超过一定阈值且持续一定时间时判断可能进入十字此时屏蔽掉最外侧两路电感的信号只用中间三路电感进行偏差计算。因为十字交叉时真正能表征主赛道方向的信号集中在中间区域外侧电感容易被交叉导线干扰。屏蔽后车在十字处的轨迹会更稳定。这个逻辑要放在偏差计算之前用状态机管理if (cross_flag) { // 十字模式只用中间三路 error calc_error_cross(normalized); } else { error calc_error_normal(normalized); }起跑线的处理相对简单它是停车区前方的一条磁铁带对电感信号影响不大主要影响的是检测停车。我们在代码里加了起跑线检测逻辑通过一段固定时长的磁场突变信号不过如果只追求完赛这部分可以简化。5. 常见问题与排查技巧实录5.1 高频问题速查表现象可能原因排查与解决办法车在直道上左右摆头KP过大产生振荡 / 舵机中位不准 / 传感器安装不对称先核对舵机中位再降低KP检查五路电感是否严格对称安装弯道入弯迟钝冲出赛道KD不足 / 电平感布局过于靠后增大KD将电感前移以增加信号变化的提前量跑起来后信号幅度明显变小电机电磁干扰 / 电源纹波过大电机驱动与传感器分开供电电机外壳接地电源加LC滤波车逐渐偏向一边某路电感信号异常 / 归一化参数漂移用串口打印归一化前后数据检查是哪一路电感数值偏低或偏高低速正常高速乱跑速度环没调好 / 方向环跟不上先限定最高速度单独调方向环在高速下的表现再优化速度环动态响应过十字时跑飞十字交叉信号干扰增加十字识别状态机屏蔽外侧电感5.2 排查思路与调试工具调试时先用串口把重要的中间变量全部打出来包括五路归一化值、偏差值、目标速度、实际速度、PWM输出。我在调车时习惯用蓝牙模块无线发送数据这样车在跑动过程中也能实时看到数据变化不然只能等车跑完停下来才能下载数据效率太低了。调参时把数据记录下来回放分析比在赛道上凭感觉调要靠谱得多。还有一个排查方向经常被忽略电源稳定性。电磁组的系统里有舵机、电机、传感器、单片机电机是最大的干扰源。如果电源处理不好ADC基准电压会跟着波动导致传感器数据包含大量噪声。我们之前遇到过一个诡异的问题车在高速时传感器数据偶尔跳变排查了好久最后发现是电池电压低于7.2V之后稳压芯片输出开始出现纹波而ADC采集刚好在纹波峰值附近导致读数异常。后来换了低 dropout 的稳压芯片并且在电机驱动电源和传感器电源之间加了LC隔离问题才彻底解决。5.3 经验之谈有几个调试经验值得多说两句。其一调参时一定要做好记录建议把每次修改的参数、赛道表现、数据日志都记下来否则调了两小时之后发现越来越差你都不记得是从哪个版本开始的。我们队后来养成了每次调参前先备份代码版本的习惯配合git管理出了状况随时可以回退。其二电磁组的车对机械结构非常敏感。电感支架的固定方式、轮胎磨损程度、底盘高度变化都会影响信号特征。我们比赛前夜发现车过一个特定位置的弯道时总会抖动排查半天发现是电感支架有一颗螺丝松了导致电感在高速振动中位置偏移。所以每次调车前花两分钟检查所有螺丝和结构件比多调一小时的PID收益更大。其三如果你发现车的表现时好时坏先怀疑硬件连接再怀疑供电最后才怀疑代码逻辑。软件往往是稳定的硬件在颠簸和振动中才是最容易出问题的。这条经验帮我省了无数个调试的夜晚。这辆电磁组小车带给我的收获远不止一次比赛的成绩。从电感谐振的物理原理到PID整定的实操手感整个方案里每一个环节都有值得钻研的细节。赛后我们团队复盘时达成了一个共识电磁组最大的魅力在于它逼迫你把每一个环节都理解透彻只要有一个地方是蒙对的车就会在各种意想不到的场合把你的侥幸暴露出来。希望这份方案能帮后面参赛的队伍少走一些弯路也期待看到大家在赛道上有更快的发挥。本文还有配套的精品资源点击获取