芯查查logo
  • 物料选型
  • 数据服务
    1. 新品推荐
    2. 查替代料
    3. 丝印反查
    4. 查品牌
    5. PCN/PDN
    6. 查代理
    7. 数据合作
  • 应用方案
  • SaaS产品
      SaaS产品
    1. 供应链波动监测预警
    2. 半导体产业链地图
    3. 智能BOM管家
    4. 解决方案
    5. 汽车电子
    6. 政府机构
    7. 数据API
  • 商城
  • 资讯与直播
    1. 资讯
    2. 直播
  • 论坛社区
    1. 论坛
    2. 学习
    3. 测评中心
    4. 活动中心
    5. 积分商城
  • 查一下
正在使用账号登录iCEasy商城
meiyao
【峰岹科技_FU6832L_V3开发板】BLDC电机驱动

 

先了解一下FU6832的相关性能与一些配置,具体如下:

 FU6832系列电机驱动专用芯片集成了电机控制引擎(ME)和8051内核,为电机控制提供了高性能的解决方案。这款芯片特别适用于无刷直流电机(BLDC)和永磁同步电机(PMSM)的驱动控制,支持方波、空间矢量脉宽调制(SVPWM)/正弦脉宽调制(SPWM)以及磁场定向控制(FOC)等多种控制策略。 

主要特性: 

双核并行工作:ME引擎负责电机控制的复杂运算,而8051内核则用于参数配置和日常事务处理,提高了整体性能和响应速度。 高速指令执行:8051内核大部分指令周期为1T或2T,保证了快速的数据处理和参数更新。 

集成的硬件模块:FOC、MDU、LPF、PI、SVPWM/SPWM等硬件模块可自动完成电机控制的核心运算,简化了软件开发的复杂性。 

核心组成:FU6832L芯片集成了电机控制引擎(ME)和8051内核,实现了双核并行工作。 8051内核:大部分指令周期为1T或2T,支持高速的数据处理和参数配置。

 ME特性:集成有FOC(磁场定向控制)、MDU(电机驱动单元)、LPF(低通滤波器)、PI(比例积分控制器)、SVPWM/SPWM(空间矢量脉宽调制/正弦脉宽调制)等硬件模块,可自动完成电机FOC/BLDC运算控制。 多种通信接口:CRC、SPI、I2C、UART、LIN等通信接口使得芯片能够方便地与其他设备进行数据交换。 

内置功能丰富:芯片内部集成了高速运算放大器、比较器、Pre-driver、高速ADC、高速乘/除法器等,为电机控制提供了强大的硬件支持。 无感运行FOC驱动:有感启动后,可切换至无感运行状态,降低了对传感器的依赖,提高了系统的可靠性。 

有感启动无感运行FOC驱动的使用方法: 初始化配置:使用8051内核对芯片进行初始化配置,包括设置通信接口、配置电机参数、选择控制模式等。 无感运行:当电机达到稳定运行状态后,可切换至无感运行模式,此时不再依赖传感器提供的位置和速度信息,而是通过ME引擎根据电机的电气参数进行估算和控制。 实时调整:在电机运行过程中,8051内核可以根据需要实时调整控制参数,电流、速度、转矩等,以满足不同的应用需求。 

以上是对FU6832L_V3开发板的具体介绍,下面开始对BLDC电机驱动详细说明:

1、原理图:

 

MOS管在BLDC电机驱动电路中的主要作用是作为开关元件,通过控制其通断来驱动电机三相绕组的电流。

  • 通过精确控制MOS管的开关状态,可以实现电机的高效率、高精度驱动。
  • 在选择适用于BLDC电机驱动的MOS管时,需要考虑多个参数,输入电压、输出电压、电源电压范围、静态功耗、动态功耗、频率响应、输入电阻和输出电阻以及电机工作电压等。
  • 这些参数的选择需要根据电机的具体需求和驱动电路的设计来确定。BLDC电机驱动电路通常采用三相全桥结构,其中每一相都包含两个MOS管(一个上桥臂和一个下桥臂)上图所示。
  • 通过控制这三个上桥臂和三个下桥臂的MOS管开关状态,可以实现电机三相绕组的电流控制。

 

