芯查查logo
  • 数据服务
    1. 新产品
    2. 物料选型
    3. 查替代
    4. 丝印反查
    5. 查品牌
    6. PCN/PDN
    7. 查方案
    8. 查代理
    9. 数据合作
  • SaaS/方案
      SaaS产品
    1. 供应链波动监控
    2. 半导体产业链地图
    3. BOM管理
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 行业资讯
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
  • 开通会员
峰岹科技_FU6832L_V3开发板使用心得(六)-BLDC
原创 精华 发布时间:2024/06/01 14:51
版块:
开发板测评
简介:测试单片机的BLDC控制流程。

编译环境:keil 5.39  C51编译器:C51V959

因为自己之前使用BLDC的控制,自己当初也为了调试这个电机废了好长时间去理解这些硬件设计原理,包括电源电路的设计,驱动电机电路的场效应管的选择,霍尔电路的采集和电压、电流的采集部分,这里浅谈一下基本的设计原理。

1:电压电源电路:

 

这里我查到电路板的一些硬件资料:FU6832L开发板供电支持3V-24V,最大电流10A设计;但是我看到使用的使用的降压LDO为LM317(输入最高电压为37V。)板载的场效应管(MOSFET)N沟道 的漏源电压为40V,RU40L10L(P沟道)的的漏源电压为40V。通过调节采样电阻的大小和比例,我觉得这里是不是可以支持到36V的电压,当然这里我没有进行测试。。。。

该主控芯片FU6832L是一款集成电机控制引擎(ME)和8051内核的高性能电机驱动专用芯片,ME集成FOC、MDU、LPF、PI、SVPWM/SPWM等诸多硬件模块,可硬件自动完成电机FOC/BLDC运算控制,这里购买的是BLDC直流无刷电机,进行调试的。

电机接口电路:

 

霍尔检测电路:

 

功率开关管则直接使用 使用输入电源 电源。同时,该方案采用可变电阻旋钮调节 0~3.3V 的电压输入作为速度命令的输入端, 以此调节电机转速。 

使用可直接通过转动可变电阻旋钮以此调节输入电压,同时当输入电压值超过起动阈值时, 电机将会启动运行, 而当电压值低于阈值时电机将会关闭运行。

电流采样这里采用的是2510封装的采样电路,这里即使电机堵转基本上不会对主控造成影响。

部分电机驱动代码:

void MC_Control(void)

{

    switch (mcState)

    {

        case mcReady:

            Motor_Ready();

            

            if ((mcCurOffset.OffsetFlag == 1) && (MotorSpeed.FlagONOFF == 1))

            {

                mcState = mcInit;

                mcCurOffset.OffsetFlag = 0;

                /**********电机目标方向*************/

                #if(FREnable ==0)

                {

                   MotorSpeed.TargetFR                 = FRMODE;

                }

#else

{

    if (FRPin == 0)                                             //  1:CCW ;0:CW

                    {

                        MotorSpeed.TargetFR  = CW;

                    }

                    else

                    {

                        MotorSpeed.TargetFR  = CCW;

                    }

}

                #endif //end

            }

            

            break;

            

        case mcInit:

            Motor_Init();

            #if (IPMState == IPMtest)                           // 正常按电机状态机运行

            {

                if(mcCurOffset.OffsetFlag == 1)

{

mcState                 = mcCharge;

mcFocCtrl.State_Count   = Charge_Time;

}

            }

            #else

            {

                mcState                 = mcCharge;

                mcFocCtrl.State_Count   = 300;                    //6832可以不需要预充电

            }

            #endif

            break;

            

        case mcCharge:

            Motor_Charge();

            #if (IPMState == NormalRun)                         // 正常按电机状态机运行

            {

                if (mcFocCtrl.State_Count == 0)

                {

                    MOE = 0;

                    mcState = mcTailWind;

                }

            }

            #endif

            break;

            

        case mcTailWind:

            #if (TailWind_Mode == NoTailWind)

            {

                mcState                   = mcPosiCheck;

                mcFocCtrl.State_Count     = 0;

            }

            

            #elif (TailWind_Mode == TailWind)

            {

                Motor_TailWind();

            }

            #endif

            break;

                        

            

        case mcPosiCheck:

            #if (PosCheckEnable==0)                             //初始位置检测不使能时初始角度为预定位角度

            if (mcFocCtrl.State_Count == 0)

            {

                mcFocCtrl.mcPosCheckAngle = 0;

                mcState = mcAlign;

                mcFocCtrl.State_Count = Align_Time;

            }           

            #else

            {

RPDFunctions();

            }

            #endif

            break;

        case mcAlign:

            Motor_Align();

            #if (AlignTestMode == 1)

            {

                while (1);

            }

            #else

            {

                if (mcFocCtrl.State_Count == 0)

                {

#if((PosCheckTestEnable)&&(PosCheckEnable))

{

ClrBit(DRV_CR, DRVEN);

MOE = 0;

FOC_CR1 = 0x00;

ClrBit(DRV_CR, FOCEN);

mcState = mcInit;

}

#else

{

                      mcState = mcStart;

}

#endif

 

                }

            }

            #endif

            break;

            

        case mcStart:

            Motor_Open();

            break;

            

        case mcRun:

            if (MotorSpeed.FlagONOFF == 0)

            {

                mcState = mcStop;

                mcFocCtrl.State_Count = 5000;

            }

            

            break;

            

        case mcStop:

            Motor_Stop();

            

            break;

            

        case mcBrake:

            if (mcFocCtrl.State_Count == 0)

            {

                mcState = mcReady;

                ClrBit(DRV_CR, DRVEN);

                MOE = 0;

                ClrBit(DRV_CR, FOCEN);

            }

            

            break;

            

        case mcFault:

            FaultProcess();

            _nop_();

            break;

            

        default:

            break;

    }

}

 

