ixicuzks 发表于 2025-10-11 08:55:09

BLDC六步换相无感启动问题求助 | 好的

各位大佬好!
想请教一下,BLDC六步换相无感启动,怎么做才能让启动的成功率做到最高?我现在遇到的问题是预启动的时候,经常电机需要左右转动几下才动起来然后进入闭环。我需要做到95%的成功率,直接顺滑进入闭环。希望做过类似项目的大佬指点下,可以有偿,只要问题能解决!!!我想解决掉电机启动偶尔会反转和抖动的问题,不是底下结构不稳定,握在手上也是一样的。

目前用的电机功率比较小,是3.7VDC的。

<blockquote>


ixicuzks 发表于 2025-10-11 08:56:14

#define        STARTUP_PWM                                  900                 // 启动时的占空比        8元风扇电机, 12V-->300, 18V-->240, 24V-->200
#define STARTUP_INTERVAL                    8000                // 启动时两次换向的最大间隔时间 us为单位
#define        STARTUP_END_PhaseTime                12000                // 判断启动结束的换相时间us,8元风扇电机
#define COMMUNICATION_NUM                        6

/******************* 强制电机启动函数 ***************************/
void PWMA_ISR(void) interrupt PWMA_VECTOR // 23.4375KHz(42.67us)中断率,用于处理启动电机,查询读取比较器结果
{
    u16 i;
       
        cmpo_state = (cmpo_state << 1) | (CMPCR1 & 1);        // 读取比较器状态,放在一个字节中, 连续8次检测到相同电平才认为有效
        if((cmpo_state & 0xff) == 0xff)        B_cmpo= 1;        //连续4个采样为1, 则比较器输出1
        if((cmpo_state & 0xff) == 0x00)        B_cmpo= 0;        //连续4个采样为0, 则比较器输出0

        if(run_mode == MOTOR_IDLE)        //空闲模式
        {
                B_RUN = 0;
                PWM_Value= 0;        // 设置停止占空比
                PWMA_CCR1 = PWM_Value;
                PWMA_CCR2 = PWM_Value;
                PWMA_CCR3 = PWM_Value;
        }
       
        else if(run_mode == MOTOR_PRE_POSITION)        //预定位模式
        {
                if(SampleTime == 0)        //刚开始, 启动前将SampleTime=0
                {
                        step = 1;
                        StepMotor();        //换相一次
                        PWM_Value = STARTUP_PWM;        // 设置启动占空比
                        PWMA_CCR1 = PWM_Value;
                        PWMA_CCR2 = PWM_Value;
                        PWMA_CCR3 = PWM_Value;
                        SampleTime = 1;
                }
                else if(++SampleTime >= (STARTUP_INTERVAL/43))        //预定位时间到,准备启动电机,预定位时间为最大换相时间, 43是PWM周期为43us(23.4K)
                {
                        for(i=0; i<8; i++)       
                                PhaseTimeTmp = STARTUP_INTERVAL / 43;        //初始默认最大换相时间
                       
                        TimeIndex = 0;
                        commutation_num = 0;        //启动换相次数累加
                        Degree30_time   = 0;
                        SampleTime = STARTUP_INTERVAL / 43 / 4;
                        run_mode = MOTOR_STARTING;        //下一个模式:启动模式
                        StepMotor();        //换相一次
                        SampleTime = 0;   // 重置时间计数器
                }
        }
       
        else if(run_mode == MOTOR_STARTING)        //启动模式
        {
                SampleTime++;

                if(Degree30_time != 0)        //有30度角延时
                {
                        if(--Degree30_time == 0)        //30度角延时到,则换相
                        {
                                StepMotor();        //换相
                                commutation_num++;        //启动换相次数累加
                               
                                if ((commutation_num >= COMMUNICATION_NUM) && (PhaseTime <= 600))
                                {
                                        B_startDone = 1;        //已启动
                                        B_start   = 0;        //已启动完成
                                        B_RUN   = 1;        //已运行
                                        run_mode = MOTOR_RUNNING;
                                        Target_RollSpeed = Measure_RollSpeed; // 或根据 duty_run 推算
                                        delay_us(50);
                                        XiaoCiCnt = 0;                //1:需要消磁, 2:正在消磁, 0已经消磁
                                        if(step & 1)        CMPCR1 = 0x8c + 0x20;        // 比较器上升沿中断,        PIE=1: 允许比较器上升沿中断, PIE=0: 禁止上升沿中断.        NIE=1: 允许比较器下降沿中断, NIE=0: 禁止下降沿中断.
                                        else                        CMPCR1 = 0x8c + 0x10;        // 比较器下降沿中断,        PIE=1: 允许比较器上升沿中断, PIE=0: 禁止上升沿中断.        NIE=1: 允许比较器下降沿中断, NIE=0: 禁止下降沿中断.
                                }
                        }
                }
                else        //检测反电动势过0
                {
                        B_zcFound = 0;
                       
                        if (step & 1)
                        {       // 上升沿检测
                                if (B_cmpo) B_zcFound = 1;
                        }
                        else
                        {            // 下降沿检测
                                if (!B_cmpo) B_zcFound = 1;
                        }
                       
                        if (B_zcFound && (SampleTime > STARTUP_END_PhaseTime / 43 / 4))        //检测到过0事件, 换相时间过小则不换相
                        {
                                if(SampleTime > (STARTUP_INTERVAL / 43))               
                                        SampleTime = STARTUP_INTERVAL / 43;        //换相过慢,
                               
                                PhaseTimeTmp = SampleTime;        //保存本次换相时间
                                SampleTime = 0;
                                if(++TimeIndex >= 8)       
                                        TimeIndex = 0;        //索引溢出归0
                               
                                for(PhaseTime8sum=0, i=0; i<8; i++)       
                                        PhaseTime8sum += PhaseTimeTmp;        //求8次换相时间累加和, 用于计算实时转速 = 1/(M*PhaseTime8sum*3/4) 转/秒 = 60/(M*PhaseTime8sum*3/4) 转/分,PhaseTime8sum*3/4为换相6次的时间,M为磁极对。
                               
                                PhaseTime = PhaseTime8sum >> 3;                //换相时间
                               
                                if(PhaseTime >= 18)        Degree30_time = PhaseTime / 2 - 4;        //换相时间的一半, 即30度电角度, -8为修正8次采样时间
                                else                                Degree30_time = 1;                                        //换相时间的一半, 即30度电角度
                        }
                        else if(SampleTime >= 1500)        //超时重新预定位启动
                        {
                                SampleTime = 0;
                                run_mode= MOTOR_PRE_POSITION; //超时则重新预定位启动
                                StepMotor();        //换相一次
                        }
                }
        }
       
    if(B_RUN)                                        PWMA_IER = 0;    //如果电机已启动运行,则禁止PWMA中断
    if(run_mode == MOTOR_IDLE)        PWMA_IER = 0;
       
        PWMA_SR1 = 0;        //清除标志
}

