峰岹科技
直播中

zxwzxs

9年用户 10经验值
擅长:电源/新能源 模拟技术 EMC/EMI设计 控制/MCU
私信 关注
[问答]

FU6812做高压无感FOC吊扇控制,电机检测问题

FU6812做高压无感FOC吊扇控制,怎么在上电后快速检测是否有插电机?缺相是启动后检测,但不插电机需要报故障怎么检测?

/*---------------------------------------------------------------------------*/
/* Name		:	void Fault_Detection(void)
/* Input	:	NO
/* Output	:	NO
/* Description:	保护函数,因保护的时间响应不会很高,采用分段处理,每5个定时器中断执行一次对应的保护
	              常见保护有过欠压、过温、堵转、启动、缺相等保护,调试时,可根据需求,一个个的调试加入。
/*---------------------------------------------------------------------------*/
void Fault_Detection(void)
{
    mcFaultDect.segment++;
    if(mcFaultDect.segment>=5)
    {
        mcFaultDect.segment=0;
    }
    if(mcFaultDect.segment==0)
    {
        if(CurrentRecoverEnable)//过流保护恢复使能
        {
            Fault_OverCurrentRecover(&mcFaultDect);
        }
    }
    else if(mcFaultDect.segment==1)
    {
        if(VoltageProtectEnable==1)//过压保护使能
        {
            Fault_OverUnderVoltage(&mcFaultDect);
        }
    }
    else if(mcFaultDect.segment==2)
    {
        if(StartProtectEnable==1)//启动保护使能
        {
			 	  Fault_Start(&mcFaultDect);
        }
    }
    else if(mcFaultDect.segment==3)
    {
        if(StallProtectEnable==1)//堵转保护使能
        {
            Fault_Stall(&mcFaultDect);
        }
    }
    else if(mcFaultDect.segment==4)
    {
        if(PhaseLossProtectEnable==1)//缺相保护使能
        {
            Fault_phaseloss(&mcFaultDect);
        }
    }
    else
    {
        
    }
}
/*****************************************************************************
 * Function:		 void	Fault_phaseloss(mcFaultVarible *h_Fault)
 * Description:	 缺相保护函数,当电机运行状态下,10ms取三相电流的最大值,
	               1.5s判断各相电流最大值,若存在两相电流值大于一定值,而第三相电流值却非常小,则判断为缺相保护,电机停机;
 * Parameter:		 mcFaultVarible *h_Fault
 * Return:			 no
 *****************************************************************************/
  void Fault_phaseloss(FaultVarible *h_Fault)
  {
    if(mcState == mcRun)
    {
        h_Fault->Lphasecnt++;
        if(h_Fault->Lphasecnt>100)//100*5=500ms
        {
            h_Fault->Lphasecnt=0;
            if((mcCurVarible.Max_ia<PhaseLossLowCurrent)&&(mcCurVarible.Max_ib>PhaseLossHighCurrent)&&(mcCurVarible.Max_ic>PhaseLossHighCurrent))
            {
                h_Fault->AOpencnt++;
            }
            else
            {
                h_Fault->AOpencnt =0;
            }
            if((mcCurVarible.Max_ib<PhaseLossLowCurrent)&&(mcCurVarible.Max_ia>PhaseLossHighCurrent)&&(mcCurVarible.Max_ic>PhaseLossHighCurrent))
            {
                h_Fault->BOpencnt++;
            }
            else
            {
                if(h_Fault->BOpencnt>0)
                    h_Fault->BOpencnt --;
            }
            if((mcCurVarible.Max_ic<PhaseLossLowCurrent)&&(mcCurVarible.Max_ib>PhaseLossHighCurrent)&&(mcCurVarible.Max_ia>PhaseLossHighCurrent))
            {
                h_Fault->COpencnt++;
            }
            else
            {
                if(h_Fault->COpencnt>0)
                    h_Fault->COpencnt --;
            }
            mcCurVarible.Max_ia = 0;
            mcCurVarible.Max_ib = 0;
            mcCurVarible.Max_ic = 0;
            if(h_Fault->AOpencnt > 1|| h_Fault->BOpencnt > 1 || h_Fault->COpencnt > 1)
            {
                mcProtectTime.LossPHTimes++;
                mcFaultSource=FaultLossPhase;
                FaultProcess();
                SetBuzzer(1, 1, 2);     //蜂鸣器响两声	
            }
        }
    }

    #if (!StartONOFF_Enable)
    {
        /*******缺相保护恢复*********/
        if((mcFaultSource==FaultLossPhase)&&(mcState == mcFault)&&
        (mcProtectTime.LossPHTimes<5))//可重启5次
        {
            h_Fault->mcLossPHRecCount++;
            if(h_Fault->mcLossPHRecCount>=PhaseLossRecoverTime)
            {
            h_Fault->AOpencnt=0;
            h_Fault->BOpencnt=0;
            h_Fault->COpencnt=0;
            mcState = mcReady;
            mcFaultSource=FaultNoSource;
            }
        }
        else
        {
            h_Fault->mcLossPHRecCount=0;
        }
    }
    #endif

  }
