4. 启动策略(三段式启动):转子预定位、外同步加速、切换至闭环运行

无传感器BLDC启动,说白了就是个「猜位置」的游戏。

电机静止时,反电动势为零。你没法通过它判断转子在哪。但你又必须给对相序,否则电机要么抖,要么反转,要么直接堵转。

我刚开始做这个项目时,就踩过这个坑。上电直接给PWM,电机嗡嗡响就是不转。后来才明白——启动不是靠运气,而是靠策略。

行业内最成熟的做法,就是三段式启动。我习惯叫它「三步走」:先定位,再硬拖,最后放手让它自己跑。

4.1 第一步:转子预定位

预定位的目的很简单——让转子停在你想要的位置上。

怎么做?给任意两相通电,产生一个固定磁场。转子会被这个磁场吸过去,最终停在那个位置。

举个例子:我让A+、B-通电,电流从A相流入,B相流出。产生的合成磁动势会指向某个固定方向。转子会乖乖转过去,停稳。

关键点:预定位时间要足够长。我一般给300~500ms。太短了转子还没停稳,后面加速就容易失步。

这里有个细节——预定位电流不能太小。电流小了,力矩不够,转子可能被负载摩擦力卡住,停不到指定位置。但也不能太大,否则转子冲过头,来回震荡。

我个人习惯:预定位电流设定为额定电流的30%~50%。这个范围既能保证定位可靠,又不会过热。

小技巧:如果你发现预定位后电机启动方向偶尔不对,可以试试先给一个短脉冲,让转子动一下,再给定位电流。这样能打破静摩擦力的「死锁」。

4.2 第二步:外同步加速

转子定位好了,接下来要把它拖起来。

外同步加速,说白了就是「开环硬拖」。你按照预设的换相频率,强制给电机换相。转子被磁场拖着走,速度慢慢往上提。

这个过程有点像推秋千。你不管秋千本身的节奏,就按自己的频率推。只要频率合适,秋千总能荡起来。

换相频率怎么定?从零开始,逐步增加。我一般用这样一个斜坡函数:

// 外同步加速的换相频率计算
// target_freq: 目标切换频率(Hz)
// accel_time: 加速时间(s)
// current_time: 当前已加速时间(s)

float calc_commutation_freq(float target_freq, float accel_time, float current_time) {
    if (current_time >= accel_time) {
        return target_freq;  // 加速完成
    }
    
    // 线性斜坡
    float freq = target_freq * (current_time / accel_time);
    
    // 最低频率限制,防止启动时频率太低导致抖动
    if (freq < 5.0f) {
        freq = 5.0f;
    }
    
    return freq;
}

加速时间怎么选?我踩过的坑是——加速太快,电机失步;加速太慢,启动过程太长,用户觉得卡顿。

我的经验值:

负载类型 加速时间 说明
轻载(风扇、泵类) 0.5~1.0秒 惯性小,可以快一点
中载(压缩机) 1.0~2.0秒 需要克服气体压力
重载(电动工具) 2.0~3.0秒 惯性大,要慢慢来

注意:外同步阶段,你是在「盲推」。没有反电动势反馈,你不知道转子实际跟没跟上。所以换相频率的斜率不能太陡。我曾经把加速时间设成0.3秒,结果电机直接啸叫——那是失步的声音。

嗯,这里还要注意一点:外同步阶段的PWM占空比要适当提高。因为开环状态下,电机效率低,需要更多能量才能拖起来。我一般比闭环时的占空比高10%~20%。

4.3 第三步:切换至闭环运行

这是三段式启动里最微妙的一步。

外同步加速到一定速度后,反电动势信号已经足够强了。这时候你要从「开环盲推」切换到「闭环反馈」。切换时机不对,电机要么掉速,要么直接停转。

切换条件是什么?两个:

  • 速度足够高:一般需要达到额定转速的10%~20%。具体看电机参数,我习惯等反电动势幅值达到5V以上再切换。
  • 信号稳定:反电动势过零检测的信号要连续稳定出现3~5次。不能有毛刺或漏检。

切换过程怎么实现?我常用的方法是「软切换」:

// 三段式启动 - 切换控制
// state: 0=预定位, 1=外同步加速, 2=切换中, 3=闭环运行

void motor_start_control(void) {
    static uint8_t start_state = 0;
    static uint32_t bemf_stable_count = 0;
    
    switch (start_state) {
        case 0:  // 预定位
            do_pre_position();
            if (pre_position_done()) {
                start_state = 1;
            }
            break;
            
        case 1:  // 外同步加速
            do_openloop_accel();
            // 检测反电动势是否稳定
            if (bemf_detected()) {
                bemf_stable_count++;
                if (bemf_stable_count >= 5) {
                    start_state = 2;  // 进入切换
                }
            } else {
                bemf_stable_count = 0;
            }
            break;
            
        case 2:  // 切换中 - 软切换
            // 开环占空比逐渐减小,闭环占空比逐渐增大
            float openloop_weight = 1.0f - (switch_timer / SWITCH_TIME);
            float closedloop_weight = (float)switch_timer / SWITCH_TIME;
            
            pwm_duty = openloop_weight * openloop_duty + 
                       closedloop_weight * closedloop_duty;
            
            if (switch_timer >= SWITCH_TIME) {
                start_state = 3;  // 切换完成
            }
            switch_timer++;
            break;
            
        case 3:  // 闭环运行
            do_closedloop_control();
            break;
    }
}

切换时间SWITCH_TIME我一般设50~100ms。太快了容易冲击,太慢了又拖泥带水。

避坑指南:我曾经在切换时直接丢掉开环占空比,换成闭环计算值。结果电机转速瞬间掉下来,因为闭环刚开始算出来的占空比偏小。后来改成软切换,用加权平均过渡,问题就解决了。

4.4 三段式启动的完整流程图

下面这张图是我自己总结的,把整个启动流程串起来了。你想想看,每一步的输入输出都很清楚:

三段式启动流程图 步骤1:转子预定位 给两相通电,强制转子停到指定位置 定位完成? 步骤2:外同步加速 按斜坡频率强制换相,逐步提高转速 反电动势稳定? 步骤3:切换至闭环运行 软切换过渡,进入闭环控制模式 未稳定,继续加速 未完成,继续定位

4.5 实际调试中的几个坑

三段式启动看起来简单,实际调试时问题不少。我把自己踩过的坑列出来,你遇到了可以少走弯路:

  1. 预定位后转子抖动——定位电流太大,转子过冲。解决办法:减小定位电流,或者加一段「刹车时间」让转子停稳。
  2. 外同步加速时电机啸叫——换相频率变化太快,转子跟不上。解决办法:延长加速时间,或者用S形曲线代替线性斜坡。
  3. 切换瞬间转速掉下来——闭环初始占空比计算偏小。解决办法:用软切换过渡,或者把闭环初始占空比设成开环最后时刻的值。
  4. 重载启动失败——外同步力矩不够。解决办法:提高外同步阶段的占空比,或者增加预定位电流。

我的习惯:调试时先把三段式启动的每个阶段单独测试。预定位看转子停的位置对不对,外同步看转速能不能平稳上升,切换看反电动势信号是否连续。每个阶段都调好了,再连起来跑。这样出问题能快速定位。

嗯,三段式启动就讲到这里。说白了就是三个字:定、拖、切。每个环节都有细节,但掌握了核心逻辑,剩下的就是根据具体电机和负载去调参数了。


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