1. PID控制的工程本质与应用场景

在嵌入式运动控制系统中,PID(Proportional-Integral-Derivative)并非一种抽象的数学游戏,而是一套经过工业界数十年验证、面向物理世界闭环调节的工程方法论。它的存在前提非常朴素: 被控对象的实际输出永远无法天然等于期望设定值 。这一基本事实源于电机负载变化、机械摩擦非线性、供电电压波动、环境温度漂移等不可消除的物理扰动。

以直流减速电机速度控制为例,当单片机输出一个固定的PWM占空比(如2000/65535),电机在空载、水泥地面、瓷砖、木板、沙地等不同工况下,实际转速必然产生显著差异。原因在于:同一电枢电压产生的电磁转矩,在不同滚动阻力和空气阻力下,所能维持的稳态角速度完全不同。若不引入反馈调节机制,系统本质上是开环的——设定值与实际值之间存在不可控的偏差带,且该偏差随工况剧烈漂移。

PID的价值正在于它构建了一个 可工程实现的误差驱动闭环
- R(Reference) :由上位机或用户设定的目标速度,单位为RPM或脉冲/秒;
- Y(Actual Output) :通过编码器实时采集的电机实际转速;
- E(Error) = R − Y :瞬时误差,是整个控制律的唯一输入信号;
- U(Control Output) :PID算法计算出的控制量,最终作用于PWM占空比寄存器。

这个闭环结构彻底改变了系统行为:它不再依赖“给多少占空比就转多少速度”的理想化假设,而是持续观测偏差、分析偏差的历史趋势与变化速率,并据此动态修正控制力度。其工程目标明确—— 在负载突变、供电波动等扰动下,将实际转速稳定在设定值附近,且超调小、响应快、稳态误差趋近于零

需要特别指出的是,“PID”本身不是目的,而是实现“伺服控制”这一更高层级目标的工具。在电机控制领域,我们常称其为 速度环(Speed Loop) ;当控制目标变为角度、位置或姿态时,则演变为 位置环(Position Loop) 姿态环(Attitude Loop) 。例如,使用MPU6050实时获取小车航向角θ,设定目标角度θ_ref,则误差E = θ_ref − θ,PID输出用于差速调节左右轮速,从而实现定向行走——这本质上是同一套控制逻辑在不同物理量上的映射。理解这一点至关重要:掌握PID,就是掌握了一种通用的、基于误差反馈的物理系统调节范式。

2. 闭环控制的先决条件:高可靠性测量装置

PID闭环的成立,以两个关键物理量的精确、实时获取为绝对前提: 设定值(R)可编程、实际值(Y)可测量 。其中,设定值由软件变量直接赋值,技术难度低;而实际值的获取,则构成了整个闭环的“感知神经”,其性能直接决定了PID能否有效工作。

在电机速度控制场景中, 编码器(Encoder)是目前工程实践中最主流、最可靠的测速传感器 。其核心优势在于:
- 非接触式测量 :无滑动摩擦,寿命长,免维护;
- 数字量输出 :抗干扰能力强,无需模拟信号调理电路;
- 高分辨率与线性度 :可精确分辨微小转速变化;
- 方向识别能力 :支持正反转判别,满足全向运动需求。

编码器按原理可分为光电式与霍尔式两类:
- 光电编码器 :利用LED光源与光敏接收管,配合带有等距透光缝隙的码盘工作。当电机轴带动码盘旋转时,光线周期性通断,产生方波脉冲。其精度高、响应快,但成本较高,对灰尘、油污敏感;
- 霍尔编码器 :利用霍尔元件感应磁极变化。结构更坚固,耐油污、防尘性能优异,成本较低,适用于工业现场,但分辨率通常低于同价位光电编码器。

对于绝大多数学生实验与中小型机器人项目,霍尔编码器已完全满足需求。本案例所采用的即为典型霍尔编码器电机,其内部结构清晰分层:
- 底部 :标准直流减速电机本体。所谓“减速”,是在普通直流电机后级集成行星齿轮或蜗轮蜗杆机构,以牺牲转速为代价换取输出扭矩的数十倍提升。实物上表现为电机前端凸出的金属壳体,这是识别减速电机的直观标志;
- 中部 :编码器模块。通过精密联轴器与电机轴刚性连接,确保两者同步旋转;
- 顶部 :信号处理电路板,完成霍尔信号整形、滤波与AB相输出。

