一种基于霍尔传感器的电机转子转速的测量

来源:互联网 发布:windows系统的手机 编辑:程序博客网 时间:2024/04/25 16:42

原理:转子电角度旋转一圈为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信号    用于里程计算 

}

0 0