/*---------------------------------------------------------------------------*/
/* Name     :   void MC_Control(void)
/* Input    :   NO
/* Output   :   NO
/* Description: 电机状态机函数,包括初始化、预充电、顺风逆风判断、预定位、启动、运行、故障等
/*---------------------------------------------------------------------------*/
void MC_Control(void)
{
    switch(mcState)
    {
        case mcReady:    // 关闭输出,上电会对电流进行采集校准,当采样校准结束标志置1且启动指令置1后,才跳转到mcInit
            Motor_Ready();
            if((mcCurOffset.OffsetFlag == 1) && (mcSpeedRamp.FlagONOFF == 1)) mcState = mcInit;
        break;

        case mcInit:                          					// 初始化状态,进入mcCharge状态
            Motor_Init();
            FOC_Init();
            mcState		= mcCharge;
            mcFocCtrl.State_Count = 0;
//            mcState               =  mcCharge;					// 跳入mcCharge状态
//            mcFocCtrl.State_Count = Charge_Time;
        break;

        case mcCharge:											// 预充电状态,MCU输出固定频率占空比,预充电结束后,跳入mcTailWind
            Motor_Charge();
            #if (IPMState == NormalRun)							// 正常按电机状态机运行
			if( mcFocCtrl.State_Count == 0)
			{
				//顺逆风检测
				if(mcFocCtrl.mcChargeStep == 0)
				{
					MOE = 0;										// 关闭输出
					mcState		= mcTailWind;
          mcFocCtrl.State_Count = 40;
				}
				//初始位置检测启动
				else if(mcFocCtrl.mcChargeStep == 1)
				{
					MOE = 0;
					mcState = mcPosiCheck;
				}
//                GP07 = 0;
			}

            #endif
        break;

        case mcTailWind:
            #if (TailWind_Mode == NoTailWind)					// 无顺逆风处理的,直接跳入下一个状态
                mcState                           = mcPosiCheck;
                McStaSet.SetFlag.PosiCheckSetFlag = 0;
                mcFocCtrl.mcPosCheckAngle         = 0xffff;		// 角度赋初值

            #elif (TailWind_Mode == TailWind)
                Motor_TailWind();

            #endif
        break;

        case mcPosiCheck:
            #if (PosCheckEnable==0)								//初始位置检测不使能时初始角度为预定位角度
                mcFocCtrl.mcPosCheckAngle = Align_Angle;
                mcState = mcAlign;
                mcFocCtrl.State_Count = Align_Time;

            #else
                RPD();

            #endif
        break;

        case mcAlign:       // 预定位时间结束后,直接启动; AlignTestMode=1用于初始位置检测调试用
            Motor_Align();

            #if (AlignTestMode==1)
                while(1);

            #else
                if(mcFocCtrl.State_Count == 0) mcState = mcStart;

            #endif
        break;

        case mcStart:                           // 配置电机启动参数,进入mcRun状态。
            Motor_Open();
        break;

        case mcPllTect:                           // 配置电机启动参数,进入mcRun状态。
            #if (EstimateAlgorithm == PLL)
                Motor_PllStart();
            #endif
        break;

        case mcRun:                             // 运行状态,若运行状态的给定变为0,进入mcStop状态。
            if(mcSpeedRamp.TargetValue == 0)
            {
                mcState               = mcStop;
                mcFocCtrl.State_Count = 6000;
//              FOC_IQREF             = 0;
            }
        break;

        case mcStop:
            if((mcFocCtrl.SpeedFlt<Motor_Min_Speed)||(mcFocCtrl.State_Count==0))
            {
                #if (StopBrakeFlag == 0)
                    if(mcFocCtrl.mcIqref > POWER_OFF_CURRENT)			//小于最小电流
                    {
                        mcFocCtrl.mcIqref-= 5;
                        FOC_IQREF = mcFocCtrl.mcIqref;	
                        PI_UK	  =	mcFocCtrl.mcIqref;
                    }
                    else
                    {
											//直接关闭,自由停止
                        mcState = mcReady;
                        MOE=0;
                        FOC_CR1 = 0x00;
                        /*关闭FOC*/
                        ClrBit(DRV_CR, FOCEN);
											
											//刹车后再关闭
//												MOE = 0;
//                        FOC_CR1 = 0x00;
//                        ClrBit(DRV_CR, FOCEN);
//                        DRV_DR  = DRV_ARR+1;
//                        DRV_CMR &= 0xFFC0;
//                        DRV_CMR |= 0x015;            // 三相下桥臂通,刹车
//                        ClrBit(DRV_CR, OCS);         // OCS = 0, DRV_COMR;OCS = 1, FOC/SVPWM/SPWM
//                        MOE = 1;
//                        mcState               = mcBrake;
//                        mcFocCtrl.State_Count = StopWaitTime;
                    }

                #else
                    if(mcFocCtrl.SpeedFlt < Motor_Stop_Speed)			//小于最低速度刹车
                    {
                        MOE = 0;
                        FOC_CR1 = 0x00;
                        ClrBit(DRV_CR, FOCEN);
                        DRV_DR  = DRV_ARR+1;
                        DRV_CMR &= 0xFFC0;
                        DRV_CMR |= 0x015;            // 三相下桥臂通,刹车
                        ClrBit(DRV_CR, OCS);         // OCS = 0, DRV_COMR;OCS = 1, FOC/SVPWM/SPWM
                        MOE = 1;
                        mcState               = mcBrake;
                        mcFocCtrl.State_Count = StopWaitTime;
                    }

                #endif
            }
            else if(mcSpeedRamp.TargetValue > 0)
            {
                mcState            = mcRun;
								mcFocCtrl.State_Count = 0;
//                mcFocCtrl.CtrlMode = 0;
            }
        break;

        case mcBrake:
            if(mcFocCtrl.State_Count == 0)
            {
                mcState = mcReady;
                MOE=0;
                ClrBit(DRV_CR, FOCEN);
            }
        break;

        case mcFault:
        break;
    }
}

回帖(1)

jf_15925133

2022-12-16 10:34:29
不插电机为什么需要报缺相检测?最高效的办法就是进入仿真去查看,可以看到错误状态
举报

更多回帖

发帖
×
20
完善资料,
赚取积分