该结构设计实现了机电一体化:编码器仅感知轴的机械转动,与电机驱动电路完全电气隔离。这意味着,即使不给电机供电,只要手动旋转轴,编码器A/B相仍能输出标准正交脉冲——这是验证编码器接线与MCU解码功能的最基础测试方法。

3. 正交解码原理与STM32硬件实现

编码器输出的AB两相脉冲,并非简单的计数信号,而是一组具有严格相位关系的正交方波。其设计精髓在于: 利用相位差编码旋转方向,利用脉冲密度编码旋转速度 。理解此原理,是正确配置STM32定时器进行正交解码的基础。

3.1 正交脉冲的物理意义

观察标准正交编码波形图:A相与B相方波周期相同,但相位相差90°(即四分之一周期)。当电机正向旋转时,A相脉冲前沿总领先B相前沿;反向旋转时,B相前沿则领先A相。这种相位领先关系,是方向判别的唯一依据。

更关键的是, 每个完整的机械周期内,AB相组合可产生4个状态跳变
- A=0, B=0 → A=1, B=0 (正向第一步)
- A=1, B=0 → A=1, B=1 (正向第二步)
- A=1, B=1 → A=0, B=1 (正向第三步)
- A=0, B=1 → A=0, B=0 (正向第四步)

反向旋转时,状态转换顺序恰好相反。因此,一个1024线的编码器(即码盘有1024个刻线),在正交解码模式下,每转一圈可产生1024 × 4 = 4096个计数脉冲。这4倍频效应,是正交解码相对于单相计数的核心价值——它成倍提升了测速分辨率与低速稳定性。

3.2 STM32定时器的正交解码模式

STM32的高级定时器(TIM1/TIM8)与通用定时器(TIM2-TIM5, TIM9-TIM14)均支持硬件正交解码。其核心是将定时器的编码器接口(TI1与TI2)配置为捕获通道,自动解析AB相的边沿序列,并根据预设的方向逻辑,对计数器(CNT)进行递增或递减操作。

本案例选用TIM3定时器,其通道1(CH1)与通道2(CH2)分别映射至GPIOB的Pin6与Pin7(即PB6, PB7)。此引脚选择并非随意,而是严格遵循STM32数据手册的 重映射规则 :TIM3_CH1与TIM3_CH2的默认复用功能即为PB4/PB5,但通过AFIO重映射寄存器(AFIO_MAPR),可将其重映射至PB6/PB7。此举规避了PB4/PB5可能与其他外设(如SPI1_NSS)的冲突,体现了工程设计中的引脚资源规划意识。

在CubeMX或寄存器配置中,关键参数如下:
- Clock Source :设置为 Internal Clock ,即定时器自身作为时钟源;
- Counter Mode :必须选择 Encoder Mode ,并指定 Encoder Mode 1 (仅TI1计数)或 Encoder Mode 2 (仅TI2计数)或 Encoder Mode 3 (TI1与TI2共同计数,即标准四倍频模式);
- PSC(Prescaler) :置0,禁用分频,确保最高计数精度;
- ARR(Auto-Reload Register) :设置为65535(0xFFFF),即16位计数器最大值。此值的选择需权衡:
- 若编码器线数已知(如1024线),最优ARR = (线数 × 4) − 1 = 4095,使计数器每转一圈自动溢出,便于计算转速;
- 但本案例中编码器线数未标定,故采用最大值65535。此时计数器溢出周期变长,需在软件中处理溢出中断,累加溢出次数以获得真实计数值。虽增加软件复杂度,但保证了对任意线数编码器的兼容性。

硬件解码的优势在于:CPU无需干预脉冲计数过程,计数由硬件全自动完成,实时性高、无丢脉冲风险。这为后续PID运算释放了宝贵的CPU资源。

4. 实验平台搭建与硬件接口规范