/*---------------------------------------------------------------------------*/

/*  Name     :   void TailWindSpeedDetect(void)

    /* Input    :   NO

    /* Output   :   NO

    /* Description: 顺逆风速度检测,根据角度的变化趋势来判断方向

    /*---------------------------------------------------------------------------*/

void TailWindSpeedDetect(void)

{

    static int16 LatestTheta;

    

    if (mcState == mcTailWind)

    {

        //顺风检测过程由于FOC内部根据电流估算角度,故直接对FOC_ETHETA进行处理

        if (TailWindDetect.MotorTailWindState == NormalTailWind)

        {

            LatestTheta = FOC__ETHETA;

            

            //旋转方向判断在 <-170度   <10 >-10  >170度三个状态切换的时间

            if (LatestTheta < -30946)

            {

                //计数器未清零或从状态3跳到状态1时清零

                if ((TailWindDetect.SpeedTimerClearStatus == 0) || (TailWindDetect.AngleState == 3))

                {

                    TailWindDetect.SpeedCountTimer       = 0;

                    TailWindDetect.SpeedTimerClearStatus = 1;

                    

                    if (TailWindDetect.AngleState == 3)

                    {

                        TailWindDetect.ShakeTimes ++;    //来回1和3之间抖动,抖动次数加1

                    }

                }

                

                //<-170度  时设置状态为1,并清零SpeedCountTimer在TIM5中计时

                TailWindDetect.AngleState = 1;

            }

            else if ((LatestTheta > -1820) && (LatestTheta < 1820)) //<10 >-10

            {

                //状态1或状态3切换到状态2时保存当前转速时间至TailWindDetect.SpeedCount[SpeedStoreNum]

                if ((TailWindDetect.AngleState == 1) || (TailWindDetect.AngleState == 3))

                {

                    //计算当前转速,RPM

                    TailWindDetect.SpeedCountTimer += 1;//防止为0

                    DivQ_L_MDU(((TailWindDetect.TempThailWindSpeedBase) >> 16), TailWindDetect.TempThailWindSpeedBase, TailWindDetect.SpeedCountTimer, TailWindDetect.TailWindSpeed);

                    TailWindDetect.SpeedStoreNum ++;

                    

                    //用于SpeedCountTimer清零

                    if (TailWindDetect.SpeedTimerClearStatus == 1)

                    {

                        TailWindDetect.SpeedTimerClearStatus = 0;

                    }

                    

                    //有1状态切换到2状态说明角度递增旋转方向为CW,3->2则为CCW

                    if (TailWindDetect.AngleState == 1)

                    {

                        TailWindDetect.MotorDir = CW;

                    }

                    else if (TailWindDetect.AngleState == 3)

                    {

                        TailWindDetect.MotorDir = CCW;

                    }

                    

                    TailWindDetect.ShakeTimes = 0;//清除来回抖动的计数

                }

                

                TailWindDetect.AngleState = 2;

            }

            //>170度时

            else if (LatestTheta > 30946)

            {

                //计数器未清零或从状态1跳到状态3时清零

                if ((TailWindDetect.SpeedTimerClearStatus == 0) || (TailWindDetect.AngleState == 1))

                {

                    TailWindDetect.SpeedCountTimer       = 0;

                    TailWindDetect.SpeedTimerClearStatus = 1;

                    

                    if (TailWindDetect.AngleState == 1)

                    {

                        TailWindDetect.ShakeTimes ++;    //来回1和3之间抖动

                    }

                }

                

                TailWindDetect.AngleState = 3;

            }

        }

    }

}