霍尔检测电路接口

保护电路:防止电压超过霍尔传感器的工作电压范围。

上拉电阻(R12/14/15):确保在没有磁场作用时,霍尔传感器的输出处于确定状态。

限流电阻(R22/19/16):限制通过霍尔传感器的电流,以保护其免受损坏。

滤波电容(C2/19/17):滤除噪声和杂散信号,提高测量的准确性和稳定性。

测量电路:接收霍尔电势差并进行放大和测量,最终得到与磁场强度成正比的电压信号。

 

主控:

BLDC电机FU6832L主控是一款高性能的电机驱动专用芯片,专为BLDC(Brushless Direct Current,无刷直流)电机控制而设计。

 

代码:

 

电机控制状态机 , 电机的状态只能在电机状态控制中切换,禁止在其他地方切换电机状态

void MC_Control(void)

{

// 根据mcState的值来决定执行哪个case

switch (mcState)

{

case mcReady: // 如果当前状态是mcReady

Motor_Ready(); // 执行电机就绪操作

 

// 如果存在故障源(mcFaultSource不等于FaultNoSource)

if (mcFaultSource != FaultNoSource)

{

// 将状态设置为mcFault

mcState = mcFault;

}

// 如果电流偏移标志被设置(OffsetFlag为1),并且控制电源已开启(isCtrlPowOn为true)

// 并且直流母线电压在恢复阈值范围内(mcDcbusFlt在OVER_VOLTAGE_RECOVER和UNDER_VOLTAGE_RECOVER之间)

else if ((mcCurOffset.OffsetFlag == 1) && (isCtrlPowOn == true) &&

(mcFocCtrl.mcDcbusFlt < OVER_VOLTAGE_RECOVER) &&

(mcFocCtrl.mcDcbusFlt > UNDER_VOLTAGE_RECOVER))

{

// 将状态设置为mcInit,并重置电流偏移标志和计数

mcState = mcInit;

mcCurOffset.OffsetFlag = 0;

mcCurOffset.OffsetCount = 0;

}

break; // 结束mcReady的case

 

case mcInit: // 如果当前状态是mcInit

// 如果存在故障源(mcFaultSource不等于FaultNoSource)

if (mcFaultSource != FaultNoSource)

{

// 将状态设置为mcFault

mcState = mcFault;

}

// 如果控制电源已关闭(isCtrlPowOn为false)

else if (isCtrlPowOn == false)

{

// 将状态设置为mcStop

mcState = mcStop;

}

else

{

// 执行电机初始化操作

Motor_Init();

 

#if (CHARGE_EN == Enable)

mcFocCtrl.State_Count = CHARGE_TIME;

mcState = mcCharge; // 跳入mcCharge状态

#else

#if (TAILWIND_MODE == NoTailWind)

#if (PosCheckEnable == Enable)

mcState = mcPosiCheck;

McStaSet.SetFlag.PosiCheckSetFlag = 0;

mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值

#elif (ALIGN_MOME != ALIGN_DSIABLE)

mcFocCtrl.mcPosCheckAngle = Align_Angle;

mcState = mcAlign;

mcFocCtrl.State_Count = Align_Time;

#else

mcState = mcStart;

#endif

#else

mcFocCtrl.State_Count = TAILWIND_TIME; //顺逆风判断时间

mcState = mcTailWind;

#endif

#endif

 

}

 

break;

 

case mcCharge:

 

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (isCtrlPowOn == false)

{

mcState = mcStop;

}

else

{

Motor_Charge();

 

if (mcFocCtrl.State_Count == 0)

{

MOE = 0; // 关闭输出

#if (TAILWIND_MODE == NoTailWind)

#if (PosCheckEnable == Enable)

mcState = mcPosiCheck;

McStaSet.SetFlag.PosiCheckSetFlag = 0;

mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值

#elif (ALIGN_MOME != ALIGN_DSIABLE)

mcFocCtrl.mcPosCheckAngle = Align_Angle;

mcState = mcAlign;

mcFocCtrl.State_Count = Align_Time;

#else

mcState = mcStart;

#endif

#else

mcFocCtrl.State_Count = TAILWIND_TIME; //顺逆风判断时间

mcState = mcTailWind;

#endif

}

}

break;

 

#if (TAILWIND_MODE != NoTailWind)

case mcTailWind:

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (isCtrlPowOn == false)

{

mcState = mcStop;

}

else

{

if (McStaSet.SetFlag.TailWindSetFlag == 0) //初始化

{

SetBit(DRV_CR , DRVEN); // 计数器使能 0-->Disable 1-->Enable

McStaSet.SetFlag.TailWindSetFlag = 1;

#if (TAILWIND_MODE == RSDMethod)

RSDDetectInit();

#elif (TAILWIND_MODE == BEMFMethod)

BEMFDetectInit();

#endif

}

 

#if (TAILWIND_MODE == RSDMethod)

if (mcFocCtrl.State_Count > 0) // 顺逆风检测时间结束前判断转速

{

mcState = RSDStartProcess();

}

else // 时间结束 还未检测到有效转速 则当做静止启动

{

ClrBit(CMP_CR2, CMP0EN); // 关闭比较器

ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数

mcFocCtrl.Start_Mode = STATIC_START;

#if (PosCheckEnable == Enable)

mcState = mcPosiCheck;

McStaSet.SetFlag.PosiCheckSetFlag = 0;

mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值

#elif (ALIGN_MOME != ALIGN_DSIABLE)

mcFocCtrl.mcPosCheckAngle = Align_Angle;

mcState = mcAlign;

mcFocCtrl.State_Count = Align_Time;

#else

mcState = mcStart;

#endif

}

#elif (TAILWIND_MODE == BEMFMethod)

if (mcFocCtrl.State_Count > 0) // 顺逆风检测时间结束前判断转速

{

mcState = Bemf_Start_Process();

}

else // 时间结束 还未检测到有效转速 则当做静止启动

{

ClrBit(CMP_CR2, CMP0EN); // 关闭比较器

ClrBit(TIM1_CR0, T1BCEN); // 关闭定时器

mcFocCtrl.Start_Mode = STATIC_START;

#if (PosCheckEnable == Enable)

mcState = mcPosiCheck;

McStaSet.SetFlag.PosiCheckSetFlag = 0;

mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值

#elif (ALIGN_MOME != ALIGN_DSIABLE)

mcFocCtrl.mcPosCheckAngle = Align_Angle;

mcState = mcAlign;

mcFocCtrl.State_Count = Align_Time;

#else

mcState = mcStart;

#endif

}

#endif

 

}

break;

#endif

 

#if (PosCheckEnable == Enable)

case mcPosiCheck:

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (isCtrlPowOn == false)

{

mcState = mcStop;

}

else

{

if (mcFocCtrl.State_Count == 0)

{

mcFocCtrl.mcPosCheckAngle = 0;

mcState = mcAlign;

mcFocCtrl.State_Count = Align_Time;

}

}

 

break;

#endif

 

#if (ALIGN_MOME != ALIGN_DSIABLE)

case mcAlign:

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (isCtrlPowOn == false)

{

mcState = mcStop;

}

else

{

Motor_Align();

 

#if (ALIGN_MOME == ALIGN_TEST)

 

while (1);

 

#else

 

if (mcFocCtrl.State_Count == 0)

{

mcState = mcStart;

}

 

#endif

}

 

break;

#endif

case mcStart:

 

if (mcFocCtrl.Start_Mode == TAILWIND_START) // 顺风启动

{

#if (TAILWIND_MODE == BEMFMethod)

mcState = mcRun;

#elif (TAILWIND_MODE == RSDMethod)

mcState = mcRun;

#endif

}

else if (mcFocCtrl.Start_Mode == HEADWIND_START) // 逆风启动

{

if(mcFocCtrl.State_Count > 0) // 逆风启动刹车过程

{

// 配置刹车代码

MC_Break();

}

else

{

mcFocCtrl.State_Count =100; // 顺逆风判断时间

mcState = mcReady; // 刹车结束 切回顺逆风检测

}

 

}

else // 静止启动

{

Motor_Static_Open();

mcState = mcRun;

}

 

break;

 

case mcRun:

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (isCtrlPowOn == false)

{

mcState = mcStop;

mcFocCtrl.State_Count = 10; //单位:1ms

 

}

break;

case mcStop:

// if (mcFaultSource != FaultNoSource)

// {

// mcState = mcFault;

// }

// else

// {

if (( mcFocCtrl.PowerFlt < Motor_Max_Power) || (mcFocCtrl.State_Count == 0))

{

if (StopBrakeFlag == 0)

{

mcState = mcReady;

// MOE = 0;

FOC_CR0 = 0x00;

ClrBit(DRV_CR, FOCEN);

}

else

{

 

// if (mcFocCtrl.SpeedFlt < Stop_MOTOR_SPEED_RPM)

// {

MOE = 0;

MC_Break(); // 配置刹车代码

mcState = mcBrake;

mcFocCtrl.State_Count = StopWaitTime;

// }

}

 

}

// }

 

break;

 

case mcBrake:

if (mcFaultSource != FaultNoSource)

{

mcState = mcFault;

}

else if (mcFocCtrl.State_Count == 0)

{

MOE = 0;

 

ClrBit(DRV_CR, FOCEN);

mcState = mcReady;

}

 

break;

 

case mcFault:

if (mcFaultSource == FaultNoSource) //保护清零后关闭输出,软件重新运行

{

mcState = mcReady;

}

else

{

Pdelay_OFF;

ClrBit(DRV_CR, FOCEN); //FOC Disable

MOE = 0;

}

 

break;

 

default:

 

mcState = mcReady;

break;

}

}

 

 

 

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;

            }

        }

    }

}

 

 