一个可靠、可复现的实验平台,是理论知识转化为实践能力的基石。本案例的硬件架构遵循模块化、电气隔离、电源适配三大原则,具体实现如下:

4.1 电源系统设计

电机与编码器对供电质量要求迥异,必须分立设计:
- 电机驱动电源 :采用3S锂聚合物电池(标称电压11.1V,满电12.6V)。该电压等级完美匹配电机额定电压范围(11–16V),可提供充足启动扭矩。需注意:3S电池满电电压略低于电机上限,若实验中出现带载无力现象,下一阶段将升级为4S电池(标称14.8V,满电16.8V);
- 编码器逻辑电源 :霍尔编码器工作电压为5V,必须由稳定LDO(低压差稳压器)从电池电压降压获得。本平台使用AMS1117-5.0芯片,其输入耐压达15V,输出电流可达1A,完全满足编码器及MCU的逻辑供电需求。稳压后的5V通过排针引出,形成独立的调试电源轨;
- MCU主控电源 :STM32F103C8T6开发板自带USB转串口芯片(CH340),其5V输出经板载AMS1117-3.3稳压后,为MCU核心提供3.3V电源。此电源仅用于MCU逻辑, 严禁 用于驱动电机或编码器,避免地线噪声窜入数字电路。

4.2 信号连接与电气隔离

各模块间连接严格遵循信号流向与电气隔离规范:
- 编码器至MCU :编码器的A相、B相、GND、VCC四线,直接焊接至开发板的PB6、PB7、GND、5V排针。务必确保GND共地,否则AB相信号参考电平漂移,导致解码错误;
- MCU至电机驱动 :MCU的两个通用IO(如PA0, PA1)输出PWM信号,接入L298N驱动芯片的IN1、IN2引脚;
- 电机驱动至电机 :L298N的OUT1、OUT2端子连接电机两端;
- 电机驱动电源 :L298N的VCC(电机电源)端子直接接入3S电池正负极;
- 关键隔离点 :L298N的逻辑电源(VSS)与电机电源(VCC)的地(GND)在芯片内部是隔离的。必须将L298N的逻辑地(VSS GND)与MCU的GND短接,同时将L298N的电机地(VCC GND)与电池负极短接,最后将这两组地在电源入口处单点连接。此“星型接地”法可最大限度抑制电机换向产生的大电流噪声对MCU的干扰。

4.3 调试接口配置

为实时监控电机转速,系统通过USART1(PA9/PA10)将解码计数值发送至上位机。波特率设为115200,数据格式为8-N-1。上位机软件(如XCOM、SSCOM或自定义Python脚本)负责接收、解析并绘制实时曲线。调试时,应首先断开电机驱动,仅给编码器供电,手动旋转电机轴,观察串口是否稳定输出变化的计数值——此为验证编码器硬件链路与MCU解码功能的黄金步骤。

5. 从计数值到物理转速的工程换算

定时器捕获的原始计数值(CNT)是一个无量纲的整数,其大小仅反映AB相脉冲的累积数量。要将其转化为具有物理意义的转速(如RPM),必须建立严格的数学映射关系。该换算过程包含三个关键环节: 时间基准确定、脉冲-转角关系建立、单位制统一

5.1 时间基准:采样周期的精确控制

转速定义为单位时间内的转数。因此,必须在一个精确、稳定的采样周期T内,读取计数器的增量ΔCNT。本案例采用 定时器更新中断(Update Interrupt)作为采样触发源
- 将TIM2(或其他独立定时器)配置为周期性中断,中断周期T = 100ms(即10Hz采样率);
- 在TIM2中断服务函数中,执行以下原子操作:
c uint16_t current_cnt = __HAL_TIM_GET_COUNTER(&htim3); // 原子读取当前计数值 uint16_t delta_cnt = current_cnt - last_cnt; // 计算增量 last_cnt = current_cnt; // 更新上一次读数
- 关键点: __HAL_TIM_GET_COUNTER() 是CMSIS定义的底层宏,直接读取CNT寄存器,无函数调用开销,确保读取动作的原子性。若在读取过程中发生TIM3溢出, delta_cnt 计算将因16位无符号数的自然回绕而自动正确(例如,从65534到2,delta = 2 − 65534 = 4,符合预期)。

