무 브러시 직류전기 학습 노트

49291 단어
내용
이번 호의 학습 내용은 주로 원리를 결합하여 PMSM에 호르 센서와 무호르 센서가 프로그램에서의 차이를 비교하면 호르 센서 프로그램에서 속도/위치 검측과 관련된 코드를 가지고 학습한다.
2. 지식점
1. 호르 센서 프로그램에서 속도/위치 감지
PMSM에 호르 센서가 있는 프로그램에서 주 함수에 HALL 이 정의되어 있음SENSORS의 경우 HALLHallTimerInit() 함수, 코드는 다음과 같습니다.
#elif defined HALL_SENSORS
HALL_HallTimerInit();
#endif
   HALL_HallTimerInit()                      ,            ,        :
void HALL_HallTimerInit(void)
{
  TIM_TimeBaseInitTypeDef
  TIM_HALLTimeBaseInitStructure;
  TIM_ICInitTypeDef  TIM_HALLICInitStructure;
  NVIC_InitTypeDef  NVIC_InitHALLStructure;
  GPIO_InitTypeDef  GPIO_InitStructure;
  #if defined(TIMER2_HANDLES_HALL)
    /* TIM2 clock source enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    /* Enable GPIOA, clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_StructInit(&GPIO_InitStructure);
    /* Configure PA.00,01 ,02 as Hall sensors input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;// GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    #elif defined(TIMER3_HANDLES_HALL)
      GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
      /* TIM3 clock source enable */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
      /* Enable GPIOA, clock */
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,
ENABLE);
    /* Enable GPIOB, clock */
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    GPIO_StructInit(&GPIO_InitStructure);
    /* Configure PA.06,07  PB.00 as Hall sensors input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7| GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    //GPIO_Init(GPIOB,&GPIO_InitStructure);
    #else // TIMER4_HANDLES_HALL
    /* TIM4 clock source enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
    /* Enable GPIOB, clock */   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /* Configure PB.06,07,08 as Hall sensors input */      
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6,GPIO_Pin_7, GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);       
  #endif
    // Timer configuration in Clear on capture mode
    TIM_DeInit(HALL_TIMER);
    TIM_TimeBaseStructInit(&TIM_HALLTimeBaseInitStructure);
    // Set full 16-bit working range
    TIM_HALLTimeBaseInitStructure.TIM_Period = U16_MAX;
    TIM_HALLTimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(HALL_TIMER,&TIM_HALLTimeBaseInitStructure);
    TIM_ICStructInit(&TIM_HALLICInitStructure);
    TIM_HALLICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_HALLICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
    TIM_HALLICInitStructure.TIM_ICFilter = ICx_FILTER;   
    TIM_ICInit(HALL_TIMER,&TIM_HALLICInitStructure);
    // Force the HALL_TIMER prescaler with immediate access (no need of an update event) 
    TIM_PrescalerConfig(HALL_TIMER,(u16)HALL_MAX_RATIO,TIM_PSCReloadMode_Immediate);
    TIM_InternalClockConfig(HALL_TIMER);
    //Enables the XOR of channel 1, channel2 and channel3
    TIM_SelectHallSensor(HALL_TIMER, ENABLE);
    TIM_SelectInputTrigger(HALL_TIMER,TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(HALL_TIMER,TIM_SlaveMode_Reset);
    // Source of Update event is only counter overflow/underflow
    TIM_UpdateRequestConfig(HALL_TIMER,TIM_UpdateSource_Regular);
    /* Enable the HALL_TIMER IRQChannel*/
    #if defined(TIMER2_HANDLES_HALL)
    NVIC_InitHALLStructure.NVIC_IRQChannel = TIM2_IRQChannel;
    #elif defined(TIMER3_HANDLES_HALL)
    NVIC_InitHALLStructure.NVIC_IRQChannel = TIM3_IRQChannel;
    #else //TIMER4_HANDLES_HALL
    NVIC_InitHALLStructure.NVIC_IRQChannel = TIM4_IRQChannel;
   #endif
   NVIC_InitHALLStructure.NVIC_IRQChannelPreemptionPriority =                                             TIMx_PRE_EMPTION_PRIORITY;
   NVIC_InitHALLStructure.NVIC_IRQChannelSubPriority = TIMx_SUB_PRIORITY;
   NVIC_InitHALLStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitHALLStructure);
   // Clear the TIMx's pending flags
   TIM_ClearFlag(HALL_TIMER, TIM_FLAG_Update + TIM_FLAG_CC1 + TIM_FLAG_CC2 + \TIM_FLAG_CC3 + TIM_FLAG_CC4 + TIM_FLAG_Trigger +TIM_FLAG_CC1OF +  \TIM_FLAG_CC2OF + TIM_FLAG_CC3OF + TIM_FLAG_CC4OF);
   // Selected input capture and Update  (overflow) events generate interrupt
   TIM_ITConfig(HALL_TIMER, TIM_IT_CC1,ENABLE);
   TIM_ITConfig(HALL_TIMER, TIM_IT_Update,ENABLE);
   TIM_SetCounter(HALL_TIMER,HALL_COUNTER_RESET);
   TIM_Cmd(HALL_TIMER, ENABLE);
}

