ARTICLE DETAIL

资讯详情

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

PWM电机开环控制实战:从H桥驱动到STM32调速全解析

PWM电机开环控制实战:从H桥驱动到STM32调速全解析 做嵌入式的小伙伴应该都接过类似的需求——项目一上来第一个任务就是用PWM驱动电机转起来而且要求先开环跑通不做闭环。这篇博文我就是想把“P0PWM电机开环控制”这个项目从方案选型到代码实现、再到调试踩坑的完整过程整理出来。这里面没什么高深的东西但每一步都有值得注意的细节把这些细节讲清楚比我列一段代码更有价值。我假设你可能在单片机、树莓派、或者任何能输出方波的平台上做这个任务所以下面内容会以STM32为主讲软硬件实现其他平台的坑我尽量在对应章节带一句。适合谁看正要接手电机驱动任务的初学者或者已经能让电机转起来但总遇到电流噪声、发热、转速不稳这些问题的人这篇文章应该能帮你省一点时间。1. 项目拆解先把“P0任务”想清楚1.1 这个任务到底在解决什么问题“P0”这个命名在研发任务分解里通常指最高优先级、需要最优先打通的核心任务。放到电机控制这个场景里P0指的就是“用最简单的办法让电机可控地转起来”。别小看这句话它隐含了两个验收条件第一是转速可调第二是方向可控如果需要正反转的话而这两件事都建立在稳定的PWM输出上。先把问题树画出来。电机要转需要三样东西可控的输出电压、足够的驱动电流、正确的控制时序。PWM负责第一样驱动电路负责第二样GPIO和定时器负责第三样。开环控制的意思是你只给出“期望值”系统不关心实际转速也不反馈修正。比如你设定50%占空比让电机以某个速度转动但实际电池电压掉了一点、负载力矩变大了一点转速就会偏离预期系统不会自动纠正——这就是开环。所以这个P0任务真正的交付物不只是“电机在转”而是一套可以扩展的电机驱动基础链路控制器输出可控的PWM信号驱动芯片把信号放大成功率输出电机两端得到平均电压可调的方波电压最后表现为转速随占空比变化。我们要把这条链路每一环都验证清楚后面做PID闭环、做无刷电机控制才有依托。1.2 开环和闭环的区别以及为什么先做开环很多人一接触电机控制就在问怎么不用PID我的回答是先把开环做扎实再谈闭环。开环和闭环的本质区别在于有没有“传感器反馈”这个环节。开环直接把控制量占空比送给执行器闭环则需要编码器或霍尔传感器把实际转速测回来和期望值做差再通过PID之类的算法修正输出。先做开环有三个非常现实的原因。第一个原因是验证硬件链路电机、驱动器、电源、PWM输出哪一环有问题开环状态下最容易定位。第二个原因是建立基线只有先知道“占空比50%大致对应多少转/分”你才知道闭环PID的初始参数该从哪里起步。第三个原因是控制在手很多实际场景比如风扇、水泵、模型舵机根本不需要精确转速开环PWM就能满足需求。在这个阶段我建议你把所有调试信息打印出来尤其是“设定占空比”和“实际电流”这两个值。别急着上传感器先用万用表测电机两端平均电压看看和理论值差多少这会让你对整条链路的损耗有直观认识。1.3 方案选型从驱动芯片到控制器的取舍在动手前要把硬件选型想清楚。控制器可以是STM32、树莓派、51、ESP32任意一种驱动器则要从“用分立元件搭”和“用集成驱动芯片”里选。我的建议是如果你只是想通过这个项目理解原理那可以用分立元件搭H桥四个MOS管加四个续流二极管虽然调试起来麻烦但原理会吃得非常透。如果你的目标是把产品做出来或者快速验证方案直接上集成驱动芯片比如TB6612、L298N、DRV8870、A4950。这些芯片内部集成了H桥逻辑和功率MOSFET外围只需要几个电容电阻省去搭桥和保护电路的麻烦。我最早做过一个用四个MOS管自己搭H桥的项目调试死区、防止上下桥臂直通烧管子就花了两天后来换TB6612半小时就搞定。控制器平台方面STM32通用性最强、资料最丰富也是我这次用的平台。树莓派更适合做Linux上位机联动控制输出PWM记得用硬件PWM引脚而不是软PWM。51单片机做低速小电流应用完全够但要考虑定时器资源是否宽裕。选型这件事没有标准答案关键看你的成品形态和团队技术栈。2. PWM控制电机的核心原理2.1 PWM的本质是“等效平均电压”先打个比方。PWM就像快速开关的水龙头你以非常快的频率把水阀开一下关一下虽然水流是一股一股的但接水的水桶里水面上升的速度取决于开阀时间占总时间的比例。这里“开阀时间占的比例”就是占空比用百分比或0~1之间的数表示。对于直流有刷电机情况类似。电机的机械惯量很大电气响应速度远慢于PWM开关频率所以电机并不会跟着每一个脉冲一顿一顿地转而是感受到一个“平均电压”。忽略驱动管压降时平均电压等于电源电压乘以占空比V_avg Vcc × D其中D就是占空比取值范围0~1。如果电源电压是12V、占空比50%那电机感受到的平均电压就是6V。注意这是理想情况实际因为MOS管导通压降、线损等会略低一点但这不影响理解。要严格解释这件事得引入电机模型。直流有刷电机的电枢回路可以简化成一个电阻R串联一个电感L再串一个反电动势源E。反电动势和转速成正比E Ke × ωKe是电机常数ω是角速度。稳态时平均电压有一部分落在电阻上I×R剩下的都用来平衡反电动势所以转速基本正比于(V_avg - I×R) / Ke。这就是为什么占空比变大转速变高而负载变大电流上升、电阻压降增大后转速会掉——开环系统的固有问题。2.2 占空比与转速、扭矩的关系占空比决定了平均电压平均电压决定了可用的“电压余量”再减去电阻压降才是反电动势所以占空比不是和转速严格线性对应的。空载情况下摩擦很小电流很小转速约等于V_avg/Ke基本线性。带载之后电流增大Ra乘以电流的压降会把转速拉下来所以你会发现同样的占空比空载转得快、带载转得慢。扭矩和电流直接相关T Kt × IKt是扭矩常数I是电枢电流。占空比提高平均电压提高电流会先短暂增大然后随着转速上升、反电动势增加而回落到稳态值。这个过程的时间常数由机械惯量和阻尼决定通常几十毫秒到几百毫秒。从控制角度看占空比就是系统的“油门”输入。你给大油门它加速给油门它减速。但电机的速度状态量由负载力矩、摩擦力、转动惯量共同决定这是后续闭环要管的事情。开环控制能做到的是给定一个占空比得到一个“大致稳定”的转速并且让你能通过调整占空比来调整转速。2.3 频率怎么选太高太低都不行PWM频率是另一个关键参数而且很多人在这里栽过跟头。频率太低时电机能感知到每一个脉冲会表现为顿挫、抖动、啸叫电流纹波也非常大换向器火花变大。频率太高时开关损耗随频率线性增长MOS管发热严重驱动芯片温度飙升但电机转速并不会因此变好。这里有两条经验线。第一避开人耳最敏感的2kHz到5kHz频段否则电机会发出很刺耳的尖叫声。第二电流纹波大小由公式ΔI ≈ (Vcc × D × (1-D)) / (f × L)决定L是电机电枢电感所以频率越高纹波越小但频率上升到一定值后收益递减开关损耗反而成了主要矛盾。实际项目里我通常把有刷直流电机的PWM频率选在10kHz到20kHz。10kHz刚好在人耳听觉上限附近很多电机已经听不到明显噪声20kHz超过多数人的听觉范围噪声更小但要注意驱动芯片的开关损耗。如果是小功率空心杯电机、玩具电机频率可以选20kHz如果是减速电机或者力矩电机电感较大、响应较慢8kHz到10kHz完全够用。频率相关的另一个细节是PID控制周期。千万别把PID的运算频率和PWM频率混为一谈速度环通常运行在几百Hz到1kHz就足够快PWM频率却要高得多。我之前见过一个新人把PWM频率设成100Hz电机抖得像跳舞然后一个劲调PID参数其实问题根本不在控制算法上。3. 硬件电路与驱动方案落地3.1 H桥电路原理正反转的基础要驱动有刷电机正反转单路推挽输出做不到得用H桥。所谓H桥就是四个开关管接成“H”形的电路电机接在H的横梁上。左上和右下导通时电机正转右上和左下导通时电机反转四管全断时电机自由停车惯性滑行上下同时导通就是灾难——电源直接短路俗称“直通”或“shoot-through”。这就是PWM死区的来历。在H桥实际驱动中同侧上下管不能同时导通切换时需要先关断一个管子等待一段时间死区时间后再开通另一个。死区时间太短管子开关特性差异会导致瞬间直通太长则输出波形畸变、有效电压下降。具体数值要看管子栅极电荷和驱动能力一般做在几百纳秒到几微秒像英飞凌TC3xx的CCU6单元做BLDC控制时死区配置是必须专门调的一个参数。PWM信号叠加在H桥上就构成了完整的电机调速系统PWM控制平均电压调速桥臂方向控制正反转。两者配合可以做出正转加速、正转减速、反转加速、反转减速四种状态还能通过“制动”状态下桥双管导通电机端短接快速停转。3.2 常见驱动模块对比怎么选市面上常见的电机驱动模块我按使用场景列了一个对比表。模块/芯片最大电流导通压降逻辑电压适用场景注意点L298N2A峰值3A2V左右5V教学实验压降大发热严重TB66121.2A峰值3.2A0.5V左右2.7V~5.5V小型机器人性价比高常用首选DRV88703.6A约0.5V6.5V~45V汽车级、中功率内部集成电流采样A49502A约0.6V6V~32V工业中压逻辑电平兼容性好分立MOS管H桥看管子取决于MOS管需自举电路大功率定制调试复杂TB6612是当前大多数智能小车项目的首选导通压降低、体积小、逻辑电平宽即便模块标称电流不如L298N高实际表现却好很多。L298N内部用的是BJT达林顿管压降有2V左右12V电源实际到电机两端只剩10V这个损耗非常可观。换成TB6612后我实测过同样12V供电、同样电机转速明显高出一截原因就是导通压降超低。所以选驱动时别只看电流指标导通压降直接决定了有效输出电压这个参数在低电压应用里比如3.7V锂电池供电尤其致命。3.3 电源与保护电路的设计要点电机启动瞬间电流是额定电流的好几倍这个特性很多人容易忽略。堵转电流甚至可以达到额定电流的5~10倍如果电源容量不够电压会被瞬间拉低轻则转速掉下去重则单片机复位、驱动芯片进入欠压保护。所以选电源时峰值电流能力至少要按电机的堵转电流来留余量而不是按额定电流。我自己常用的做法是三层应对。第一层大电容电机电源端并联一个470uF~2200uF的电解电容再加一个0.1uF高频瓷片电容吸收开关瞬间的尖峰电流。第二层续流H桥每个开关管旁边都有一个续流二极管接通感性能量回路用集成驱动芯片时一般内置用分立MOS管时必须自己加大电流快恢复二极管。第三层隔离如果单片机和电机共用一个电源最好在逻辑电源和功率电源之间加磁珠或LC滤波避免电机电流突变产生的毛刺干扰MCU。另外有一个实操细节驱动模块的地线必须和单片机地线连在一起但功率地路径要宽、要短尽量和逻辑地分开走最后单点连接。否则功率地的电压波动会灌进MCU的地参考导致AD采样偏移甚至复位。4. 软件实现与参数配置4.1 基于STM32的定时器PWM配置以STM32F103系列为例用TIM2输出一路PWM。这里先讲原理再给配置避免你搬了代码却不知道每个参数在干什么。PWM频率由定时器时钟、预分频器PSC和自动重载值ARR共同决定。假设APB1定时器时钟为72MHz目标PWM频率是20kHz可以这么算先分频到1MHz即PSC 72 - 1 71然后ARR 1MHz / 20kHz 50也就是ARR 49。这样定时器以1MHz频率递增计数从0数到49周期20us正好20kHz。PWM输出的比较值CCR则决定了占空比Duty CCR / (ARR 1)。注意是ARR1因为计数器从0开始计。设置CCR 25占空比就是50%CCR 10占空比约20%。这个换算关系在写调速函数时要用对否则转速会和你预期的对不上。CubeMX里的配置思路是选择TIM2Clock Source设为Internal ClockChannel1设为PWM Generation CH1然后设置Prescaler 71Counter Period 49Pulse就是初始CCR写25输出极性选High。其他高级设置里如果用了H桥且是分立器件搭的需要开Break功能和死区时间寄存器用集成驱动芯片时死区通常由芯片内部处理不需要配置。4.2 代码示例从占空比计算到转速控制生成工程后核心代码很短。启动PWM输出HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_1);然后写一个调速接口用百分数作为输入void Motor_SetDuty(TIM_HandleTypeDef *htim, uint32_t channel, uint8_t duty) { if (duty 100) duty 100; uint32_t arr __HAL_TIM_GET_AUTORELOAD(htim); uint32_t ccr (arr 1) * duty / 100; __HAL_TIM_SET_COMPARE(htim, channel, ccr); }这个函数的好处是不管你ARR改成多少占空比输入都是0~100的整数不用每次重新换算CCR。如果你要控制正反转同时还需要两个方向引脚比如TB6612模块的AIN1和AIN2#define MOTOR_FORWARD GPIO_PIN_SET #define MOTOR_BACKWARD GPIO_PIN_RESET void Motor_SetDirection(GPIO_TypeDef *port, uint16_t pin1, uint16_t pin2, BitAction dir) { HAL_GPIO_WritePin(port, pin1, dir); HAL_GPIO_WritePin(port, pin2, (BitAction)!dir); }实际运行时我习惯把“停”和“零速”区分开占空比0是电机两端电压为0电机处于滑行状态如果想让电机尽快停住用刹车模式——对TB6612来说就是把两个输入引脚同时拉低让电机两端短接利用反电动势快速制动。4.3 其他平台实现树莓派、51、ESP32树莓派做PWM输出时最省事的是用硬件PWM引脚。树莓派有PWM0和PWM1两组硬件PWM在BCM编号下对应GPIO12、GPIO13PWM0和GPIO18、GPIO19PWM1。如果你用RPi.GPIO库的软件PWM也是可以的但要注意它依赖系统调度高频率下抖动很大驱动舵机或电机时可能力矩不稳。更好的选择是使用支持硬件PWM的库比如libgpiod或Python的gpiozero底层或者直接写设备树把引脚复用成PWM功能。51单片机没有硬件PWM外设STC系列新出的部分型号有增强PWM通常用定时器中断来软件翻转IO。这种方式的CPU开销比较高但如果控制一台小电机周期1ms中断一次在中断里翻转引脚占空比通过查表或比较计数器实现是完全可以用的。舵机控制的20ms周期50Hz PWM用这种方法做也毫无压力。ESP32则方便很多LEDC外设专为PWM设计可以配置多路不同频率、不同占空比的输出而且内部有硬件呼吸灯模式做LED渐变、RGB调色非常顺手。驱动电机时记得用LEDC的定时器精度调高一点占空比分辨率才够。不管什么平台有一个通病值得提醒软件延时做PWM输出时一旦被中断干扰波形会产生毛刺驱动电路会捕捉到异常占空比轻则转速抖动重则造成过流。所以能用硬件外设生成PWM就绝不用软件模拟这是我在多个平台上踩出来的经验。5. 调试过程中的常见问题与排查5.1 电机不转、抖动、尖叫先按顺序排查电机一上电不转最恐怖的情况是驱动芯片冒烟但大多数时候只是某个逻辑条件没满足。我的排查顺序是这样的。第一步查电源。电机电源电压是否到位电机启动电流瞬间很大用万用表测电压可能看到电压被拉到很低甚至为0这多半是电源限流或电池内阻过大。第二步查使能脚。很多驱动芯片需要把STBY待机引脚拉高才会工作有些模块的使能脚悬空时不输出这里最容易漏。第三步查PWM信号。用示波器或逻辑分析仪看PWM输出引脚确认频率、占空比是否符合预期。如果没有示波器可以写个循环让占空比从0慢慢上升到100同时用万用表测电机两端电压看是否线性上升。电机抖动或者发出刺耳尖叫基本是PWM频率设置得太低电机在跟脉冲走。这时候先把频率提到10kHz以上再看问题是否消失。同时检查一下占空比更新是不是平滑变化如果程序里直接跳很大的占空比电机扭矩突变也会引起机械振荡。5.2 驱动芯片发热、电流纹波大是怎么回事发热问题要分两种情况。一种是小负载正常工作时发热明显多半是PWM频率过高导致开关损耗过大或者驱动芯片压降太大比如L298N换低导通压降的驱动芯片最直接。另一种是大功率输出时发热这属于散热设计问题加散热片、增强空气流通、或者降低一点PWM频率都能改善。电流纹波大的问题在示波器上用电流探头看会比较直观。如果没有电流探头可以用一个采样电阻串在电机回路里测电阻两端的电压波形间接观察电流。纹波过大的主要原因有三类PWM频率太低、驱动电压太高但电感太小、续流回路不完善。解决办法分别对应提高频率、加PWM软启动斜坡、检查续流二极管或芯片的续流能力。一个有刷电机的关键现象是在相同平均电压下PWM频率越高电流波形越平滑电机换向火花越小。但这个平滑效果在频率超过20kHz后提升就不明显了反而因为开关损耗加大导致整体效率下降。所以效率优先时10~15kHz是个不错的折中区间。5.3 常见问题速查表现象可能原因排查方向电机完全不动使能脚没拉高/电源电压不够/占空比为0检查STBY引脚、电源负载电压、初始CCR电机只会单方向转方向引脚逻辑没接对确认IN1/IN2和PWM引脚的接线与代码逻辑电机抖动、啸叫PWM频率太低提到10kHz以上再观察转速突然下降或停止电源电压被拉到保护值实测驱动板输入电压换更大功率的电源带载后转速掉很多开环控制固有压降、电源内阻大换低内阻电源、粗导线或上闭环驱动芯片烫手开关损耗大/散热不足/堵转降低PWM频率、加散热、检查负载单片机偶尔复位功率地与逻辑地干扰单点接地、大电容滤波、隔离供电这个表格基本涵盖了我这些年调试电机驱动遇到的八成问题。剩下两成是硬件损坏类问题比如MOS管被击穿、芯片手册参数扯淡等只能通过替换法排除。6. 从开环到闭环的进阶路线6.1 为什么开环只能算“能用”不能算“好用”开头说了开环控制的本质是不检测实际结果、不修偏。这在调速场景里有三个痛点第一带载转速会掉。同样是50%占空比空载可能2000rpm带负载后可能掉到1500rpm负载越大掉得越狠。第二电源电压变化带来转速波动。电池从满电4.2V用到3.7V同一占空比对应转速差异很大。第三电机个体差异明显。同一型号电机的一致性不算差但批次间有差异开环校准一台不代表所有都准。如果你的项目只是用电机吹风、抽水这些误差可以接受。但如果是循迹小车要求两轮速度一致、云台要求转动角度精确、或者机械臂要求定位不漂开环是完全不能用的。先把这三点想明白你才真正理解为什么做闭环不是炫技而是刚需。6.2 加编码器和PID最常用的闭环路线最常见的升级路径是在电机尾部加霍尔编码器测量实际转速然后用PID控制器把实际转速拉回期望值。整个控制结构可以理解成期望转速r(t)和实际转速y(t)做差得到误差e(t)PID算法根据误差算出PWM占空比PWM驱动电机编码器反馈实际转速形成一个完整的负反馈回路。PID有三个参数比例项Kp负责对当前误差做出响应积分项Ki负责消除稳态误差微分项Kd负责抑制超调和振荡。实操时建议先清零Ki和Kd只调Kp从小往大加直到系统出现临界振荡然后回调一点再加入Ki消除稳态误差最后视情况加一点Kd抑制超调。这个调参顺序是我一直沿用的方法比盲目搜参数组合高效得多。编码器测速还有几个细节要注意。AB相正交编码器可以用STM32的定时器编码器模式直接读脉冲个数单位时间内的脉冲数就是转速。计算转速时要把减速比算进去——如果电机带一个1:30的减速箱电机轴转30圈才带动输出轴转1圈那编码器测到的是电机轴转速换算成输出轴转速时要除以30。6.3 再往后走中心对齐模式、电流环、BLDC和IPM闭环之后如果你要继续往电机控制深处走会碰到几个方向。第一个方向是PWM波形优化STM32高级定时器支持中心对齐模式计数从0加到ARR再减回0输出波形对称谐波含量更低配合ADC采样时刻设定可以在PWM周期中心点采样电流避开开关噪声这是FOC电流环采样的前提。第二个方向是无刷电机BLDC控制需要三路半桥共六路PWM配合霍尔传感器或反电动势过零检测做换相英飞凌TC3xx系列MCU的CCU6定时器单元就是专门为这类应用设计的。第三个方向是IPM电机、效率Map图、更精细的电流纹波分析这些都是做车规级、工业级电驱系统才用得到的深度内容。我不建议一上来就追这些概念但对它们保持了解是有价值的。你会发现从PWM开环控制这第一步走出去后面每一步都是前面知识的自然延伸PWM占空比的概念到了FOC里变成了SVPWM调制波死区概念到了BLDC里变成了换相时序设计开环调速的经验到了闭环里变成了PID参数的初值参考。这条路径很清晰值得花时间慢慢走。我个人在实际操作中的体会是PWM开环控制这个任务看上去简单但它是整个电机控制知识体系的地基。地基扎不扎实决定了你后面学到FOC、做无人机电调、调PID时会不会反复回头补课。做这个项目时我强烈建议你把每一个“为什么”都弄明白为什么这么选频率、为什么控制器输出要加死区、为什么开环会掉速。这些问题想透了你收获的远不止一个会转的电机而是一整套分析电机控制问题的方法。
返回列表