5.2 脉冲-转角关系:线数与倍频因子

设编码器标称线数为N(lines/revolution),则每转一圈产生的AB相状态变化数为4N(四倍频)。因此,计数器每增加1,对应的角度增量为:

Δθ = 360° / (4N) = 90° / N

若已知N=1024,则每计数1次,轴旋转0.0879°。但实际应用中,N往往未知,此时需采用 实测校准法
- 固定电机轴,手动旋转整整一圈(360°),记录TIM3计数器在此期间的总增量ΔCNT_total;
- 则实际线数 N_actual = ΔCNT_total / 4;
- 后续所有转速计算均以此N_actual为准。

5.3 转速计算公式推导

在采样周期T(秒)内,计数器增量为ΔCNT,则:
- 对应的机械转数 = ΔCNT / (4N)
- 对应的转速(RPS, revolutions per second) = [ΔCNT / (4N)] / T = ΔCNT / (4N × T)
- 转速(RPM, revolutions per minute) = [ΔCNT / (4N × T)] × 60 = (15 × ΔCNT) / (N × T)

代入T = 0.1s(100ms),得:

RPM = (15 × ΔCNT) / (N × 0.1) = 150 × ΔCNT / N

此即本案例中使用的最终转速公式。例如,若ΔCNT = 4096,N = 1024,则RPM = 150 × 4096 / 1024 = 600 RPM。该公式简洁、高效,可在资源受限的MCU上快速完成整数运算。

6. PID控制律的离散化实现与参数物理意义

PID控制器的连续域传递函数为:

U(s) = Kp × E(s) + Ki × E(s)/s + Kd × s × E(s)

其中Kp、Ki、Kd分别为比例、积分、微分增益。在数字系统中,必须将其离散化为差分方程。本案例采用最常用、最易实现的 位置式PID(Position Form) ,其离散化形式为:

U[k] = Kp × e[k] + Ki × T × Σe[i] + Kd × (e[k] − e[k−1]) / T

其中:
- U[k] :第k个采样周期的控制输出(即PWM占空比);
- e[k] :第k个采样周期的误差(R − Y);
- T :采样周期(秒);
- Σe[i] :从i=0到i=k的所有历史误差累加和。

6.1 各项增益的物理意义与工程影响

  • 比例项(Kp × e[k]) :提供即时响应。Kp越大,系统对误差的反应越激烈,响应越快,但过大会导致超调甚至振荡。其本质是“误差越大,用力越猛”。在电机启动阶段,Kp主导了初始加速能力;
  • 积分项(Ki × T × Σe[i]) :消除稳态误差。只要存在持续误差,积分项就会不断累积,推动输出持续调整,直至误差为零。Ki过大,会使系统响应迟钝、易饱和;Ki过小,则消除静差缓慢。它是克服恒定负载(如摩擦力矩)的关键;
  • 微分项(Kd × (e[k] − e[k−1]) / T) :预测未来趋势。它对误差的变化率敏感,能在误差急剧增大前施加反向抑制力,有效抑制超调与振荡。Kd过大,会放大高频噪声,导致输出抖动;Kd过小,则阻尼不足。

6.2 工程实现中的关键细节

  • 积分饱和(Integral Windup)防护 :当电机堵转或指令突变时,误差长期存在,积分项会累积至极大值,导致控制器输出超出PWM范围(0–65535)。一旦误差反转,积分项需长时间释放,造成严重滞后。解决方案是实施 积分限幅(Anti-windup)
    c integral += error; if (integral > INTEGRAL_MAX) integral = INTEGRAL_MAX; else if (integral < INTEGRAL_MIN) integral = INTEGRAL_MIN;
  • 微分先行(Derivative on Measurement) :标准PID中微分作用于误差,易受设定值阶跃干扰。工程中更推荐将微分作用于被控量Y(即编码器转速),因其变化更平缓,抗噪性更好。此时控制律变为:
    U[k] = Kp × e[k] + Ki × T × Σe[i] − Kd × (Y[k] − Y[k−1]) / T
  • 输出限幅与死区 :最终PWM输出U[k]必须钳位在[0, 65535]范围内。此外,为避免电机在极低速时因静摩擦力无法启动,可设置一个微小死区(Dead Band),当|U[k]| < Dead_Band时,强制U[k] = 0。