主函数:

 

uint32 PowerUpCnt = 0;

 

/* ----- 上电空指令延时 等待系统稳定 ----- */

for (PowerUpCnt = 0; PowerUpCnt < SystemPowerUpTime; PowerUpCnt++);

 

/* ----- 部分变量初始化 ----- */

SoftwareInit();

 

/* ----- 硬件初始化,配置MCU外设 ----- */

HardwareInit();

 

/* ----- 等待硬件初始化稳定 ----- */

for (PowerUpCnt = 0; PowerUpCnt < SystemPowerUpTime; PowerUpCnt++);

 

 

// #if (DBG_MODE != DBG_DISABLE) // 调试小工具

// /* -----debug配置(SPI调试),量产程序可以删除----- */

// DebugSet();

// #endif

// SetReg(CMP_CR3, DBGSEL1 | DBGSEL0, DBGSEL1); // ADC trig

 

while (1)

{

 

/* -----获取电流采样偏置电压----- */

if (!mcCurOffset.OffsetFlag)

{

GetCurrentOffset();

}

else

{

/* -----电机控制状态机----- */

MC_Control();

mcFocCtrl.mcUqvlue = FOC__UQ;

mcFocCtrl.mcUdvlue = FOC__UD;

 

if (g_1mTick)

{

TickCycle_1ms();

g_1mTick = 0;

}

 

}

}

}

 

 

视频:

实际波形:

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

全部评论

加载中
游客登录通知
已选择 0 人
自定义圈子
移动
发布帖子
发布动态
发布问答
最新帖子
SWIR051AU短波红外相机进行橘子品质检测成像实验分享昨天的12V-3A,15V-3A,18V-3A碳化硅方案原理图和PCB文件大靶面短波红外相机选型指南大靶面短波红外相机推荐:SWIR151BU1900nm拓展波段短波红外相机选型参考
热门版块
查看更多
Arduino
萤火工场
开发板测评与实战
问型号
飞腾
开源硬件项目
每日打卡
电子DIY
维修技术交流
抄图联盟

257

收藏

分享

微信扫码
分享给好友

评论