尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PWM电机开环控制完全指南:从占空比原理到STM32落地

PWM电机开环控制完全指南:从占空比原理到STM32落地 从任务板上的P0标签说起——在一个真实的产品开发流程里P0意味着“优先级最高、阻塞一切、必须先跑通”。而PWM电机开环控制恰恰就是几乎所有电机应用的第一块多米诺骨牌轮式机器人要动起来先靠它风机水泵要转起来先靠它连后面要做的闭环调速、位置控制、力控本质上都是在开环这个“底座”上长出来的。这篇文章就围绕这个“底座”来写从PWM控制电机的物理本质讲起到H桥驱动电路、PWM参数选型再到STM32平台上的代码落地和实测数据最后聊聊开环控制的使用边界和往闭环演进的思路。不管你是刚接手第一个电机项目的学生还是被分派去调驱动板的工程师这篇文章都按“自己重新做一遍”的标准来写。1. 先把最基本的物理关系搞清楚占空比如何变成转速1.1 电机转子为什么“听”PWM的话很多人一开始会困惑一件事我明明给电机的是一个个脉冲方波不是连续的直流电压电机怎么就能平稳转起来这里的关键在于电机本身就是一个天然的低通滤波器。直流电机在电气上可以简化成一个模型绕组电阻R、绕组电感L、以及一个反电动势源e(t)。反电动势的大小和转子转速成正比e Ke·ωKe是反电动势系数ω是角速度。当PWM高电平期间电源电压Vcc加在绕组上电流上升PWM低电平期间绕组通过续流二极管继续导通电感中的电流缓慢下降。因为机械系统的惯性远大于电气系统转速对电压的响应是缓慢的所以电机感知到的其实是PWM波形的“平均电压”。这个逻辑一定要想透PWM不是靠“脉冲冲击”驱动电机的而是靠“平均等效电压”驱动电机的。脉冲的频率越高、电感越大电流纹波越小电机运行越平稳。1.2 平均电压的计算占空比的本质占空比D定义为高电平时间Ton占整个周期T的比例D Ton / (Ton Toff) Ton / T那么施加在电机上的平均电压就是U_avg D × Vcc举个例子12V电源、占空比50%平均电压就是6V。但要注意这里说的是“平均电压”实际绕组上的电压是一个方波电流才是相对平滑的。电流纹波大小可以估算ΔI ≈ (Vcc × D × (1 - D)) / (f × L)这公式很实用后面选PWM频率时要用到它。f是PWM频率L是电机绕组电感。可以看出D越接近50%纹波越大频率越高纹波越小电感越大纹波越小。1.3 空载转速与电压的近似线性关系在空载情况下电机的稳态转速近似满足U_avg ≈ Ke × ω I × R空载电流很小I×R可以忽略所以转速基本和平均电压成正比。这就是为什么通过调节占空比就能调节转速——本质上你在调的是一台“数字化的可调直流电源”。不过这里的“线性”只是近似实际会有两个明显偏差一是占空比很小时电压不足以克服电机转子上的静摩擦力和齿槽力矩电机根本不转这段称为启动死区二是随着转速升高轴承摩擦和风阻变大转速会略低于线性预期。这些都是开环控制天然带有的误差来源后面实测部分会看到。2. H桥与驱动电路开环系统的“执行机构”2.1 为什么单管驱动不够用大多数MCU的GPIO引脚驱动能力只有几毫安到二十毫安直接带电机是不可能的。更基础的方案是单管驱动一个MOS管串联在电机和地之间PWM控制MOS管的通断。这个方案能做调速但有两个限制电机只能朝一个方向转并且当PWM关断时电机绕组的续流需要靠一个反向二极管释放否则电感和寄生电容会产生很高的尖峰电压打穿MOS管。如果项目要求电机正反转——比如小车前进后退、舵机正反转、云台俯仰——那就得上H桥。H桥由四个开关管组成电机接在桥臂中间。通过控制不同开关管组合可以让电流以两种方向流过电机从而实现正转、反转、刹车和滑行四种状态。2.2 H桥的四种工作状态与PWM调制方式用Q1/Q2表示左侧上下管Q3/Q4表示右侧上下管状态如下状态导通的开关管电机行为正转Q1 Q4电流正向流过电机反转Q2 Q3电流反向流过电机刹车Q1 Q3或Q2Q4电机两端短路急停滑行全部关断电机自由转动靠惯性开环调速最常用的调制方式是“单极性PWM”比如正转时Q4常通Q1由PWM波控制反转时反过来。这样每周期只有一个管子在做高频开关开关损耗相对小。还有“双极性PWM”方式对角线两个管子同时通断正转和反转交替出现转矩响应更快但开关损耗和电流纹波都更大一般用在需要高动态响应的伺服场合普通开环调速用不上。2.3 死区时间桥上最容易炸管的细节H桥最忌讳的是上下两个管子同时导通——这叫直通shoot-through相当于电源直接短路瞬间电流能把管子烧穿。解决方案就是插入死区时间在上下管切换时先关断导通的管子等待一小段时间再打开另一侧的管子。这个时间一般是几百纳秒到几微秒具体看MOS管的关断延迟和驱动芯片的能力。高级定时器比如STM32的TIM1/TIM8自带互补PWM输出和死区插入功能硬件上自动处理这个时序。如果用普通定时器做H桥就得在软件里手动加延时或者在驱动芯片上选带死区控制的专用栅极驱动IC。这块不做一定会交学费。2.4 常用驱动模块怎么选L298N、TB6612、AT8236对于学习和快速验证最常见的现成模块有三个我直接说结论模块最大电流压降适合场景L298N2A实测折半高约2V以上大扭矩教学演示效率无所谓TB66121.2A低约0.5V小型机器人3.3V逻辑兼容好AT82366A左右低稍大功率电机、电动工具验证L298N压降大、发热严重但胜在便宜大碗很多人入门都用它。TB6612的MOS管压降低得多同样电压下电机实际获得的电压更高转速也更高适合电池供电的移动平台。AT8236是国产驱动里比较能打的散热好适合驱动大一点的直流减速电机。如果自己画板子驱动级一般选半桥驱动芯片如IR2104、EG2104加外部MOS管或者直接选集成栅极驱动的智能半桥如DRV8870、A4950本质都是把H桥的“脑”逻辑控制和“肌肉”功率管分工处理好。3. PWM参数选型频率不是越高越好3.1 频率选择的三个约束PWM频率不是拍脑袋定的至少要同时满足三个约束第一频率要高于人耳可听范围或者避开机械共振点。频率落在20Hz到18kHz之间时电机绕组和外壳会发出刺耳的啸叫声很多项目就是因为PWM频率设在了16kHz附近结果整机都在吱吱叫。常见的做法是直接跳到20kHz以上进入超声波频段人耳就听不到了。第二频率要远高于电机的电气时间常数。电机绕组的电气时间常数τe L/R一般在几十微秒到几毫秒。PWM周期最好比τe小一个数量级以上这样电流纹波才足够小。举个例子电感1mH、内阻2Ωτe就是0.5ms那PWM周期至少得在50µs以内也就是频率要高于20kHz左右。第三频率要匹配MCU定时器的时钟分辨率。频率越高一个PWM周期内的计数器计数值越少占空比分辨率就越低。如果ARR只有499那占空比步进就是0.2%可能不够精细。3.2 占空比分辨率高频率的隐藏代价PWM占空比分辨率本质上由ARR值决定ARR越大可表示的占空比档位越多分辨率 1 / (ARR 1) × 100%以72MHz主频的STM32F103为例设置PSC0即计数器时钟72MHz。若输出20kHz则ARR1 72MHz / 20kHz 3600占空比精度约0.028%充裕。但如果你用主频只有几十MHz的Cortex-M0比如48MHz输出50kHz时ARR1 960精度约0.1%还是可用的。如果频率推到100kHzARR1 480占空比档位不到500级对精密调速就不太够了。所以高频PWM不是免费的你牺牲的是占空比精度。工程上一般按“频率尽量高、但占空比分辨率不低于0.1%~0.2%”来反推频率上限。3.3 实测对比不同频率下的表现差异我在一个12V直流减速电机上做过简单对比用示波器看电机电流波形数据大致如下PWM频率听觉感受电流纹波幅度电机温度噪声评价1kHz明显啸叫很大发热较快不可接受8kHz轻微啸叫中等温升正常勉强可用20kHz听不到较小温升正常推荐50kHz听不到更小温升正常对MCU资源要求高注意频率不是无限高就好。频率升高后MOS管每周期开关损耗增大驱动芯片的功耗也会上升而且MCU定时器中断配合ADC采样的时序会变紧张。20kHz到25kHz是大多数直流电机开环应用的一个甜点区。3.4 电流纹波公式如何指导选频回头看电流纹波公式ΔI ≈ (Vcc × D × (1 - D)) / (f × L)一辆12V供电的智能小车电机电感0.5mH占空比50%时纹波最大。如果频率选10kHz则ΔI ≈ (12 × 0.5 × 0.5) / (10×10³ × 0.5×10⁻³) 3 / 5 0.6A如果电机额定电流1A0.6A的纹波叠加上去就是1.3A的峰值对MOS管电流应力和电机换向器寿命都不友好。把频率提高到20kHz纹波直接减半到0.3A效果显著。这就是为什么我用频率计算公式而不是凭感觉选参数。4. STM32平台落地定时器配置、代码骨架和实测数据4.1 定时器选型和通道规划以STM32F103为例定时器资源大致分为三类TIM1/TIM8高级定时器支持互补PWM输出和硬件死区插入驱动H桥首选。TIM2~TIM5通用定时器支持4路独立PWM适合单电机调速或多路舵机控制。TIM6/TIM7基本定时器不带PWM输出只能做定时中断。开环控制最常用的其实就是TIM2/TIM3每路PWM占用一个通道。如果后面要加编码器测速编码器接口需要额外占用两个通道所以规划引脚时要把编码器接口和PWM通道分开免得后面引脚冲突。4.2 PWM输出配置一份最小可用的CubeMX/寄存器配置在STM32CubeMX里选择一个定时器的通道设置为PWM Generation CHx具体参数按照20kHz输出配置参数值计算依据Prescaler (PSC)7172MHz/(711) 1MHz计时频率Counter Period (ARR)491MHz/(491) 20kHzPulse0~50占空比 Pulse/50CH PolarityHigh高电平有效对应的HAL代码片段TIM_HandleTypeDef htim2; TIM_OC_InitTypeDef sConfigOC {0}; htim2.Instance TIM2; htim2.Init.Prescaler 71; htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 49; htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(htim2); sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 0; // 初始占空比0% sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim2, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1);运行中修改占空比不需要重新配置直接__HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, 25); // 占空比50%这个接口背后其实是往定时器的CCR寄存器里写值硬件会在下一个计数周期自动装载不会产生脉宽毛刺这是PWM调速必须依赖的机制——绝对不能写在GPIO电平的软件延时里模拟PWM。4.3 软件PWM控制周期与调速平滑度在51单片机上很多人用过软件延时翻转IO口生成PWM比如驱动WS2811 RGB灯。这种做法的优点是引脚随意、不依赖定时器外设缺点也非常明显软件PWM会阻塞CPU而且占空比调变时容易产生毛刺导致电机抖动。如果只是点个灯、驱动个蜂鸣器软件PWM没问题但做电机转速控制出现一个很长的异常高电平电机会突然顿挫严重时电流冲击过大还会损坏驱动管。如果MCU定时器资源确实紧张折中方案是“定时器中断计数器变量”。比如用1kHz定时中断中断里维护一个周期计数和一个比较值电平翻转逻辑放在中断里。这种方法频率上限一般在几kHz且CPU占用率会随着保持频率线性上升。所以结论很明确只要芯片有硬件PWM外设就优先用硬件PWM这是电机控制的基本素养。4.4 开环实测数据占空比与转速的真实曲线我在一个额定12V、空载转速2400RPM的直流减速电机上记录了一组数据电机无负载电源是稳压电源PWM频率设为20kHz占空比实测转速(RPM)理论平均电压(V)非线性偏差0%00—10%01.2启动死区不转15%901.8勉强开始转20%2102.4略低于线性30%5703.6基本接近线性50%10906.0基本接近线性80%18809.6略低于线性100%240012.0基准点有几个结论值得记下来第一10%以下是不转的这是静摩擦力和齿槽力矩导致的不是PWM过零问题。要让电机可靠启动多数情况下需要占空比跳到15%~20%以上。第二中段30%~80%曲线几乎线性这也是开环控制“够用”的范围。第三超过80%之后转速增长又慢下来因为转速越高机械损耗风阻、轴承摩擦占比越大电压更多地消耗在克服阻力上。这就是开环控制的基本特征你给定一个占空比电机会运行在某个转速上但这个转速到底是多少受负载、电源电压、温度影响很大。同一占空比空载和带载的转速可能差30%以上。理解这一点才算真正理解“开环”的含义。5. 开环控制的软肋摩擦死区、负载扰动、电源波动5.1 启动死区与静摩擦力前面实测里占空比10%电机不转这就是启动死区。原因是电机转子要克服静摩擦力和齿槽力矩才能开始运动而这个力矩对应的电流需要一定的电压才能建立起来。占空比太低平均电压不足以建立足够的启动电流。解决启动死区有几种工程手段启动阶段直接给一个较高的占空比“冲一下”转速建立后再回调到目标值。很多电动工具、风机启动时就是这么干的。用PWM频率调制低频时脉宽更宽电流峰值更大更容易克服静摩擦。但低频会带来噪音不推荐作为常规手段。如果对启动特性要求高就得放弃开环上编码器做转速闭环让控制器自动补偿死区。5.2 负载变化时的转速跌落开环控制最让新人不爽的一点程序里写死30%占空比空载时转速700RPM轮子一压到障碍物转速立刻掉到400RPM甚至直接堵转。原因不复杂根据电机稳态方程U_avg Ke·ω I·R负载增大时I增大I·R压降变大在U_avg不变的情况下Ke·ω必然减小转速就掉下来了。开环系统没有测速反馈控制器不知道转速跌了自然也不会修正占空比。如果项目需要恒速运行——比如循迹小车希望左右两轮始终同步、云台希望旋转速度恒定——那开环是做不到的。此时必须引入闭环用编码器或霍尔传感器测转速PID控制器根据转速误差调整占空比这也就是PID闭环控制电机转速的常规做法。5.3 电源电压波动开环最容易被忽视的问题电压波动对开环的影响比很多人想的大得多。理想12V供电是不存在的电池供电时满电13V、放电末端10V压降3V直接让平均电压偏差25%。同一个50%占空比满电时电机转速明显更高。这个问题的解决办法有几个层次系统层面选择带稳压的电源方案或者用DCDC把母线电压稳住。控制层面把电压归一化——用ADC实时采样母线电压Vbus算占空比时用目标电压除以实际电压得到一个修正后的占空比。最彻底的办法还是闭环转速闭环本身就能主动对抗电源扰动因为任何扰动最终都会反映到转速上PID会去修正。5.4 开环控制里的故障保护不闭环也要有底线“开环”指的是转速没有反馈调节但不代表可以不设防。PWM电机驱动里最基础的三重保护是过流保护、过温保护、欠压保护。过流保护可以在主回路串采样电阻将电流信号放大后输入MCU ADC一旦超过阈值立刻切断PWM输出。也可以用驱动芯片自带的电流检测引脚比如DRV8870的IPROPI引脚原理相同。欠压保护的目的是防止电池电压过低时电机强行启动导致电压塌陷。在许多锂电池供电的设备中欠压保护阈值通常设在单节3.0V左右多节串联则按比例计算。过温保护要看功率管和电机温度。MOS管的结温上限一般是125℃~150℃电机的绕组温升也很关键用手摸电机外壳超过70℃就应该考虑降额或者停机。需要特别注意的是PWM故障保护动作要直接作用于PWM输出而不是靠软件循环。把刹车逻辑放在定时器崩溃或MCU卡死的场景下就很难用了。所以更稳妥的方案是用硬件比较器检测过流信号信号直接硬连到PWM输出禁止引脚或驱动芯片的EN/FAULT引脚这样才能实现微秒级关断。6. 从开环到闭环速度PID的最简扩展思路6.1 开环是天梯的第一级不是终点标题是“P0PWM电机开环控制”P0意味着这是第一优先级任务但不代表做完就完了。在实际项目中开环跑通之后几乎一定会往闭环走区别只是走多远。最简单的闭环是速度闭环电机上装一个编码器MCU通过定时器的编码器模式读取转速PID控制器根据目标转速和实际转速的偏差计算PWM占空比。增量式PID的输出量就是PWM占空比的修正量和开环代码的衔接非常自然int speed_ctrl(int target_rpm, int current_rpm) { static int err_prev 0, err_integral 0; int err target_rpm - current_rpm; err_integral err; // 积分限幅防止“积分饱和” if (err_integral INTEGRAL_MAX) err_integral INTEGRAL_MAX; if (err_integral -INTEGRAL_MAX) err_integral -INTEGRAL_MAX; int output KP * err KI * err_integral KD * (err - err_prev); err_prev err; return output; // 加到当前PWM占空比上 }增量式PID和位置式PID最大的区别在于输出的是“增量”而不是“绝对占空比”这样做的好处是即使PID参数没调好输出也不会瞬间变化很大对机械系统的冲击更小。6.2 占空比限幅开环阶段就该养成的好习惯不管开环闭环PWM占空比输出都应该做限幅。限幅的直接目的有两个一是防止电机启动瞬间电流过大烧驱动二是防止PID积分饱和后输出超过100%。很多电机堵转电流是额定电流的5~10倍如果允许PID在错误状态下把占空比推到100%驱动芯片很可能直接过温。所以建议在代码里维护一个全局的PWM输出上下限变量比如最大占空比限制在90%并且响应过流信号后自动降回安全值。这个习惯到了做电流环、位置环的时候会更加重要。6.3 位置环、电流环后面的路怎么走速度闭环跑通之后再往上走就是位置环云台、机械臂关节里常用的位置闭环最外层位置PID中间层速度PID最内层电流PID形成串级结构。每一层都需要更快的控制周期和更好的系统建模但是底层的PWM输出、H桥驱动逻辑、死区配置、保护机制全都是从P0开环阶段打好的底子。回想我做过的几个项目凡是前期把开环平台的硬件保护和软件框架做扎实的后面上闭环基本就是水到渠成凡是急着跳步、开环都没调稳就去写PID的最后都会回头补硬件保护的课。PWM电机开环控制这个看似基础的P0任务其实是在给整个电机控制系统“打地基”——地基的深度决定了上层建筑的高度。
返回列表