4. 直流电机开环控制:H桥驱动原理与正反转调速实现

大家好,我是你们的老朋友。今天咱们来聊聊直流电机控制里最基础、也最核心的一块——H桥驱动。说实话,我入行那会儿,第一次用分立元件搭H桥,烧了好几个MOS管才搞明白。嗯,这些坑今天我都给你们指出来。

4.1 H桥驱动原理——说白了就是个“换向开关”

直流电机要正反转,靠什么?靠改变电流方向。H桥这个名字很形象,四个开关管搭成一个“H”形状,电机就是中间那根横杠。

核心逻辑:

  • Q1和Q4导通:电流从左到右,电机正转
  • Q2和Q3导通:电流从右到左,电机反转
  • 绝对不能同时导通Q1和Q2(或Q3和Q4)——这就是“直通”,一烧一个准

我给你们画个图,一看就明白。

H桥驱动原理图 VCC (12V/24V) Q1 Q2 Q3 Q4 M 电机 GND → 正转电流方向 ← 反转电流方向 正转:Q1+Q4导通 | 反转:Q2+Q3导通 | 禁止:Q1+Q2或Q3+Q4同时导通

你想想看,这个结构其实很巧妙。四个开关管,两两一组,一组管正转,一组管反转。我在项目里见过有人用继电器搭H桥,那噪音大得跟打电报似的,而且响应速度慢。现在主流都是用MOS管或者集成驱动芯片。

4.2 常用驱动芯片:L298N vs DRV8833

市面上常见的H桥驱动芯片,我接触最多的就是L298N和DRV8833。这俩定位不一样,我给你们对比一下。

参数 L298N DRV8833
工作电压 4.5V - 46V 2.7V - 10.8V
最大电流 2A(峰值3A) 1.5A(峰值2A)
封装 MultiWatt15(大个头) QFN/TSSOP(小身材)
内阻 约2Ω(发热大) 约0.3Ω(效率高)
PWM频率 建议≤40kHz 最高250kHz
典型应用 大功率电机、机器人底盘 小电机、电池供电设备

我的选择建议:

做12V以上的大电机项目,L298N皮实耐造,就是发热厉害,记得加散热片。做3.3V/5V的小车或者手持设备,DRV8833更合适,效率高、体积小。我曾经在一个智能窗帘项目里用DRV8833,电池续航比用L298N多了将近一倍。

4.3 正反转控制——逻辑其实很简单

控制正反转,本质上就是控制两个使能引脚的电平组合。以L298N为例,它有两个通道,每个通道有三个控制引脚:ENA、IN1、IN2。

L298N控制逻辑表(单通道):

ENA IN1 IN2 电机状态
0XX停止(高阻)
110正转
101反转
111刹车(短路制动)
100自由停止

DRV8833的控制逻辑类似,但引脚命名不同。它用IN1和IN2直接控制,没有单独的使能引脚。说白了,就是两路PWM输入,通过相位差来控制方向和速度。

4.4 调速实现——PWM是王道

直流电机调速,最常用的方法就是PWM(脉宽调制)。为什么?因为简单、高效、线性度好。

原理不复杂:固定频率下,改变占空比,就改变了平均电压。占空比越大,电机转得越快。我习惯用20kHz的PWM频率,人耳听不到,电机也不容易啸叫。

⚠️ 注意:

PWM频率不是越高越好。频率太高,MOS管的开关损耗会急剧增加,驱动芯片发热严重。我曾经在一个项目里把PWM设到100kHz,结果DRV8833烫得能煎鸡蛋。后来降到25kHz,一切正常。

下面给个HAL库的代码示例,用STM32的定时器输出PWM控制电机。

// 电机控制结构体
typedef struct {
    TIM_HandleTypeDef *htim;  // 定时器句柄
    uint32_t channel;         // PWM通道
    GPIO_TypeDef *dir1_port;  // 方向引脚1
    uint16_t dir1_pin;
    GPIO_TypeDef *dir2_port;  // 方向引脚2
    uint16_t dir2_pin;
} Motor_HandleTypeDef;

