PMSM磁场定向控制程序笔记(二)——Clark,Park及反变换

程序来源:FOC SDK2.0

说明:在FOC SDK2.0的基础上稍稍修改,并做了一些注释,主要是为了记录总结收获。删掉或者注释了一些暂时用不到的功能。

下面是MC_Clarke_Park.c文件部分程序:

#ifdef MAX_MODULATION_100_PER_CENT    //100%占空比
#define START_INDEX     63

const u16 circle_limit_table[65]=     
{
32767,32390,32146,31907,31673,31444,31220,31001,30787,30577,30371,
30169,29971,29777,29587,29400,29217,29037,28861,28687,28517,
28350,28185,28024,27865,27709,27555,27404,27256,27110,26966,
26824,26685,26548,26413,26280,26149,26019,25892,25767,25643,
25521,25401,25283,25166,25051,24937,24825,24715,24606,24498,
24392,24287,24183,24081,23980,23880,23782,23684,23588,23493,
23400,23307,23215,23125
};
#endif

#define SIN_MASK 0x0300
#define U0_90     0x0200
#define U90_180   0x0300
#define U180_270  0x0000
#define U270_360  0x0100

static Trig_Components Vector_Components;
const s16 hSin_Cos_Table[256] = SIN_COS_TABLE; //正弦、余弦查表法

/*******************************************************************************
* Function Name  : Clarke Transformation
* Description    : This function transforms stator currents qIas and  
*                  qIbs (which are directed along axes each displaced by  
*                  120 degrees) into currents qIalpha and qIbeta in a 
*                  stationary qd reference frame.
*                  qIalpha = qIas
*                  qIbeta = -(2*qIbs+qIas)/sqrt(3)
* Input          : Stat_Curr_a_b
* Output         : Stat_Curr_alfa_beta
* Return         : none.
*******************************************************************************/

Curr_Components Clarke(Curr_Components Curr_Input)
{
  Curr_Components Curr_Output;
  
  s32 qIa_divSQRT3_tmp;
  s32 qIb_divSQRT3_tmp ;
  
  s16 qIa_divSQRT3;
  s16 qIb_divSQRT3 ;

  // qIalpha = qIas
  Curr_Output.qI_Component1= Curr_Input.qI_Component1;

  qIa_divSQRT3_tmp = divSQRT_3 * Curr_Input.qI_Component1; 
  qIa_divSQRT3_tmp /=32768;   //相当于10*divsqrt(3)*Curr_Input.qI_Component1
    
  qIb_divSQRT3_tmp = divSQRT_3 * Curr_Input.qI_Component2;
  qIb_divSQRT3_tmp /=32768;   //相当于10*divsqrt(3)*Curr_Input.qI_Component2
  
  qIa_divSQRT3=((s16)(qIa_divSQRT3_tmp));		
  qIb_divSQRT3=((s16)(qIb_divSQRT3_tmp));				
    
  //qIbeta = -(2*qIbs+qIas)/sqrt(3) beta轴滞后alpha轴,与常规不一样
  Curr_Output.qI_Component2=(-(qIa_divSQRT3)-(qIb_divSQRT3)-(qIb_divSQRT3));
  
  return(Curr_Output); 
}

/*******************************************************************************
* Function Name  : Park Transformation
* Description    : This function transforms stator currents qIalpha and qIbeta,
*                  which belong to a stationary qd reference frame, to a rotor 
*                  flux synchronous reference frame (properly oriented), so as 
*                  to obtain qIq and qIds.每转65535个脉冲
*                  qId=qIalpha_tmp*sin(theta)+qIbeta_tmp*cos(Theta)
*                  qIq=qIalpha_tmp*cos(Theta)-qIbeta_tmp*sin(Theta) 与常规不一样           
* Input          : Stat_Curr_alfa_beta                Theta是d与Beta之间的夹角                
* Output         : Stat_Curr_q_d.
* Return         : Curr_Output.
*******************************************************************************/

Curr_Components Park(Curr_Components Curr_Input, s16 Theta)
{
  Curr_Components Curr_Output;
  s32 qId_tmp_1, qId_tmp_2;
  s32 qIq_tmp_1, qIq_tmp_2;     
  s16 qId_1, qId_2;  
  s16 qIq_1, qIq_2;  
  
  Vector_Components = Trig_Functions(Theta);
  
  //No overflow guaranteed
  qIq_tmp_1 = Curr_Input.qI_Component1 * Vector_Components.hCos;  	
  qIq_tmp_1 /= 32768;
  
  //No overflow guaranteed
  qIq_tmp_2 = Curr_Input.qI_Component2 *Vector_Components.hSin;
  qIq_tmp_2 /= 32768;
 
  qIq_1 = ((s16)(qIq_tmp_1));
  qIq_2 = ((s16)(qIq_tmp_2));

  //Iq component in Q1.15 Format 
  Curr_Output.qI_Component1 = ((qIq_1)-(qIq_2));	
  
  //No overflow guaranteed
  qId_tmp_1 = Curr_Input.qI_Component1 * Vector_Components.hSin;
  qId_tmp_1 /= 32768;
  
  //No overflow guaranteed
  qId_tmp_2 = Curr_Input.qI_Component2 * Vector_Components.hCos;
  qId_tmp_2 /= 32768;
  
  qId_1 = (s16)(qId_tmp_1);		 
  qId_2 = (s16)(qId_tmp_2);					

   //Id component in Q1.15 Format   
  Curr_Output.qI_Component2 = ((qId_1)+(qId_2));  
  
  return (Curr_Output);
  
}


