4. PWM生成与电机驱动:PWM原理、死区时间设置、H桥驱动逻辑
电机控制这块,说难不难,说简单也不简单。我见过不少新手,写个PWM波形跑起来挺开心,一接上电机就冒烟了。嗯,这里面的坑,我今天跟你好好聊聊。
4.1 PWM原理——不就是方波吗?
PWM,全称Pulse Width Modulation,脉冲宽度调制。说白了,就是通过调整一个方波里高电平占的比例,来模拟一个模拟电压。
你想想看,电机需要的是连续变化的电压,但FPGA只能输出0和1。怎么办?让0和1快速切换,电机因为有惯性,感受到的就是一个平均电压。
核心公式:
占空比 = T_on / T_period × 100%
等效电压 = V_max × 占空比
举个例子:5V供电,占空比60%,电机感受到的就是3V左右。我刚开始做项目时,总以为占空比和转速是线性关系,后来发现根本不是这么回事——电机有死区电压,低于某个阈值根本不转。
4.2 死区时间——这个坑我踩过
死区时间,英文叫Dead Time。为什么要加这个?因为H桥上下两个管子不能同时导通。
你想想看,如果上管还没完全关断,下管就打开了,那VCC和GND直接短路,电流瞬间飙升。我见过一块驱动板,就因为死区设得太小,MOS管直接炸了,板子上烧出一个洞。
警告:死区时间设置过小会导致上下管直通,烧毁驱动器和电机。设置过大则会影响PWM精度和电机响应速度。
死区时间怎么算?一般根据MOS管的关断延迟来定。我个人的习惯是:
- 低速MOS管(如IRF540):死区设500ns~1μs
- 高速MOS管(如IRF7842):死区设100ns~300ns
- IGBT模块:死区设2μs~5μs
我曾经在一个项目中,用了高速MOS管但忘了改死区参数,结果电机低速运行时抖动得厉害。查了两天才发现是死区太大,PWM有效占空比被压缩了。
4.3 H桥驱动逻辑——四个管子怎么玩
H桥,名字来源于电路形状像字母H。四个开关管,两个上管(Q1、Q3),两个下管(Q2、Q4)。
基本逻辑就四种状态:
| 状态 | Q1 | Q2 | Q3 | Q4 | 电机行为 |
|---|---|---|---|---|---|
| 正转 | PWM | ON | OFF | OFF | 正向加速 |
| 反转 | OFF | OFF | PWM | ON | 反向加速 |
| 刹车 | OFF | ON | OFF | ON | 急停 |
| 滑行 | OFF | OFF | OFF | OFF | 自由停止 |
这里有个细节:正转时,Q2常开,Q1给PWM。为什么不是Q1常开、Q2给PWM?因为下管通常用N沟道MOS管,导通电阻小,发热少。我习惯把PWM放在上管,下管做续流通道。
小技巧:实际项目中,我建议用互补PWM加死区插入的方式。即上管PWM和下管PWM互为反相,中间插入死区时间。这样控制更精细,电机运行也更平稳。
4.4 FPGA实现——代码怎么写
下面给一个简单的PWM生成模块,带死区插入功能。这是我项目里常用的模板:
module pwm_deadtime (
input clk, // 系统时钟,50MHz
input rst_n, // 复位,低有效
input [15:0] duty, // 占空比,0~1000对应0%~100%
input dir, // 方向:0正转,1反转
output reg pwm_h, // 上管PWM
output reg pwm_l // 下管PWM
);
// 死区计数器,假设死区时间1μs,50MHz时钟下计50个周期
parameter DEADTIME = 50;
reg [15:0] counter;
reg [15:0] duty_reg;
reg pwm_internal;
// PWM生成
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
counter <= 0;
pwm_internal <= 0;
end else begin
if (counter >= 1000)
counter <= 0;
else
counter <= counter + 1;
if (counter < duty)
pwm_internal <= 1;
else
pwm_internal <= 0;
end
end
// 死区插入逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
pwm_h <= 0;
pwm_l <= 0;
end else begin
if (dir == 0) begin // 正转
pwm_h <= pwm_internal;
pwm_l <= ~pwm_internal;
// 死区插入:检测上升沿和下降沿
if (pwm_internal == 1 && counter < DEADTIME)
pwm_l <= 0;
if (pwm_internal == 0 && counter > (1000 - DEADTIME))
pwm_h <= 0;
end else begin // 反转
pwm_h <= ~pwm_internal;
pwm_l <= pwm_internal;
// 同理插入死区
if (pwm_internal == 1 && counter < DEADTIME)
pwm_h <= 0;
if (pwm_internal == 0 && counter > (1000 - DEADTIME))
pwm_l <= 0;
end
end
end
endmodule
这段代码里,我用了计数器做PWM,占空比范围0~1000。死区插在PWM切换的边沿处,确保上下管不会同时导通。
4.5 调试经验——波形怎么看
调试PWM和H桥,示波器是必备工具。我一般会看三个关键点:
- PWM波形本身:频率对不对?占空比准不准?有没有毛刺?
- 死区时间:上下管切换时,有没有同时为高的时刻?死区宽度够不够?
- 电机电流:启动电流多大?有没有异常尖峰?
我曾经遇到一个奇怪的问题:电机低速时嗡嗡响,高速时正常。用示波器一看,发现死区时间不对称——上升沿死区200ns,下降沿死区800ns。调整后问题解决。
避坑指南:
- 不要用软件延时做死区,FPGA的时序是确定的,用计数器最可靠
- 死区时间要留余量,别卡着MOS管的极限值算
- 电机线越长,寄生电感越大,死区要适当加大
4.6 知识体系总览
下面这张图,把PWM生成和电机驱动的核心逻辑串起来了。你看一遍,应该能对整个流程有个整体认识。
嗯,PWM和电机驱动这块,说白了就是三个核心:生成波形、插入死区、控制H桥。每一步都有坑,但只要你理解了原理,调试起来就不慌。
我个人的经验是:先让电机转起来,再优化性能。别一上来就追求完美,先把基本功能调通,后面慢慢优化。毕竟,能转的电机比不转的电机好调试多了。