测试图片如下:

 

 

 

后记:在这里分享一下调试峰绍开发板的心得

需要具备基础知识的重要性

在开始调试之前,确保对BLDC电机的工作原理、电机控制器(如ESC,Electronic Speed Controller)以及电机驱动电路有深入的了解熟悉PWM(脉冲宽度调制)信号、霍尔传感器或反电动势(Back-EMF)检测在电机控制中的作用。

确保电机、控制器和电源之间的连接正确无误,特别是相线(A、B、C)和霍尔传感器的连接。

使用合适的电源为电机供电,避免过压或欠压导致的损坏。

使用示波器或逻辑分析仪检查PWM信号和传感器信号的波形和频率,确保它们处于正常范围内。

软件调试

编写或修改电机控制软件时,确保逻辑清晰、无错误,特别是与电机转动方向和速度控制相关的部分。

使用调试工具(如串口调试助手、JTAG调试器等)监控电机控制器的运行状态和错误信息。

在调试过程中,逐步增加PWM信号的占空比,观察电机的响应,避免突然加速导致的损坏。

电机性能优化

调整PWM信号的频率和占空比,找到电机最佳的运行参数,所以示波器是必不可少的。

如果可能的话,使用更先进的控制算法(如FOC,Field-Oriented Control)来提高电机的效率和性能。这里可以参考开发板的例程,不要指望零基础的情况下,一次就能看的懂,有时间的话,可以多看几遍。

安全性考虑

确保电机和控制器处于通风良好的环境中,避免过热导致的损坏。

在调试完成后,对电机和控制器进行充分的测试,确保其稳定可靠地运行。

最后希望开发板可以将单片机的引脚,利用排针的方式引到芯片的四周,这样对于初学者可以更好的去利用开发板,拥有了一款开发板,就可以利用该开发板去调试其他的功能。

 

一起学习 开发板测评
2024/06/01 14:51
  • 举报
😁😂😃😄😅😆😉😊😋😌😍😏😒😓😔😖😘😚😜😝😞😠😡😢😣😤😥😨😩😪😫😭😰😱😲😳😵😷😸😹😺😻😼😽😾😿🙀🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏✂✅✈✉✊✋✌✏✒✔✖✨✳✴❄❇❌❎❓❔❕❗❤➕➖➗➡➰🚀🚃🚄🚅🚇🚉🚌🚏🚑🚒🚓🚕🚗🚙🚚🚢🚤🚥🚧🚨🚩🚪🚫🚬🚭🚲🚶🚹🚺🚻🚼🚽🚾🛀Ⓜ🅰🅱🅾🅿🆎🆑🆒🆓🆔🆕
@好友

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
发布者
聪聪哥哥
最新帖子
树莓派pico 2测评 - 初体验【工程师经验】+ 飞线【开源】zvs142857 2.1A,3A快充 充电宝迷你UC3842 开关电源优化全解析:攻克常见难题,提升性能飞腾CPU × DeepSeek大模型,双芯加持全系列稳跑
热门版块
查看更多
电子DIY
电子元器件
维修技术
抄图联盟
汽车电子工程师论坛
工业电子专区
新手入门指南
单片机/MCU论坛
PCB设计
开源项目

92

收藏

分享

微信扫码
分享给好友

评论