이 중 전체 프로그램에서 타이머 2와 타이머 4는 정의되지 않았고, 타이머 3은 호르 센서 피드백 타이머로 사용되며, TIMER3 정의를 통해HANDLES_홀 센서에 연결된 HALLPMSM에 호르 센서가 있는 프로그램에서 로터 속도 측정 방식은 롤링 식별 방식으로 현재 상태와 이전 상태를 비교하여 로터의 회전 방향을 추정한다. 구체적인 코드는 다음과 같다.
void TIM3_IRQHandler(void)
{
  static u8  bHallState; 
  u8 bPrevHallState;
  // Check for the source of TIMx int - Capture or Update Event - 
  if (TIM_GetFlagStatus(HALL_TIMER, TIM_FLAG_Update) == RESET )
  {
    bPrevHallState = bHallState;
    bHallState = ReadHallState();
    #if (HALL_SENSORS_PLACEMENT == DEGREES_120)    
    switch(bHallState)
    {
      case STATE_5:
      if(bPrevHallState == STATE_5)
      {        
        if(bSpeed<0)
        {
          bSpeed = POSITIVE_SWAP;
        }
        else
        {
          bSpeed = NEGATIVE_SWAP;
        }
    }
    else  if (bPrevHallState == STATE_6)
    {
      bSpeed = POSITIVE;
    }
    else  if (bPrevHallState == STATE_3)           
   {
     bSpeed = NEGATIVE;
   }
   //Update angle
   if(bSpeed<0)
   {         
     hElectrical_Angle = (s16)(S16_PHASE_SHIFT+S16_60_PHASE_SHIFT);
   }
   else if(bSpeed!= ERROR)
   {         
     hElectrical_Angle = S16_PHASE_SHIFT; 
   }
   break; 
   case  STATE_3:
   if(bPrevHallState == STATE_3)
   {
     //a speed reversal occured
     if(bSpeed<0)
     {
       bSpeed = POSITIVE_SWAP;
     }        
     else
     {
       bSpeed = NEGATIVE_SWAP;
     }
   }
   else  if (bPrevHallState == STATE_5)
   {          
     bSpeed = POSITIVE;
   }
   else  if (bPrevHallState == STATE_6)           
   {
     bSpeed = NEGATIVE;           
   }
   //Update of the electrical angle
   if(bSpeed<0)
   {
     hElectrical_Angle =(s16)(S16_PHASE_SHIFT+S16_120_PHASE_SHIFT+S16_60_PHASE_SHIFT);
   }
   else if(bSpeed!= ERROR)
   {
     hElectrical_Angle =(s16)(S16_PHASE_SHIFT + S16_120_PHASE_SHIFT);
   }       
   break; 
   case STATE_6: 
   if(bPrevHallState == STATE_6)
   {        
     if(bSpeed<0)
     {
       bSpeed = POSITIVE_SWAP;
     }
     else
     {
       bSpeed = NEGATIVE_SWAP;
     }
   }
   if(bPrevHallState == STATE_3)
   {        
     bSpeed = POSITIVE; 
   }       
   else  if(bPrevHallState == STATE_5)
   {
     bSpeed = NEGATIVE;         
   }  
   if(bSpeed<0)
   {
     hElectrical_Angle =(s16)(S16_PHASE_SHIFT - S16_60_PHASE_SHIFT);  
   }       
   else if(bSpeed!= ERROR)
   {         
     hElectrical_Angle =(s16)(S16_PHASE_SHIFT - S16_120_PHASE_SHIFT); 
   }       
   break;
   default: bSpeed = ERROR;
   break;
}

이 단락 프로그램에서 호르 센서의 상태는 함수ReadHallState()를 통해 얻어지는 동시에 호르 센서의 절대성 때문에 호르 센서의 출력 상태를 알면 회전자의 위치를 재구성할 수 있다.프로그램에서도 홀 센서가 변해 끊길 때마다 로터의 전기 각도를 업데이트하고 모터의 회전과 홀 센서의 상태에 따라 소프트웨어 변수를 초기화하면 현재의 전기 각도를 계산해 파크 변화에 사용할 수 있다.따라서 회전자의 기계 주파수, 즉 회전자의 회전 속도를 알 수 있다. 구체적인 코드는 다음과 같다.
s16 HALL_GetSpeed ( void )
{ 
  s32 wAux; 
  if( hRotorFreq_dpp == HALL_MAX_PSEUDO_SPEED)
  { 
    return (HALL_MAX_SPEED);
  }
  else
  { 
    wAux = ((hRotorFreq_dpp* SAMPLING_FREQ * 10)/(65536*POLE_PAIR_NUM));
    return (s16)wAux;
  }
}

여기서 로터 주파수 hRotorFreqdpp 통과 함수 HALLGetRotorFreq()가 제공됩니다.
2. 호르 센서 프로그램에서 속도/위치 감지 없음
PMSM에 호르 센서가 없는 프로그램에서는 주 함수에 NO 이 정의되어 있습니다.SPEED_SENSORS를 실행하면 STOStateObserverInterface_Init() 함수, 코드는 다음과 같습니다.
#elif defined NO_SPEED_SENSORS
  STO_StateObserverInterface_Init();
#endif

여기서 STOStateObserverInterface_Init()의 역할은 함수 STOStart_Up()이 시작되면 관련 매개변수가 초기화되고 STOCalc_Rotor_Angle() 함수는 이산 상태 감지 방정식을 적용하여 모터의 반전동식 계산을 실현한다.또한 디지털 자물쇠 링의 방법을 통해 반전동세에 따라 회전자의 속도와 각도를 계산하는데 구체적인 코드는 다음과 같다.
void STO_Calc_Rotor_Angle(Volt_Components Stat_Volt_alfa_beta,Curr_ComponentsStat_Curr_alfa_beta, s16 hBusVoltage) 
{ 
  s32 wIalfa_est_Next,wIbeta_est_Next;
  s32 wBemf_alfa_est_Next,wBemf_beta_est_Next; 
  s16 hValfa,hVbeta; 
  s16 hIalfa_err, hIbeta_err;  
  s16 hRotor_Speed; 
  s32 bDirection; 
  if (wBemf_alfa_est > (s32)(S16_MAX*hF2)) 
  { 
    wBemf_alfa_est = S16_MAX*hF2; 
  } 
  else if (wBemf_alfa_est <= (s32)(S16_MIN*hF2)) 
  { 
    wBemf_alfa_est = -S16_MAX*hF2; 
  } 
  if (wBemf_beta_est > (s32)(S16_MAX*hF2)) 
  {  
    wBemf_beta_est = S16_MAX*hF2; 
  } 
  else if (wBemf_beta_est <= (s32)(S16_MIN*hF2)) 
  {  
    wBemf_beta_est = -S16_MAX*hF2; 
  } 
  if (wIalfa_est > (s32)(S16_MAX*hF1)) 
  { 
    wIalfa_est = S16_MAX*hF1; 
  } 
  else if (wIalfa_est <= (s32)(S16_MIN*hF1)) 
  { 
    wIalfa_est = -S16_MAX*hF1; 
  } 
  if (wIbeta_est > S16_MAX*hF1) 
  { 
    wIbeta_est = S16_MAX*hF1; 
  }   
  else if (wIbeta_est <= S16_MIN*hF1) 
  { 
    wIbeta_est = -S16_MAX*hF1; 
  } 
  hIalfa_err = (s16)((wIalfa_est/hF1)-Stat_Curr_alfa_beta.qI_Component1); 
  hIbeta_err = (s16)((wIbeta_est/hF1)-Stat_Curr_alfa_beta.qI_Component2); 
  hValfa = (s16)((Stat_Volt_alfa_beta.qV_Component1*hBusVoltage)/32768);
  hVbeta = (s16)((Stat_Volt_alfa_beta.qV_Component2*hBusVoltage)/32768); 
  /*alfa axes observer*/ 
  wIalfa_est_Next = (s32)(wIalfa_est-(s32)(hC1*(s16)(wIalfa_est/hF1))+ (s32)(hC2*hIalfa_err)+ (s32)(hC5*hValfa)- (s32)(hC3*(s16)(wBemf_alfa_est/hF2))); 
//I(n+1)=I(n)-rs*T/Ls*I(n)+K1*(I(n)-i(n))+T/Ls*V-T/Ls*emf
  wBemf_alfa_est_Next = (s32)(wBemf_alfa_est+(s32)(hC4*hIalfa_err)+ 
  (s32)(hC6*hRotor_Speed_dpp*(wBemf_beta_est/(hF2*hF3))));
  //emf(n+1)=emf(n)+K2*(I(n)-i(n))+p*w*emfb*T
  /*beta axes observer*/ 
  wIbeta_est_Next = (s32)(wIbeta_est-(s32)(hC1*(s16)(wIbeta_est/hF1))+ (s32)(hC2*hIbeta_err)+ (s32)(hC5*hVbeta)- (s32)(hC3*(s16)(wBemf_beta_est/hF2))); 
  wBemf_beta_est_Next = (s32)(wBemf_beta_est+(s32)(hC4*hIbeta_err)- (s32)(hC6*hRotor_Speed_dpp*(wBemf_alfa_est/(hF2*hF3))));
  /* Extrapolation of present rotation direction, necessary for PLL */ 
  if (hRotor_Speed_dpp >=0) 
  { 
    bDirection = 1; 
  } 
  else 
  { 
    bDirection = -1; 
  } 
  /*Calls the PLL blockset*/ 
  hBemf_alfa_est = wBemf_alfa_est/hF2;  
  hBemf_beta_est = wBemf_beta_est/hF2; 
  hRotor_Speed = Calc_Rotor_Speed((s16)(hBemf_alfa_est*bDirection),(s16)(-hBemf_beta_est*bDirection)); 
  Store_Rotor_Speed(hRotor_Speed); 
  hRotor_El_Angle = (s16)(hRotor_El_Angle +hRotor_Speed); 
  /*storing previous values of currents and bemfs*/ 
  wIalfa_est = wIalfa_est_Next; 
  wBemf_alfa_est = wBemf_alfa_est_Next; 
  wIbeta_est = wIbeta_est_Next; 
  wBemf_beta_est = wBemf_beta_est_Next; 
}

여기서 함수의 입력은 스테이트 전류(Stat Curr alfa beta), 전압 명령(Stat Volt alfa beta)과 측정된 DC 모선 전압(hBusVoltage)이다.
또한 함수 STOGet_Electrical_Angle()이 로터 각도를 반환하고 함수 STOGet_Mechanical_Angle()이 로터 기계 각도를 반환합니다. 관계식은 다음과 같습니다.
s16 STO_Get_Mechanical_Angle(void)
{
  return ((s16)(STO_Get_Electrical_Angle()/POLE_PAIR_NUM));
}

함수 STOGet_Speed() 반환 로터 전속, STOGet_Speed_Hz()는 로터 기계 속도를 반환합니다. 그들 사이의 관계는 다음과 같습니다.
s16 STO_Get_Speed_Hz(void)
{
  return (s16)((STO_Get_Speed()* SAMPLING_FREQ * 10)/(65536*POLE_PAIR_NUM));
}

3. 총결산
이번 학습을 통해 PMSM에 센서가 있는/없는 회전자 위치와 회전 속도 검출 알고리즘의 원리를 결합시켜 그에 상응하는 프로그램에 대해 어느 정도 인식을 가지게 되었다. 이는 각 파라미터에 대한 이해, 신호 피드백의 처리 과정 등을 포함한다.다음은 실습에서 실천을 통해 배운 이론 지식을 실제와 초보적인 결합을 하여 자신을 향상시킬 것이다.

좋은 웹페이지 즐겨찾기