梁工 发表于 2025-10-11 11:38:19

根据电机特性修改启动参数(程序开头的宏定义),匹配好了,基本可以100%启动成功。
您需要提供电机的基本参数:
KV值,工作电压,磁极对,这样我才能知道参数怎么匹配。
如果不知道KV值,可以实际测试,电机空载,让电机转起来,100%占空比时的驱动电压和实际转速,转速/电压 就是KV值的大致值。也可以示波器观察反电动势的幅度和周期,计算出真实的电角度KV值,再除以磁极对就是实际KV值。
如果连磁极对都不知道(可以问商家、厂家,看得到钕铁硼磁铁的话直接数数目/2),则是可以测试电子转速与实际转子转速,其比值就是磁极对,比如电子转速是6万转,转子是1万转,则磁极对为6.

ixicuzks 发表于 2025-10-11 20:46:06

梁工 发表于 2025-10-11 11:38
根据电机特性修改启动参数(程序开头的宏定义),匹配好了,基本可以100%启动成功。
您需要提供电机的基本 ...

KV应该在3100左右,满占空比差不多13000转,电压是4.2V,极对数是5

ixicuzks 发表于 2025-10-11 21:01:06

梁工 发表于 2025-10-11 11:38
根据电机特性修改启动参数(程序开头的宏定义),匹配好了,基本可以100%启动成功。
您需要提供电机的基本 ...

请问梁工这个参数怎么根据KV值或者极对数来配置? 我这个电机是3.7VDC的小电机

梁工 发表于 2025-10-11 23:41:22

ixicuzks 发表于 2025-10-11 20:46
KV应该在3100左右,满占空比差不多13000转,电压是4.2V,极对数是5
你试下下面的参数:
#define      MPP                            5    // 电机磁极对, Magnetic Pole Pair,8元风扇电机为5对磁极
#define      ROLL_MinSpeed          60    // 启动时检测到低于这个转速则认为电机停止,从静止开始启动,否则直接进入闭环
#define      PRE_PWM_DUTY         60    // 预定位占空比, 一般为START_PWM_DUTY的0.5~1,较小的占空比冲击小,但启动力矩小。
#define      START_PWM_DUTY    100   // 启动时的占空比
#define      STOP_PWM_DUTY       60    // 停止PWM,小于此PWM就停机, 根据电机特性适当改变
#define      BeginSpeed                60    // 启动起始转速,转/分
#define      FinishSpeed            600   // 启动终了转速,转/分
#define      D_StartTime             800   // 加速时间,单位ms,不能小于500, 500~10922
#define      PRE_STATE_TIME1   30    // 预定位时间1,ms, 最大值为2849ms
#define      PRE_STATE_TIME2   20    // 预定位时间2,ms, 最大值为2849ms
#define      PRE_STATE_TIME3   15    // 预定位时间3,ms, 最大值为2849ms

ixicuzks 发表于 2025-10-13 16:46:37

梁工 发表于 2025-10-11 23:41
你试下下面的参数:
#define      MPP                            5    // 电机磁极对, Magnetic Pole...

梁工请问用V2的方式可以吗,我目前用V2的启动率大概在80%左右,有时候会如视频中那样转几下才启动,请问怎么优化? 另外这个参数不行

梁工 发表于 2025-10-13 20:50:51

ixicuzks 发表于 2025-10-13 16:46
梁工请问用V2的方式可以吗,我目前用V2的启动率大概在80%左右,有时候会如视频中那样转几下才启动,请问 ...

改用V3的方式,基本100%启动。

ixicuzks 发表于 2025-10-14 07:50:57

梁工 发表于 2025-10-13 20:50
改用V3的方式,基本100%启动。

行 我再调调

ixicuzks 发表于 2025-10-14 08:50:25

梁工 发表于 2025-10-13 20:50
改用V3的方式,基本100%启动。

还有就是我的电阻这样选有问题吗? 因为我用原理图上的电阻参数没办法驱动我的电机,改为1K 去掉电容才能达到100%的占空比。 这些选型有什么要求吗? 3.7Vdc的小电机,整个板子都是是5V供电
页: [1] 2
查看完整版本: BLDC六步换相无感启动问题求助 | 好的