// 初始化电机GPIO和PWM
void Motor_Init(Motor_HandleTypeDef *motor) {
    // 启动PWM输出
    HAL_TIM_PWM_Start(motor->htim, motor->channel);
    // 初始状态:停止
    HAL_GPIO_WritePin(motor->dir1_port, motor->dir1_pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(motor->dir2_port, motor->dir2_pin, GPIO_PIN_RESET);
}

// 设置电机转速和方向
// speed: 0-1000 (对应占空比0%-100%)
// dir: 0=停止, 1=正转, 2=反转
void Motor_SetSpeed(Motor_HandleTypeDef *motor, uint16_t speed, uint8_t dir) {
    // 限幅处理
    if(speed > 1000) speed = 1000;
    
    // 设置方向
    switch(dir) {
        case 0: // 停止
            HAL_GPIO_WritePin(motor->dir1_port, motor->dir1_pin, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(motor->dir2_port, motor->dir2_pin, GPIO_PIN_RESET);
            break;
        case 1: // 正转
            HAL_GPIO_WritePin(motor->dir1_port, motor->dir1_pin, GPIO_PIN_SET);
            HAL_GPIO_WritePin(motor->dir2_port, motor->dir2_pin, GPIO_PIN_RESET);
            break;
        case 2: // 反转
            HAL_GPIO_WritePin(motor->dir1_port, motor->dir1_pin, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(motor->dir2_port, motor->dir2_pin, GPIO_PIN_SET);
            break;
    }
    
    // 设置PWM占空比
    __HAL_TIM_SET_COMPARE(motor->htim, motor->channel, speed);
}

// 使用示例
Motor_HandleTypeDef motor1 = {
    .htim = &htim2,
    .channel = TIM_CHANNEL_1,
    .dir1_port = GPIOB,
    .dir1_pin = GPIO_PIN_0,
    .dir2_port = GPIOB,
    .dir2_pin = GPIO_PIN_1
};

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_TIM2_Init();
    
    Motor_Init(&motor1);
    
    while(1) {
        // 正转,50%速度
        Motor_SetSpeed(&motor1, 500, 1);
        HAL_Delay(3000);
        
        // 反转,75%速度
        Motor_SetSpeed(&motor1, 750, 2);
        HAL_Delay(3000);
        
        // 停止
        Motor_SetSpeed(&motor1, 0, 0);
        HAL_Delay(1000);
    }
}

经验之谈:

代码里我用了1000作为占空比最大值,而不是常见的100。为什么?因为1000的精度更高,调速更细腻。特别是做闭环控制的时候,1000级的分辨率比100级好太多了。当然,如果你的定时器ARR值有限,也可以根据实际情况调整。

4.5 避坑指南——我踩过的那些雷

做电机驱动,有些坑是新手必踩的。我给你们列几个最常见的。

  • 共地问题:驱动板的GND和单片机的GND必须连在一起。我曾经忘了接地,结果电机转一下单片机就重启一下,查了半天才发现是地线没接。
  • 电源滤波:电机启动瞬间电流很大,会在电源线上产生尖峰。我习惯在电机电源两端并联一个470μF电解电容和一个0.1μF瓷片电容。
  • 续流二极管:虽然L298N和DRV8833内部都有续流二极管,但如果自己搭分立H桥,一定要在电机两端反向并联二极管,否则关断瞬间的反向电动势会击穿MOS管。
  • 死区时间:切换方向时,要先关闭所有开关管,等一小段时间再打开另一组。这个“死区时间”一般几微秒就够了,但绝对不能省。我见过有人直接切换,结果上下管瞬间导通,冒烟了。

⚠️ 特别提醒:

调试的时候,千万别用手去摸电机驱动芯片!L298N正常工作温度就有70-80度,DRV8833虽然好点,但堵转时也能到60度。我手上现在还有被L298N烫过的疤,嗯,那酸爽...

4.6 开环控制的局限性

最后说一句,开环控制虽然简单,但精度有限。电机负载变化时,转速会波动。比如你的小车爬坡,同样的PWM占空比,速度明显会降下来。

如果项目对速度精度有要求,那就得上闭环了——加编码器,做PID调节。这个我们后面章节会详细讲。今天先把开环玩明白,基础打牢了,后面才不慌。

好了,直流电机的开环控制就聊到这儿。代码和原理图我都给你们整理好了,自己动手试试看。记住,纸上得来终觉浅,绝知此事要躬行。


公众号:蓝海资料掘金营,微信deep3321