引言

在嵌入式系统中,电机驱动无处不在:从机器人关节到工业传送带,从无人机螺旋桨到智能家居门窗。然而,驱动电机远不止“给电就转”那么简单。H桥的拓扑选择、PWM的占空比与频率设计、以及堵转时的电流冲击,都是决定系统稳定性的关键。本文将以直流有刷电机为例,深入讲解H桥原理、PWM调速方法,并重点探讨堵转保护的实现策略,提供一套可落地的STM32代码方案。

H桥:电机换向的基石

拓扑与工作原理

H桥由四个开关管(MOSFET或IGBT)组成,形似字母“H”,电机接在桥臂中点。通过控制四个开关的通断组合,可实现电机的正转、反转、制动和滑行:

  • 正转:Q1和Q4导通,Q2和Q3关断,电流从左向右流过电机。
  • 反转:Q2和Q3导通,Q1和Q4关断,电流反向。
  • 制动:Q1和Q3导通(或Q2和Q4),电机两端短路,产生反向电动势制动。
  • 滑行:所有开关关断,电机自由旋转。

实际应用中,常用半桥驱动芯片(如IR2104)配合N-MOSFET,简化逻辑控制。

死区时间:防止直通短路

若同一桥臂的上下管同时导通,电源将被短路,烧毁器件。因此,在切换开关状态时,必须插入“死区时间”(Dead Time),即先关闭上管,延迟一段时间后再打开下管。死区时间通常为几百纳秒到几微秒,由驱动芯片或软件定时器实现。

// 示例:使用定时器产生带死区的互补PWM(STM32高级定时器)
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

// 配置定时器1为PWM模式1,输出比较通道1和通道1N互补
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // 占空比50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);

// 设置死区时间:例如1us(假设时钟72MHz,死区寄存器值=72)
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 72; // 1us
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRInit(TIM1, &TIM_BDTRInitStructure);

PWM调速:从占空比到有效电压

原理与频率选择

PWM(脉宽调制)通过改变占空比来调节电机两端的平均电压,从而控制转速。占空比D = Ton / T,有效电压V_avg = D * V_supply。

  • 频率选择:过低(<1kHz)会导致电机振动和噪声;过高(>50kHz)会增加开关损耗。常用范围:10kHz-20kHz(避开人耳敏感区)。
  • 分辨率:8位(0-255)或16位(0-65535),根据调速精度需求选择。

软件实现要点

  • 使用定时器产生固定频率的PWM,通过修改比较寄存器更新占空比。
  • 避免在中断中频繁修改占空比,可采用双缓冲或DMA。
  • 启动时逐渐增加占空比(软启动),防止电流冲击。
// STM32定时器2通道1输出PWM,频率10kHz,占空比可调
void PWM_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_InitStructure.TIM_Prescaler = 72 - 1; // 72MHz/72 = 1MHz
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_InitStructure.TIM_Period = 100 - 1; // 1MHz/100 = 10kHz
    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
    
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    
    TIM_Cmd(TIM2, ENABLE);
}

void Set_Motor_Speed(uint8_t duty) {
    TIM_SetCompare1(TIM2, duty); // duty范围0-100
}

堵转保护:电流检测与响应策略

堵转的危害

当电机负载过大或转子卡死时,转速为零,反电动势消失,电流急剧上升(可达额定电流的5-10倍),导致绕组过热烧毁,或损坏驱动MOSFET。因此,堵转保护是电机驱动系统的必备功能。

硬件方案:采样电阻与比较器

  • 在电机回路中串联低阻值采样电阻(如0.1Ω),通过差分放大器放大电压,送入ADC或比较器。
  • 使用比较器设定阈值,一旦超过立即触发中断,关闭PWM输出。

软件方案:ADC采样与状态机

软件方案更灵活,可设置不同阈值和响应时间。核心逻辑:

  1. 周期性采样电流(如每1ms)。
  2. 若电流超过阈值(如额定电流的1.5倍),启动计时器。
  3. 若持续超限超过设定时间(如100ms),判定为堵转,关闭PWM并置位故障标志。
  4. 可配置自动恢复:延时后重新尝试启动,若再次堵转则彻底停机。
// 堵转检测状态机示例
#define CURRENT_THRESHOLD  1500  // 电流ADC值阈值
#define BLOCK_TIME_MS      100   // 堵转判定时间
#define RETRY_DELAY_MS     2000  // 重试延时

typedef enum {
    MOTOR_RUNNING,
    MOTOR_BLOCKED,
    MOTOR_RETRY
} MotorState;

MotorState state = MOTOR_RUNNING;
uint16_t block_timer = 0;
uint16_t retry_timer = 0;

void Motor_Protection_Task(void) {
    uint16_t current = ADC_GetValue(); // 读取电流采样
    
    switch(state) {
        case MOTOR_RUNNING:
            if (current > CURRENT_THRESHOLD) {
                block_timer++;
                if (block_timer >= BLOCK_TIME_MS) {
                    state = MOTOR_BLOCKED;
                    PWM_Disable(); // 关闭PWM
                    Motor_Stop();
                    // 记录故障日志
                }
            } else {
                block_timer = 0;
            }
            break;
            
        case MOTOR_BLOCKED:
            // 等待重试延时
            retry_timer++;
            if (retry_timer >= RETRY_DELAY_MS) {
                retry_timer = 0;
                state = MOTOR_RETRY;
                PWM_Enable();
                Set_Motor_Speed(30); // 低速重试
            }
            break;
            
        case MOTOR_RETRY:
            // 检查是否恢复正常
            if (current < CURRENT_THRESHOLD) {
                state = MOTOR_RUNNING;
                Set_Motor_Speed(target_speed); // 恢复目标速度
            } else {
                // 再次堵转,停止重试
                state = MOTOR_BLOCKED;
                PWM_Disable();
                // 设置永久故障标志
            }
            break;
    }
}

注意事项

  • 采样滤波:电流信号可能含有噪声,需进行软件滤波(如滑动平均)或硬件RC滤波。
  • 阈值设定:需考虑电机启动时的浪涌电流,通常启动时允许短暂过流,因此堵转判定需有延时。
  • 热保护:除电流外,可结合MOSFET温度传感器,实现双重保护。
  • 安全冗余:硬件比较器作为第一道防线,软件作为第二道,防止MCU死机时失控。

完整示例:集成H桥与堵转保护

以下代码演示了基于STM32F103的完整驱动流程:初始化PWM和ADC,主循环中执行堵转检测。

int main(void) {
    // 初始化系统时钟、GPIO、定时器、ADC等
    SystemInit();
    PWM_Init();
    ADC_Init();
    
    // 设置目标速度(占空比60%)
    Set_Motor_Speed(60);
    
    while (1) {
        Motor_Protection_Task(); // 每1ms调用一次(可用定时器中断)
        // 其他任务...
    }
}

总结

电机驱动看似简单,实则涉及功率电子、控制算法与保护机制。H桥的死区设计是硬件基础,PWM的频率与占空比决定调速性能,而堵转保护则关乎系统安全。本文提供的方案可直接应用于实际项目,但需根据具体电机参数和电源环境调整阈值与延时。建议开发者先在仿真环境中验证逻辑,再上电测试,并逐步优化保护策略。

掌握这些核心要点,你就能构建一个既高效又可靠的电机驱动系统,为你的嵌入式项目增添动力。