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桥,示波器是必备工具。我一般会看三个关键点:

  1. PWM波形本身:频率对不对?占空比准不准?有没有毛刺?
  2. 死区时间:上下管切换时,有没有同时为高的时刻?死区宽度够不够?
  3. 电机电流:启动电流多大?有没有异常尖峰?

我曾经遇到一个奇怪的问题:电机低速时嗡嗡响,高速时正常。用示波器一看,发现死区时间不对称——上升沿死区200ns,下降沿死区800ns。调整后问题解决。

避坑指南:

  • 不要用软件延时做死区,FPGA的时序是确定的,用计数器最可靠
  • 死区时间要留余量,别卡着MOS管的极限值算
  • 电机线越长,寄生电感越大,死区要适当加大

4.6 知识体系总览

下面这张图,把PWM生成和电机驱动的核心逻辑串起来了。你看一遍,应该能对整个流程有个整体认识。

PWM生成与电机驱动知识体系 控制指令输入 PWM波形生成 频率设定 | 占空比计算 | 计数器实现 死区时间插入 边沿检测 | 死区计数器 | 互补PWM生成 H桥驱动逻辑 正转/反转/刹车/滑行 | 上下管控制 | 电流保护 电机运转 关键参数: PWM频率:1kHz~100kHz 占空比分辨率:8~16位 死区时间:100ns~5μs 取决于MOS管开关速度 H桥拓扑:N+N或P+N 注意:严禁上下管直通

嗯,PWM和电机驱动这块,说白了就是三个核心:生成波形、插入死区、控制H桥。每一步都有坑,但只要你理解了原理,调试起来就不慌。

我个人的经验是:先让电机转起来,再优化性能。别一上来就追求完美,先把基本功能调通,后面慢慢优化。毕竟,能转的电机比不转的电机好调试多了。