ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PWM电机开环控制全解析:从定时器配置到驱动电路实战

PWM电机开环控制全解析:从定时器配置到驱动电路实战 先说个结论PWM电机开环控制很多教程把它当作入门三板斧之一但实际上这活儿真要干好牵扯到电机模型、H桥原理、定时器配置、死区设计坑一点都不少。我这次把它标记成P0倒不是因为它有多难而是因为它几乎是所有移动底盘、云台、风机项目的公共底座——这一层不夯实后面上闭环、上路径规划全得回来补课。这篇文章就围绕我做“PWM电机开环控制”这个任务的全过程展开把参数怎么定、电路怎么搭、代码怎么写、波形怎么测以及我踩过的几个比较隐蔽的坑一步不落地记录下来。适合正在做智能车、机器人底盘、水泵风机调速的同学参考也适合那些“PWM看着会、一上电机就懵”的嵌入式初学者。1. 项目概述为什么PWM电机开环控制值得认真对待1.1 一个P0任务背后的含义在项目排期里P0意味着“阻断性任务”不做完后续所有依赖它的工作全部卡住。电机开环控制就是典型的P0。你可能会想不就是给电机一个PWM波让它转吗能有多复杂但真正把它接到硬件上你会发现它横跨了三块硬知识信号是怎么产生的定时器/时钟树、信号是怎么放大驱动的功率电路、电机在这个信号下到底转多快电机模型。任何一个环节出问题电机要么不动要么转得跟抽风似的要么直接烧驱动。我这次的项目背景是给一台小型差速底盘做驱动基础验证电机是两颗额定电压12V的有刷直流减速电机控制板主控是STM32系列MCU。需求很直接通过PWM调节电机转速支持正反转切换预留测速接口方便后续升级闭环。1.2 开环控制和闭环控制的边界开环控制通俗讲就是“只发命令不看结果”。你给PWM占空比50%电机理论上应该达到半速但实际转速受负载、电压波动、温度等因素影响可能只有40%也可能有55%。开环控制不关心这个偏差反正转起来就行。那什么时候适合开环对转速精度要求不高的场合比如风机、水泵、玩具车、灯光亮度调节开环完全够用。但如果你要做的是一台需要精确走直线的机器人底盘或者云台需要保持绝对稳定那必须上闭环——编码器/霍尔传感器测速再用PID把实际转速拉回目标值。我这次做开环目的很纯粹先把“电机能转、能调速、能换向”这条路跑通验证硬件设计没问题再考虑加编码器闭环。所以项目里我特意预留了电机测速接口但控制逻辑先用开环占空比映射。1.3 电机模型是绕不开的底层很多人在做PWM电机控制时忽略了一个关键基础——电机的等效模型。直流有刷电机的电气模型可以简化成一个电阻串联一个电感再串联一个反电动势源。电阻R是电枢电阻电感L是电枢电感反电动势E和转速成正比。这个模型解释了PWM控制里两个特别重要的现象第一为什么直接给电机通恒定电压时电流很大——因为低速时反电动势小电流主要由电阻限制第二为什么PWM频率太低时电机会一顿一顿地转——因为电流纹波太大转矩波动明显。理解了这个RL模型后面定PWM频率、理解电流波形就都有依据了而不是靠瞎试。2. 硬件方案选型从PWM波到电机转起来2.1 信号怎么来MCU定时器生成PWMPWM信号本质上就是“一会儿高、一会儿低”的方波高电平占比叫占空比。MCU产生PWM主要有两种方式一是用GPIO配合软件延时翻转电平二是用硬件定时器输出。我的建议是只要芯片支持定时器PWM输出就绝对不要用软件模拟。软件模拟PWM有几个硬伤一是CPU被完全占死没法干别的二是频率和占空比精度受中断抖动影响波形不干净三是做多路电机控制时相位关系很难精确控制。硬件定时器PWM的原理其实不复杂。定时器内部有一个计数器从0往上计数到某个值叫自动重载值ARR然后重新从0开始。另外有一个比较寄存器CCR当计数值小于CCR时输出高电平大于等于CCR时输出低电平。这样CCR/ARR就是占空比而ARR决定了PWM频率。以我用的STM32为例定时器时钟是72MHzF103系列。如果你想输出20kHz的PWM计算方法是先对72MHz做预分频假设分频系数设成72得到1MHz的计数时钟那么ARR 1MHz / 20kHz - 1 49也就是计数器从0数到49正好50个计数周期对应20kHz。CCR设成25就是50%占空比。这个“先分频确定频率再比较确定占空比”的思路是所有定时器PWM配置的核心。2.2 驱动电路为什么不能把GPIO直接接到电机新手最容易踩的坑之一就是试图用MCU的引脚直接驱动电机。从原理上说MCU引脚高电平输出时的电流能力通常只有几毫安到二十毫安具体看芯片手册而一个普通直流电机启动瞬间电流可以轻松超过1A。硬接上去的结果就是电压被拉垮——MCU直接复位引脚烧毁——IO口冒烟或者电磁干扰导致系统死机。正确的做法是让MCU引脚只负责输出控制信号驱动电路负责放大电流。最简单的驱动方式是“一个MOS管一个续流二极管”组成的低边开关。MOS管栅极接PWM信号源极接地漏极接电机一端电机另一端接电源正极。PWM高电平时MOS管导通电流流过电机低电平时关断电机电感电流通过续流二极管维持通路。这个电路只能单向调速不能换向。如果想要正反转就得用“全桥”结构也就是四个开关管组成H桥。左上一组对角导通时电机正转右上一组对角导通时反转上下同时导通就是短路这是绝对禁止的状态。H桥看着简单实际调试时死区、导通压降、寄生参数都是细节新手建议先用集成驱动芯片。2.3 常见驱动方案对比做电机驱动有几种常见路线我根据自己的经验把它们的优缺点列一下。方案代表器件优点缺点适用场景分立MOS管H桥IR2104 MOSFET电流大、可定制、成本低调试复杂、需要自举电容等外围大功率电机、定制驱动板集成电机驱动芯片TB6612、AT8236、DRV8833外围简单、自带保护、体积小电流有限制、散热能力一般小功率机器人、小车老牌驱动模块L298N资料多、耐造、容易买到压降大、发热严重、效率低教学实验、简单DIY我这次选用的是TB6612FNG芯片。原因很直接第一它工作在12V电压下很稳定持续输出电流1.2A峰值3A带动我这种小型减速电机绰绰有余第二它内部集成了两个H桥一个芯片就能同时控制两个电机正好匹配差速底盘的驱动需求第三它的逻辑接口电平兼容3.3VSTM32可以直接连接不需要额外电平转换。需要注意的是TB6612的电源引脚要接电机电源VM这里接12V和逻辑电源VCC接3.3V或5V两路。AO3400之类的小MOS管如果被搜到通常是用在信号电平转换或小功率开关场合做电机主驱动会偏吃力所以我不建议在大电流场景用它直接驱动电机。3. PWM四件套参数频率、占空比、死区与对齐模式3.1 PWM频率选择背后的数学PWM频率的选择是开环控制里最需要动脑子的一件事。频率太低电机电流纹波大转矩波动明显电机会发出“嗡嗡”声甚至一顿一顿地转动频率太高开关损耗增大驱动芯片和MOS管发热严重而且MCU定时器的分辨率也会被压缩。那到底怎么选这就要回到前面说的RL电机模型。电机的电感L和电阻R构成一个低通滤波器时间常数τ L/R。PWM频率至少要远高于1/τ电流才能被滤得比较平滑。举个例子一个典型的小型直流电机电枢电感约100微亨电枢电阻约2欧姆那么τ 100μH / 2Ω 50微秒对应的截止频率约3.2kHz。如果PWM频率只有几百赫兹电流就会明显波动。但又不能无脑把频率升到很高。我从实际测试对比来看20kHz左右是一个兼顾噪声、效率和纹波的甜点区间。原因有两点一是20kHz已经超出人耳可听范围能避免刺耳的“啸叫”声二是对于大多数小型直流电机这个频率下的电流纹波已经控制在可以接受的范围同时MOS管的开关损耗也不至于太大。如果你的项目对噪声不敏感或者电机电感特别小可以适当降到10kHz如果用的是航模无刷电机配的电调那又是另一套逻辑了。3.2 占空比就是平均电压PWM控制电机转速的数学本质很简单电机的平均供电电压等于电源电压乘以占空比。比如12V电源占空比50%平均电压就是6V。对应到转速就是空载转速的50%左右。但这里有两件事要特别注意。第一电机存在“死区电压”或者说“启动电压”。由于电刷压降和静摩擦的存在占空比低于某个阈值我实测大概8%到10%时电机根本不会转动只是发出微弱的电流声。所以调速范围不要从0%线性映射到100%建议软件里做一个最低启动占空比的补偿。第二PWM波的峰值电压始终是12V只是平均电压变了。这意味着电机的绝缘和驱动芯片的耐压都要按12V甚至更高设计而不是按平均电压设计。我这次实测下来在12V供电下占空比30%到85%这个区间转速基本和占空比保持线性关系低于30%时转速低、转矩小稍微带点负载就转不动高于85%时接近全速但调速空间有限。所以实际使用中我通常把工作区间设定在40%到80%。3.3 死区不是可有可无的前面提到H桥上下桥臂不能同时导通否则电源直接短路。那怎么保证不同时导通呢靠的就是“死区时间”——在切换上下管状态时故意插入一小段两边都关闭的时间。我这次用的是TB6612集成芯片它内部已经处理了死区不需要自己在寄存器里配。但如果你用STM32的高级定时器TIM1、TIM8配合外部MOS管搭建H桥就必须手动配置死区时间。死区时间太短关断慢的管子还没完全关断开通快的管子已经开始导通了还是会直通死区时间太长电机电流在死区期间只能靠续流二极管走会增加额外损耗。死区时间怎么定首先查MOS管数据手册找到关断延迟时间td(off)和下降时间tf死区时间至少大于这两者之和再留2到3倍裕量。我常用的经验值是1到2微秒对大多数中小功率MOS管都够用。STM32高级定时器里死区通过BDTR寄存器配置以MCU时钟为基准72MHz下死区定时器每计数一次约13.9纳秒要配1微秒死区就写入约72。3.4 中心对齐模式和边沿对齐模式怎么选STM32定时器有两种常见的PWM对齐模式这直接和搜索结果里反复出现的“pwm 中心对齐”“tc pwm中心对称”相关。边沿对齐模式Edge-aligned就是计数器从0向上数到ARR然后回0比较输出翻转一次中心对齐模式Center-aligned是计数器从0先向上数到ARR再向下数回0在一个周期内计数两次比较匹配两次输出波形关于周期中点对称。中心对齐模式最大的优势是PWM波形对称性更好谐波含量更低电流纹波更小。还有一个重要应用场景是在PWM中心点触发ADC采样可以采到电流纹波的平均值这对以后做电流闭环非常关键。缺点是它的PWM频率是边沿对齐的一半同样计数时钟下或者换个说法要达到同样的频率计数器时钟要翻倍。在我这个开环项目里其实边沿对齐就够用了。但我最后还是用了中心对齐模式。原因很简单后续这个底盘要升级闭环电流采样中心对齐模式下ADC采样时机好安排提前把定时器配置好省得到时候推翻重来。做技术选型时往未来多看一眼往往能省很多返工的力气。4. 开环控制逻辑的软件实现4.1 初始化定时器输出PWM硬件方案定了软件层面以STM32 HAL库为例看看怎么配置定时器输出PWM。首先要确定用哪个定时器、哪个通道我给左电机分配TIM2的CH1右电机分配TIM2的CH2。初始化过程分三步先配置定时器时基再配置PWM通道参数最后启动PWM输出。TIM_HandleTypeDef htim2; TIM_OC_InitTypeDef sConfigOC; // 1. 时基配置 htim2.Instance TIM2; htim2.Init.Prescaler 72 - 1; // 72MHz / 72 1MHz 计数时钟 htim2.Init.CounterMode TIM_COUNTERMODE_CENTERALIGNED1; // 中心对齐模式 htim2.Init.Period 50 - 1; // 1MHz / 50 20kHz PWM频率 htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE; HAL_TIM_PWM_Init(htim2); // 2. 配置PWM通道 sConfigOC.OCMode TIM_OCMODE_PWM1; sConfigOC.Pulse 25; // 初始占空比50%25/50 sConfigOC.OCPolarity TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(htim2, sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_ConfigChannel(htim2, sConfigOC, TIM_CHANNEL_2); // 3. 启动PWM HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1); HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_2);这里Prescaler和Period的计算可以套用公式PWM频率 定时器时钟 / (Prescaler × (Period 1))。72MHz / (72 × 50) 20kHz。要注意Period寄存器是零基的我们需要50个计数周期所以填49。在实际项目中我习惯把这些计算封装成一个宏或者函数输入目标频率和占空比自动计算Prescaler和ARR。尤其是Prescaler并不是只能选72它和Period是互相配合的选得太小会限制频率调节范围选得太大又降低分辨率要按项目需要的频率范围折中。4.2 软启动和软停止这是我从实际测试里学到的最重要的一课。如果程序一上电就直接给电机输出80%占空比电机的启动电流会非常大我实测瞬间可以到正常工作电流的5倍以上。对电源是考验对驱动芯片也是考验。解决办法是“软启动”以一定的时间间隔把占空比从0逐步增加到目标值。比如目标占空比60%每10毫秒增加1%600毫秒内平稳到达。这一方面限制了冲击电流另一方面也避免了底盘猛地蹿出去。void motor_soft_start(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t target) { uint16_t duty 0; while (duty target) { duty 1; __HAL_TIM_SET_COMPARE(htim, channel, duty); HAL_Delay(10); // 10ms步进 } }对应的停止时也应该软停止。突然把占空比归零电机负载瞬间卸掉底盘会因为惯性向前顿一下。软停止是逐步减小占空比让电机平滑减速。在实际的底盘控制里这个“斜坡加减速”逻辑会进一步抽象成速度规划模块配合编码器做闭环后效果会更好。4.3 正反转与刹车逻辑TB6612模块的控制逻辑很清晰每个通道有两个输入引脚AIN1、AIN2对应输出AO1、AO2。AIN1为高、AIN2为低时电机正转反之反转两者同为低时输出高阻电机自由滑行两者同为高时输出刹车。对应到代码里PWM是独立控制的。只需要注意一点在改变方向之前一定要先把PWM占空比降到0等待几十毫秒再切换方向引脚。如果直接反转电机会经历一个电流尖峰非常大的反向制动过程对驱动芯片的冲击和机械冲击都不小。我这里用两个GPIO控制方向PWM控制速度。当需要正转时设置GPIO_A高、GPIO_B低然后输出PWM反转时反过来。需要急停时直接把两个方向引脚都拉高进入刹车状态。自由滑行则是把两个引脚都拉低。4.4 简单速度斜坡与保护开环控制虽然没有反馈但基本的保护逻辑不能少。我这里做了三件事第一占空比限幅。软件里规定最大值不超过90%留出余量防止电源电压被拉垮。第二电流保护。在电源回路串入采样电阻通过ADC实时监测电流如果连续一段时间超过阈值立刻封锁PWM输出并点亮故障灯。这个在开环项目里看似可选但实际非常有价值。有一次我调试时电机堵转30毫秒内电流飙到3A以上如果没有这层保护驱动芯片大概率要烧。第三启动判别。给PWM后延时一小段时间如果电机没有产生反电动势可以通过检测电流是否异常持续偏高判断就认为电机卡死需要报警。这在自动设备里很有用。5. 实测结果与调试记录5.1 示波器观察到的真实波形上电之后第一件事不是看电机转不转而是拿示波器看PWM波形。我首先要确认的是频率和占空比是否符合预期。把探头夹在TB6612的PWM输入引脚上能看到标准的方法波频率20kHz占空比取决于设定值高电平3.3V。这一步正常说明定时器配置没有问题。然后把探头换到电机两端这里看到的波形会比较“脏”——不再是干净的方波而是带着明显圆角的波形。这是因为电机的电感和电阻构成了低通滤波器把方波的高频分量滤掉了一部分。这个现象是正常的也正因为如此电机的实际电压波形是平缓的脉动而不是硬生生的开关波形。如果这里出现异常尖峰往往是续流回路有问题或者布线寄生电感太大。5.2 占空比与转速实测我用光电测速传感器读取电机自带的码盘反馈记录不同占空比下的实际转速。实测数据大致是这样的占空比空载转速RPM现象10%0电机不动有轻微电流声20%230能缓慢转动转矩很小30%410稳定转动50%780线性区间噪声正常70%1150线性区间90%1490接近全速噪声变大可以看到转速和占空比在30%到90%之间基本是线性关系。低于30%存在明显的死区这是电刷压降和静摩擦共同作用的结果。这个线性关系就是开环控制的底气虽然没有闭环精度但至少能做出一个可预测的速度映射表。5.3 频率对噪声和温升的影响我还专门对比了不同PWM频率下的表现。用1kHz驱动时电机明显发出低沉的“嗡嗡”声同时转速波动肉眼可见用10kHz时噪声明显减小但依然能听到轻微啸叫用20kHz时耳朵基本听不到电机电磁噪声只剩下轴承的机械声和风噪。温升方面20kHz下驱动芯片表面温度比10kHz时高大概5到8摄氏度这是开关损耗增加的结果。所以如果散热条件很差又不介意噪声用10kHz也没问题但从整体体验来看20kHz是最平衡的点。如果后续功率等级提升到数百瓦级别开关损耗会变得很可观那时候可能要考虑用更低频率或者换用更高性能的驱动方案。6. 常见问题与排查技巧实录6.1 问题速查表做电机控制遇到问题第一步不要急着改代码先判断问题在哪个环节。我自己整理了一个排查顺序电源 → 信号 → 驱动 → 电机 → 机械。问题现象可能原因排查方法电机完全不转无电流声电源没通/保险烧/使能引脚未拉高万用表量VM引脚电压检查STBY引脚电机有电流声但不转占空比低于死区阈值提高最小占空比到10%以上电机能转但转速忽快忽慢PWM频率太低 / 电源内阻过大示波器看电机两端波形检查电源带载能力电机只能单方向转方向引脚电平配置错误 / H桥一路损坏交换方向引脚测试确认另一路是否正常一启动就复位或重启电源电压被拉垮检查电源功率加装大电容驱动芯片异常发热PWM频率过高 / 负载过大 / 散热不良降低频率测量工作电流检查散热正反转切换时电压尖峰缺少死区或续流回路不良检查驱动芯片死区配置确认续流二极管6.2 几个值得说一说的排查案例第一个案例是电机“转了一下就停”。当时我查了很久的代码最后发现是电源的问题。12V电源适配器的输出能力只有1A而电机启动瞬间电流超过2A直接把电源电压拉到了7V以下MCU检测到电压跌落触发了内部BOD复位。解决办法是换用功率余量更大的电源同时在电机电源输入处加了470微法和100纳法两级电容问题立刻消失。第二个案例是双电机转速不一致。左右两个电机即使给同样的PWM占空比空载转速也有5%左右的差异。这在开环控制里很常见因为电机的制造公差和负载差异会导致相同电压下转速不同。解决思路有两个一是接受这个误差在软件里做静态补偿二是上编码器闭环让PID来动态修正。我验证了闭环效果后果断把系统升级成了闭环方案。第三个案例比较隐蔽PWM输出口冲突。我最初把电机PWM和调试串口的TX引脚复用了一个定时器的不同通道调试时没问题但只要一上电机串口数据就乱码。原因是为PWM生成的定时器中断优先级设置不当干扰了串口通信时序。最终我把PWM和串口分配到互不干扰的定时器上问题才彻底解决。6.3 我的几个独家避坑技巧搞电机控制这些年有几个小经验是非常规文档里不会写的但实际帮了我很多。第一所有的PWM控制代码在硬件上电之前先把周期和占空比初始化为安全值占空比0等主程序初始化完成后再输出。这样可以防止MCU刚上电瞬间引脚不定态时电机乱转。第二驱动芯片的逻辑电源和电机电源一定要分开走线在PCB布局上电机电源线尽量短、尽量粗地线采用单点接地。如果两者共用地线太长环路电感会在高电流变化时产生地弹干扰逻辑信号。第三电机和驱动板之间加一个“TVS管”或者一个大电容可以有效吸收电机换向产生的尖峰脉冲。有一次我在调试时发现驱动芯片总是周期性损坏最后查明白是电机是感性负载关断瞬间产生了超过30V的反向尖峰直接击穿了芯片内部的MOS管。加上TVS管之后这个故障再也没出现过。我个人在实际操作中的体会是PWM电机开环控制这个任务代码量虽然不大但它考验的是对“信号链”的完整理解——从寄存器配置到定时器时钟树从驱动芯片到电机本体的感性负载特性再到电源的瞬态响应。每一个环节都不算难但串在一起任何一个薄弱点都会让整条链路失效。做这类基础控制任务最好的态度就是沉下心一个环节一个环节地验证把波形看明白把参数算清楚把保护做扎实。这一层地基打牢了后面不管是上PID闭环、加编码器测速还是扩展到无刷电机FOC控制你都有底气说一句“我知道底下的原理是什么”。
返回列表