/*******************************************************************************
* Function Name  : RevPark_Circle_Limitation
* Description    : Check if
*       Stat_Volt_q_d.qV_Component1^2 + Stat_Volt_q_d.qV_Component2^2 <= 32767^2
*                  Apply limitation if previous condition is not met,
*                  by keeping a constant ratio 
*                  Stat_Volt_q_d.qV_Component1/Stat_Volt_q_d.qV_Component2
*                 将经过PID调节后的Vd,Vq映射到0-32767,对应的占空比位0-100%
*                 这就设计到合成矢量取模运算,即sqrt(Vd^2+Vq^2);
*                 运算量比较大,查表法
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/

void RevPark_Circle_Limitation(void)
{
s32 temp;
             
temp = Stat_Volt_q_d.qV_Component1 * Stat_Volt_q_d.qV_Component1 
             + Stat_Volt_q_d.qV_Component2 * Stat_Volt_q_d.qV_Component2;  // min value 0, max value 2*32767*32767
              
if ( temp > (u32)(( MAX_MODULE * MAX_MODULE) ) ) // (Vd^2+Vq^2) > MAX_MODULE^2 ´大于最大调制比
   {
   u16 index;
              
   temp /= (u32)(512*32768);  // min value START_INDEX, max value 127
   temp -= START_INDEX ;      // min value 0, max value 127 - START_INDEX
		              //减去一个索引值,是因为前面的值都是32768,没有意义,存了浪费时间
   index = circle_limit_table[(u8)temp];                   //index = MMI*S16_Max^2/V_magnitude_index
              
   temp = (s16)Stat_Volt_q_d.qV_Component1 * (u16)(index); //(Vq1)*MMI*S16_Max/V_mag
   Stat_Volt_q_d.qV_Component1 = (s16)(temp/32768);        //Vq=(Vq1)*MMI*S16_Max/(32768*V_mag) 
              
   temp = (s16)Stat_Volt_q_d.qV_Component2 * (u16)(index); //(Vd1)*MMI*S16_Max^2/V_mag
   Stat_Volt_q_d.qV_Component2 = (s16)(temp/32768);        //Vd=(Vd1)*MMI*S16_Max/(32768*V_mag)
   }

} 

/*******************************************************************************
* Function Name  : Rev_Park Transformation
* Description    : This function transforms stator voltage qVq and qVd, that 
*                  belong to a rotor flux synchronous rotating frame, to a 
*                 stationary reference frame, so as to obtain qValpha and qVbeta
*                  qValfa=qVq*Cos(theta)+qVd*Sin(theta)
*                  qVbeta=-qVq*Sin(theta)+qVd*Cos(theta)                  
* Input          : Stat_Volt_q_d.
* Output         : Stat_Volt_a_b
* Return         : none.
*******************************************************************************/

Volt_Components Rev_Park(Volt_Components Volt_Input)
{ 	
  s32 qValpha_tmp1,qValpha_tmp2,qVbeta_tmp1,qVbeta_tmp2;
  s16 qValpha_1,qValpha_2,qVbeta_1,qVbeta_2;
  Volt_Components Volt_Output;
   
  //No overflow guaranteed
  qValpha_tmp1 = Volt_Input.qV_Component1 * Vector_Components.hCos;
  qValpha_tmp1 /= 32768;
  
  qValpha_tmp2 = Volt_Input.qV_Component2 * Vector_Components.hSin;
  qValpha_tmp2 /= 32768;
		
  qValpha_1 = (s16)(qValpha_tmp1);		
  qValpha_2 = (s16)(qValpha_tmp2);			

  Volt_Output.qV_Component1 = ((qValpha_1)+(qValpha_2));
 
  
  qVbeta_tmp1 = Volt_Input.qV_Component1 * Vector_Components.hSin;
  qVbeta_tmp1 /= 32768;
  
  qVbeta_tmp2 = Volt_Input.qV_Component2 * Vector_Components.hCos;
  qVbeta_tmp2 /= 32768;

  qVbeta_1 = (s16)(qVbeta_tmp1);				
  qVbeta_2 = (s16)(qVbeta_tmp2);
   				
  Volt_Output.qV_Component2 = -(qVbeta_1)+(qVbeta_2);
 
  return(Volt_Output);
}
/*******************************************************************************
* Function Name  : Trig_Functions 
* Description    : This function returns Cosine and Sine functions of the input 
*                  angle
*                 该函数根据输入角返回三角余弦和正弦函数值
* Input          : angle in s16 format
* Output         : Cosine and Sine in s16 format
* Return         : none.
*******************************************************************************/
Trig_Components Trig_Functions(s16 hAngle)
{
  u16 hindex;
  Trig_Components Local_Components;
  
  /* 10 bit index computation  */  
  hindex = (u16)(hAngle + 32768);  
  hindex /= 64;      
  
  switch (hindex & SIN_MASK) 
  {
  case U0_90:
    Local_Components.hSin = hSin_Cos_Table[(u8)(hindex)];
    Local_Components.hCos = hSin_Cos_Table[(u8)(0xFF-(u8)(hindex))];
    break;
  
  case U90_180:  
     Local_Components.hSin = hSin_Cos_Table[(u8)(0xFF-(u8)(hindex))];
     Local_Components.hCos = -hSin_Cos_Table[(u8)(hindex)];
    break;
  
  case U180_270:
     Local_Components.hSin = -hSin_Cos_Table[(u8)(hindex)];
     Local_Components.hCos = -hSin_Cos_Table[(u8)(0xFF-(u8)(hindex))];
    break;
  
  case U270_360:
     Local_Components.hSin =  -hSin_Cos_Table[(u8)(0xFF-(u8)(hindex))];
     Local_Components.hCos =  hSin_Cos_Table[(u8)(hindex)]; 
    break;
  default:
    break;
  }
  return (Local_Components);
}
今天就能理解到这儿了,还有很多不理解的地方,改天继续。加油!


  • 11
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值