原理:转子电角度旋转一圈为360度,hall传感器根据转子位置可以输出6种不同的编码代表6个不同的扇区。
通过测量转子在每一个扇区的时间估算出转子速度,根据速度估算出电角度。当发生扇区切换时校准转子电角度。
代码:
void HALL_GetCaptCounter(void)
{
Hall_Counter++;//
Hall_Now_State = ReadHallState(); //
if(Hall_Now_State==Hall_Old_State)
{
Hall_State=Hall_Now_State;
}
Hall_Old_State=Hall_Now_State;
Hall_Sector=Hall_to_Sector[Hall_State];
if((Hall_Counter==0x3FF)||(Old_Hall_Sector!=Hall_Sector)) //判断是否发生扇区切换
{
if((Hall_Sector == (Old_Hall_Sector+1))||(Old_Hall_Sector==5&&Hall_Sector==0)) //正转
Hall_DIR_Temp= 1;
else if((Hall_Sector == (Old_Hall_Sector-1))||(Old_Hall_Sector==0&&Hall_Sector==5)) //反转
Hall_DIR_Temp= -1;
else
Hall_DIR_Temp=0;
Hall_Dir_SUM_1=Hall_Dir_SUM_1+Hall_DIR_Temp-Hall_DirFIFO_1[CaptCounter_1];
Hall_DirFIFO_1[CaptCounter_1]= Hall_DIR_Temp;
Hall_Speed_SUM_1=Hall_Speed_SUM_1+Hall_Counter-Hall_SpeedFIFO_1[CaptCounter_1];
Hall_SpeedFIFO_1[CaptCounter_1]=Hall_Counter;
///霍尔错误检测
if(Old_Hall_Sector==0)
{
Hall_Sector_N=Old_Hall_Sector+1;
Hall_Sector_P=5;
}
else if(Old_Hall_Sector==5)
{
Hall_Sector_N=0;
Hall_Sector_P=Old_Hall_Sector-1;
}
else
{
Hall_Sector_N=Old_Hall_Sector+1;
Hall_Sector_P=Old_Hall_Sector-1;
}
if((Hall_Counter<0x2FF)&&(State==RUN))//
{
if((Hall_Sector==Hall_Sector_N)||(Hall_Sector==Hall_Sector_P))
{}
else
{
Hard_SetFault(HALL_ERROR);
}
}
if(((Hall_Sector==6)||(Hall_Sector==7))&&(State != IDLE))
{
Hard_SetFault(HALL_ERROR);
}
霍尔速度计算
Hall_Speed=(s32)(0x2AAA*16)*Hall_Dir_SUM_1/Hall_Speed_SUM_1; //扇区角度0~65536 每一个扇区的角度为0x2AAA;
SpeedCtrl_State=1; //平滑力矩使用
MotorData.PresentSpeed = ((s32)Hall_Speed*SystemValues.PWMFrequency*10)>>20;//0.1Hz 当前速度 >>20单位转换。 10电机极对数
MotorData.SpeedAcc = MotorData.PresentSpeed - MotorData.OldSpeed; //平滑力矩使用
MotorData.OldSpeed = MotorData.PresentSpeed;
Hall_DIR_TempOld=Hall_DIR_Temp;
Hall_Angle_SPEED = Hall_Speed;
Hall_Counter=0;
CaptCounter_1++;
if(CaptCounter_1>=6)
{
CaptCounter_1=0;
}
Old_Hall_Sector=Hall_Sector;
}
Virtual_Electrical_Angle = Virtual_Electrical_Angle + (Hall_Angle_SPEED>>4);//+((Err_Theta_SUM-50000)>>12); 估算电角度
Virtual_Sector = ((u32)Virtual_Electrical_Angle*24)>>16;
//启动
switch(Hall_Sector) //当发生扇区切换的时候,校准电角度
{
case 0:
if(Virtual_Sector>=14) //从非0扇区区正转进入0扇区
{
Virtual_Electrical_Angle=0;
}
else if( Virtual_Sector<=13&&Virtual_Sector>=4) //从非0扇区区反转进入0扇区
{
Virtual_Electrical_Angle=0x2AAA;
}
break;
case 1:
if((Virtual_Sector<4)||(Virtual_Sector<=23&&Virtual_Sector>=18))
{
Virtual_Electrical_Angle=0x2AAB;
}
else if(Virtual_Sector>=8&&Virtual_Sector<=17 )
{
Virtual_Electrical_Angle=0x5555;
}
break;
case 2:
if((Virtual_Sector<8)||(Virtual_Sector<=23&&Virtual_Sector>=22))
{
Virtual_Electrical_Angle=0x5556;
}
else if(Virtual_Sector>=12&&Virtual_Sector<=21)
{
Virtual_Electrical_Angle=0x7FFF;
}
break;
case 3:
if(Virtual_Sector<12&&Virtual_Sector>=2)
{
Virtual_Electrical_Angle=0x8000;
}
else if((Virtual_Sector>=16)||(Virtual_Sector<=1))
{
Virtual_Electrical_Angle=0xAAAA;
}
break;
case 4:
if(Virtual_Sector<16&&Virtual_Sector>=6)
{
Virtual_Electrical_Angle=0xAAAB;
}
else if((Virtual_Sector>=20)||(Virtual_Sector<=5))
{
Virtual_Electrical_Angle=0xD555;
}
break;
case 5:
if(Virtual_Sector<20&&Virtual_Sector>=10)
{
Virtual_Electrical_Angle=0xD556;
}
else if(Virtual_Sector<=9)
{
Virtual_Electrical_Angle=0xFFFF;
}
break;
}
HALL_PG(); //输出PG信号 用于里程计算
}
————————————————
版权声明:本文为CSDN博主「电机控制duking」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/oJianZhiTianYa1/article/details/45477005