第 5 篇让轮子真正转起来——PWM、编码器与 PID 闭环回顾全套小车工厂模型第1篇看懂main入口、头文件工具箱、开机初始化、while(1)主线流水线第2篇掌握变量储物盒、嵌入式专用定宽数据类型第3篇学会分支循环控制流、函数模块化、枚举状态机第4篇搞懂中断定时闹钟、volatile关键字、中断标准三步写法本篇进入车间动力核心讲透小车能动的整套关键技术PWM电子油门、编码器测速码表、PID速度闭环、陀螺仪角度纠偏。前面所有铺垫全部落地本篇真正让小车稳、直、准地跑起来。0. 引子小车乱跑的根本原因只写好程序框架、逻辑、中断小车依然跑不稳。如果直接给电机固定电压你会遇到两个必现问题1.四轮转速不一样电机出厂存在个体差异、地面摩擦力不均同样电压下四轮速度参差不齐小车必然跑偏2.速度无法稳定电池电压下降、行驶阻力变化时车速会自主波动完全不受程序控制。想让小车可控、直行、不漂移必须配齐整套动力三件套( 1 )PWM调节电机动力大小油门( 2 )编码器读取车轮真实转速测速眼睛( 3 )PID闭环自动微调油门稳住速度、修正偏差智能大脑1. PWM电机的无级电子油门1.1 什么是PWM大白话讲解单片机无法像电源一样直接无级调节输出电压它采用高频快速通断电的方式依靠“通电时长占比”模拟出平均电压以此控制电机转速。通俗比喻就像快速反复开关手电筒开得久、关得短光线就亮开得短、关得久光线就暗。只要开关频率足够高人眼和电机都感知不到卡顿运转效果和恒定调压完全一致转速顺滑无抖动。核心概念占空比占空比 高电平通电时长 / 一个完整PWM周期时长占空比越大 → 电机平均供电电压越高 → 转速越快反之则转速越慢。1.2 项目硬件配置TIM1高级定时器本项目使用TIM1 高级定时器输出4路独立PWM波形分别对应控制四个麦轮电机硬件自动输出波形无需CPU持续干预效率极高GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;// 复用PWM输出模式TIM_TimeBaseInitStructure.TIM_Period1000-1;// PWM计数最大值区间0~999TIM_TimeBaseInitStructure.TIM_Prescaler72-1;// 72MHz时钟分频TIM_OCInitStructure.TIM_OCModeTIM_OCMode_PWM1;// 选择PWM模式1TIM_OCInitStructure.TIM_OCPolarityTIM_OCPolarity_High;TIM_CtrlPWMOutputs(TIM1,ENABLE);// 高级定时器必须开启总输出最终输出PWM频率为1KHz无高频噪音电机运行平稳顺滑。1.3 调节车速的本质修改PWM比较值代码中通过修改比较值精准调节每一路电机的动力输出voidTIM1_SetCH1(uint16_tpwm){TIM_SetCompare1(TIM1,pwm);}数值有效范围0~999- 0占空比为0电机完全停转- 999满占空比电机全速运行。1.4 正负速度控制电机正反转重点区分PWM只控制转速大小不控制转向。小车通过额外的GPIO高低电平区分电机转向- 速度数值为正 → 正转引脚拉高电机正转- 速度数值为负 → 反转引脚拉高电机反转。这也呼应了第二篇的知识点车轮速度变量必须用int16_t支持正负数值如果使用无符号的uint16_t无法区分正负转速小车彻底无法后退运动逻辑完全错乱。1.5 纯开环控制的致命缺陷仅固定输出PWM数值属于开环控制。这种模式下哪怕四路PWM数值完全一致受电机公差、地面摩擦、电池电压波动影响四个车轮实际转速必然不同小车行驶一定会跑偏、漂移无法稳定直行。想要解决跑偏问题必须实时获取车轮真实转速编码器正式登场。2. 编码器车轮的高精度测速码表2.1 编码器通俗原理麦轮内置正交编码器车轮每转动极小角度编码器就会输出一组A、B两相脉冲信号。核心逻辑- 车轮转得越快单位时间内脉冲数量越多- 车轮转得越慢单位时间内脉冲数量越少- A、B两相相位差可精准判断电机正转、反转。STM32定时器支持硬件正交解码无需CPU手动计数硬件自动统计脉冲数量测速精准、不占用系统资源。项目硬件分配TIM2/TIM3/TIM4/TIM5 四个定时器分别独立采集四个车轮的编码器数据。2.2 5ms定时采集测速标准逻辑我们沿用第四篇的TIM7 5ms定时中断固定周期读取四轮转速保证测速时序统一、精度一致Speed1Encoder1_Get();Speed2Encoder2_Get();Speed3Encoder3_Get();Speed4Encoder4_Get();单次测速函数逻辑简单高效读完即刻清零计数器避免脉冲累积误差int16_tEncoder1_Get(void){int16_tTempTIM_GetCounter(TIM2);// 读取5ms内累计脉冲数TIM_SetCounter(TIM2,0);// 读取后立即清零计数器returnTemp;// 返回脉冲增量代表实时车速}每5ms的脉冲增量直接对应车轮的实时转速正负数值对应正反转。2.3 为什么车速变量必须加 volatileSpeed1~Speed4 属于典型的中断、主线共享变量- 中断服务函数负责实时修改转速数据- 主循环负责读取数据、PID运算、屏幕显示。如果不加volatile修饰编译器会开启变量缓存优化主线会一直读取旧的缓存数据出现屏幕车速卡死、速度反馈失效、PID不调节等隐形bug。3. PID闭环控制小车稳定行驶的核心算法3.1 开环 vs 闭环一秒看懂差距-开环控制只固定输出PWM油门不管车轮实际转速被动接受行驶状态车速波动大、极易跑偏-闭环控制设定目标车速编码器反馈真实车速PID算法自动增减PWM油门强行让实际转速贴合目标转速。通俗比喻就像汽车定速巡航上坡自动加大油门补动力下坡自动减小油门防超速全程稳住设定速度。3.2 P、I、D三项通俗白话解读不用复杂公式零基础也能看懂核心作用-P比例项快速纠偏目标速度与实际速度差值越大调节力度越强快速缩小转速偏差解决大范围速度误差-I积分项消除稳态误差P只能修正大偏差长期存在的微小转速差无法消除I会累积微小误差、逐步补齐让小车匀速行驶更稳、轨迹更直-D微分项防抖防震荡预判速度变化趋势提前收力避免转速忽快忽慢、车身抖动。3.3 项目实用方案增量式PI控制小车编码器采集的脉冲存在轻微噪声开启D微分项容易放大噪声导致电机异响、车身抖动。因此本项目采用工程最优方案舍弃D项使用PI控制兼顾稳定性与精准度。采用增量式算法每次仅在上一次输出基础上微调转速变化顺滑无突变floaterrortgt-(float)real;s-pid_outputKp*(error-s-last_err)Ki*error;// 限制PWM输出区间防止过载、炸机if(s-pid_outputPWM_MAX)s-pid_outputPWM_MAX;if(s-pid_outputPWM_MIN)s-pid_outputPWM_MIN;3.4 四轮独立PID控制项目为四个车轮配置了独立PID控制器互不干扰、单独修正。精准解决电机个体差异让四个车轮转速高度统一从根源减少行驶跑偏。3.5 模式切换必须重置PID小车切换前进、平移、旋转等运动模式时必须调用PID重置函数清空积分累积值。如果不重置上一种模式残留的积分输出会叠加到新模式上导致小车起步抖动、瞬间窜动影响行驶稳定性。4. 陀螺仪角度闭环彻底解决直行跑偏仅靠四轮速度PID只能保证四个车轮转速一致但地面打滑、机械装配误差、单侧阻力变化依然会让车头慢慢偏移小车越跑越偏。想要真正跑直线必须增加角度闭环。4.1 MPU6050航向角采集依托TIM7定时中断固定周期读取MPU6050陀螺仪原始角速度通过积分运算换算出小车车头航向角yaw实时掌握车头朝向。4.2 差速纠偏原理类比开车和手动开车修正方向逻辑完全一致- 车头向左偏移 → 右侧车轮加速、左侧车轮减速微调回正- 车头向右偏移 → 左侧车轮加速、右侧车轮减速微调回正。通过左右轮差速微调自动修正车头角度保证直行轨迹笔直。4.3 自动基准归零解决陀螺仪漂移陀螺仪长期积分会产生数值漂移导致轻微跑偏。项目设置自动校准逻辑小车无大幅度角度偏移时每隔1秒自动刷新航向基准零点抵消漂移误差长期行驶依然稳定。5. 本篇小结知识点通俗理解PWM电机电子油门通过占空比精准控制动力大小编码器车轮测速码表脉冲数量、正负对应车速与转向开环控制固定油门无反馈车速不稳、极易跑偏PID速度闭环智能定速巡航自动微调油门稳住四轮转速一致P比例项快速修正大范围速度偏差I积分项消除微小稳态误差让匀速行驶更笔直增量式PI渐进式微调输出小车行驶丝滑无抖动角度闭环陀螺仪实时纠偏彻底解决直行跑偏问题PID重置切换运动模式清空积分防止起步抖动窜动6. 第4篇趣味思考标准答案思考1Timer7_5ms_Count不加 volatile 会出现哪些故障该变量是整车唯一统一时间基准几乎所有定时功能都依赖它失效后果极其严重1. 遥控超时断连保护失效遥控器失联后小车不会自动刹车存在失控风险2. OLED屏幕定时刷新逻辑卡死画面长期静止不更新3. 软件延时、周期定时任务全部失效整车时序逻辑瘫痪。思考2中断漏清标志、不判断标志分别会怎样1.漏清中断标志硬件会持续触发中断请求主线程序彻底卡死小车完全失控2.不判断标志多中断源场景下会误触发无关逻辑导致数据错乱、功能异常。本篇趣味思考答案见第 6 篇末尾1. 如果去掉PID积分项Ki小车匀速直行会出现什么问题2. 编码器A、B两相接线颠倒对车速显示和PID控制会造成什么影响7. 交流我目前也是嵌入式自学新手本篇内容是结合自己麦轮小车项目实操总结而来部分知识点理解可能存在偏差讲解也有不够严谨的地方。1. 技术大佬如果发现文中存在错误、逻辑漏洞欢迎评论区指正我会及时修正文章2. 零基础小白有看不懂的知识点、实操踩坑问题都可以留言提问我看到会逐条回复3. 大家也可以分享自己做智能小车的经验、代码优化思路一起交流学习共同进步祝愿各位大佬项目开发一路顺畅调试零bug思路源源不断祝愿所有入门小白少踩弯路快速吃透STM32早日做出属于自己的智能小车下篇预告《第 6 篇无线遥控与通信协议——NRF24L01 怎么把按键变成小车指令》讲解NRF无线收发机制、遥控按键解析、一问一答通信帧彻底打通「遥控器按键 → 小车运动」完整链路。