7. 上位机监控与调试工具链

实时、可视化的数据监控,是PID参数整定与系统故障诊断不可或缺的环节。本案例采用轻量级串口协议,配合上位机软件,构建高效调试环境。

7.1 串口数据协议设计

为平衡传输效率与解析简易性,采用固定帧长、无校验的简洁协议:
- 帧头 :0xAA(1字节);
- 数据域
- 目标转速R(uint16_t,2字节,单位:RPM);
- 实际转速Y(uint16_t,2字节,单位:RPM);
- PWM输出U(uint16_t,2字节,0–65535);
- 帧尾 :0x55(1字节);
- 总帧长 :8字节。

MCU在每个TIM2采样周期结束时,将当前R、Y、U打包,通过HAL_UART_Transmit()发送。上位机以8字节为单位接收,校验帧头帧尾后,提取三组数据。

7.2 上位机软件选型与配置

  • XCOM(国产经典) :界面简洁,支持多通道绘图。配置要点:
  • 波特率:115200;
  • 数据位:8;停止位:1;校验位:None;
  • 接收模式:HEX显示(便于观察帧头帧尾);
  • 绘图模式:启用,X轴为时间(自动),Y轴为三组数据,设置不同颜色与图例;
  • Python + Matplotlib(进阶定制) :利用 pyserial 库读取串口, matplotlib.animation 实现实时动态绘图,可添加FFT频谱分析、统计信息(均值、方差)等高级功能,适合深入研究系统动态特性。

调试时,应首先观察空载状态下的阶跃响应:设定R=300 RPM,观察Y从0上升至300的过程。理想曲线应具备:快速上升(高Kp)、无超调或轻微超调(合理Kd)、最终稳态无静差(有效Ki)。任何偏离(如持续爬升、大幅振荡、迟迟不达目标)都指向相应PID参数的失配。

8. 知识储备的实践检验:首个闭环运行现象分析

当所有硬件连接无误、固件烧录成功、上位机连接就绪后,首次加电运行将呈现极具教学意义的现象—— 计数器值的规律性溢出与爬升

具体现象描述:
- 电机未供电时,串口持续输出Y=0;
- 电机供电瞬间,Y值从0开始,以近似线性斜率稳步上升;
- 当Y值接近65535时,数值骤然跳变回0,并立即开始新一轮上升;
- 此过程循环往复,形成锯齿状波形。

此现象的根源,正是前述正交解码的硬件机制:
- TIM3工作在Encoder Mode 3,CNT寄存器为16位,最大值65535;
- 每当AB相完成一个完整四步循环(即电机轴旋转1/(4N)圈),CNT自动+1;
- 当CNT从65534增至65535后,下一个脉冲触发溢出(Overflow),CNT清零,并置位更新中断标志(UIF);
- 若软件未在中断中及时处理溢出事件,则CNT从0重新开始计数,导致Y值显示为0→65535→0的循环。

因此,观察到“0→65535→0”的锯齿波,是 硬件解码功能正常、编码器信号有效、电机确实在旋转 的三重证据。它验证了从物理旋转到数字计数的完整信号链路。下一步,便是将此原始计数值,通过前述时间基准与线数换算,转化为真实的RPM值,并最终接入PID闭环,让电机真正“听话”。

我在实际项目中曾遇到过一次诡异的“假溢出”:电机静止时,Y值仍在缓慢跳变。排查发现是编码器A/B相引线与电机驱动线捆扎过近,L298N换向产生的di/dt噪声耦合进信号线,被TIM3误判为有效脉冲。解决方法是将编码器线单独走线,并在PB6/PB7端口各并联一个10nF陶瓷电容至GND,构成RC低通滤波器。这个细节提醒我们:理论再完美,也必须经受住真实电磁环境的考验。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