[综合信息] foc算法

[复制链接]
 楼主| 1988020566 发表于 2025-5-25 16:51 | 显示全部楼层 |阅读模式
  1. void PI_Process(void)                   //一阶滤波函数
  2. {
  3.     ialfa=ia;
  4.     ibeta=_IQmpy(ia,_IQ(0.57735026918963))+_IQmpy(ib,_IQ(1.15470053837926));   //3/2变换

  5.     id = _IQmpy(ialfa,Cosine) +_IQmpy(ibeta,Sine);
  6.     iq = _IQmpy(ibeta,Cosine)- _IQmpy(ialfa,Sine) ;            //2/2变换
  7. //======================================================================================================
  8. //IQ电流PID调节控制
  9. //======================================================================================================
  10.     IQ_Ref=_IQdiv(_IQ(IQref),_IQ(E_Ding_DianLiu));//IQref为摇杆反馈的值,比上额定电流值变成标幺值,IQ_Ref为标幺值

  11.     IQ_Ref_fil=_IQmpy(_IQ(0.2),IQ_Ref_fil)+_IQmpy(_IQ(0.8),IQ_Ref);         //目标值
  12.     IQ_Fdb_fil=_IQmpy(_IQ(0.2),IQ_Fdb_fil)+_IQmpy(_IQ(0.8),iq);             //实际反馈值
  13.     IQ_read=_IQmpy(IQ_Fdb_fil,_IQ(E_Ding_DianLiu));
  14.     IQ_read=_IQmpy(IQ_read,_IQ(0.70721356));


  15.     IQ_Error=IQ_Ref_fil - IQ_Fdb_fil;                                       //本次误差
  16.     IQ_Error_read=_IQmpy(IQ_Error,_IQ(E_Ding_DianLiu));
  17.     IQ_Error_error=IQ_Error - IQ_Error_before;                              //误差积分

  18.     IQ_Up=_IQmpy(IQ_Kp,IQ_Error_error);
  19.     IQ_Ui=_IQmpy(IQ_Ki,IQ_Error);
  20.     IQ_Out_deta=IQ_Up  + IQ_Ui;

  21.     IQ_Out=IQ_Out_before + IQ_Out_deta;

  22.     IQ_OutMax=_IQ(2.8);        //电流限幅  原值3.0 限幅值0.3
  23.     IQ_OutMin=_IQ(-2.8);

  24.     if(IQ_Out>IQ_OutMax)     //正相限幅
  25.     {
  26.         IQ_Out=IQ_OutMax;
  27.     }

  28.     else if(IQ_Out<IQ_OutMin)      //反相限幅
  29.     {
  30.         IQ_Out=IQ_OutMin;
  31.     }

  32.     else
  33.     {
  34.         IQ_Out=IQ_Out;
  35.     }


  36.     IQ_Out_before=IQ_Out;
  37.     IQ_Error_before=IQ_Error;
  38.     IQ_Fdb_fil_before=IQ_Fdb_fil;
  39.     Uq=IQ_Out;

  40. //======================================================================================================
  41. //ID电流PID调节控制
  42. //======================================================================================================
  43.     ID_Ref=_IQ(0.00);

  44.     ID_Ref_fil=_IQmpy(_IQ(0.2),ID_Ref_fil)+_IQmpy(_IQ(0.8),ID_Ref);
  45.     ID_Fdb_fil=_IQmpy(_IQ(0.2),ID_Fdb_fil)+_IQmpy(_IQ(0.8),id);
  46.     ID_Fdb=id;
  47.     ID_read=_IQmpy(ID_Fdb_fil,_IQ(E_Ding_DianLiu));
  48.     ID_read=_IQmpy(ID_read,_IQ(0.70721356));
  49.     ID_Error=ID_Ref_fil - ID_Fdb_fil ;
  50.     ID_Error_read=_IQmpy(ID_Error,_IQ(4.2));
  51.     ID_Error_error=ID_Error - ID_Error_before;    //误差积分

  52.     ID_Up=_IQmpy(ID_Kp,ID_Error_error);
  53.     ID_Ui=_IQmpy(ID_Ki,ID_Error);
  54.     ID_Out_deta=ID_Up  + ID_Ui;
  55.     ID_Out=ID_Out_before + ID_Out_deta;

  56.     ID_OutMax=_IQ(2.5);
  57.     ID_OutMin=_IQ(-2.5);

  58.     if(ID_Out>ID_OutMax)        //正相限幅
  59.     {
  60.         ID_Out=ID_OutMax;
  61.     }

  62.     else if(ID_Out<ID_OutMin)    //反相限幅
  63.     {
  64.         ID_Out=ID_OutMin;
  65.     }

  66.     else
  67.     {
  68.         ID_Out=ID_Out;
  69.     }


  70.     ID_Out_before=ID_Out;
  71.     ID_Error_before=ID_Error;
  72.     ID_Fdb_old=ID_Fdb_fil;

  73.     Ud=ID_Out;
  74. /***PI滤波数据观测****/
  75.     if(PI_Times<=200)
  76.     {
  77.         IQ_REF_WATCH[PI_Times]=IQ_Ref_fil;           //观测反馈的实际电流值数组
  78.         IQ_OUT_WATCH[PI_Times]=IQ_Fdb_fil;             //观测目标电流值数组
  79.         PI_Times++;
  80.     }
  81.     else PI_Times=0;
  82. /***************************/
  83. }

  84. void SVPWM(void)      //SVPWM函数
  85. {
  86.     _iq t_01,t_02;
  87.     //======================================================================================================
  88.     //IPark变换aa
  89.     //======================================================================================================
  90.             Ualfa = _IQmpy(Ud,Cosine) - _IQmpy(Uq,Sine);
  91.             Ubeta = _IQmpy(Uq,Cosine) + _IQmpy(Ud,Sine);

  92.     //======================================================================================================
  93.     //SVPWM实现
  94.     //======================================================================================================
  95.             B0=Ubeta;
  96.             B1=_IQmpy(_IQ(0.8660254),Ualfa)- _IQmpy(_IQ(0.5),Ubeta);  // 0.8660254 = sqrt(3)/2
  97.             B2=_IQmpy(_IQ(-0.8660254),Ualfa)- _IQmpy(_IQ(0.5),Ubeta); // 0.8660254 = sqrt(3)/2

  98.             Sector=0;                //扇区判断
  99.             if(B0>_IQ(0))
  100.             {
  101.                 Sector =1;
  102.             }

  103.             if(B1>_IQ(0))
  104.             {
  105.                 Sector =Sector +2;
  106.             }

  107.             if(B2>_IQ(0))
  108.             {
  109.                 Sector =Sector +4;
  110.             }


  111.             X=Ubeta;//va
  112.             Y=_IQmpy(_IQ(0.8660254),Ualfa)+ _IQmpy(_IQ(0.5),Ubeta);  // 0.8660254 = sqrt(3)/2 vb
  113.             Z=_IQmpy(_IQ(-0.8660254),Ualfa)+ _IQmpy(_IQ(0.5),Ubeta); // 0.8660254 = sqrt(3)/2 vc


  114.             if(Sector==1)
  115.             {
  116.                 t_01=Z;
  117.                 t_02=Y;

  118.                 if((t_01+t_02)>_IQ(1))
  119.                 {
  120.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  121.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  122.                 }
  123.                 else
  124.                 {
  125.                     t1=t_01;
  126.                     t2=t_02;
  127.                 }
  128.                 Tb=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  129.                 Ta=Tb+t1;
  130.                 Tc=Ta+t2;
  131.             }
  132.             else if(Sector==2)
  133.             {
  134.                 t_01=Y;
  135.                 t_02=-X;

  136.                  if((t_01+t_02)>_IQ(1))
  137.                 {
  138.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  139.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  140.                 }
  141.                 else
  142.                 {
  143.                     t1=t_01;
  144.                     t2=t_02;
  145.                 }
  146.                 Ta=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  147.                 Tc=Ta+t1;
  148.                 Tb=Tc+t2;
  149.             }
  150.             else if(Sector==3)
  151.             {
  152.                 t_01=-Z;
  153.                 t_02=X;

  154.                  if((t_01+t_02)>_IQ(1))
  155.                 {
  156.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  157.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  158.                 }
  159.                 else
  160.                 {
  161.                     t1=t_01;
  162.                     t2=t_02;
  163.                 }
  164.                 Ta=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  165.                 Tb=Ta+t1;
  166.                 Tc=Tb+t2;
  167.             }
  168.             else if(Sector==4)
  169.             {
  170.                 t_01=-X;
  171.                 t_02=Z;
  172.                  if((t_01+t_02)>_IQ(1))
  173.                 {
  174.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  175.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  176.                 }
  177.                 else
  178.                 {
  179.                     t1=t_01;
  180.                     t2=t_02;
  181.                 }
  182.                 Tc=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  183.                 Tb=Tc+t1;
  184.                 Ta=Tb+t2;
  185.             }
  186.             else if(Sector==5)
  187.             {
  188.                 t_01=X;
  189.                 t_02=-Y;
  190.                  if((t_01+t_02)>_IQ(1))
  191.                 {
  192.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  193.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  194.                 }
  195.                 else
  196.                 {
  197.                     t1=t_01;
  198.                     t2=t_02;
  199.                 }
  200.                 Tb=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  201.                 Tc=Tb+t1;
  202.                 Ta=Tc+t2;
  203.             }
  204.             else if(Sector==6)
  205.             {
  206.                 t_01=-Y;
  207.                 t_02=-Z;
  208.                  if((t_01+t_02)>_IQ(1))
  209.                 {
  210.                     t1=_IQmpy(_IQdiv(t_01, (t_01+t_02)),_IQ(1));
  211.                     t2=_IQmpy(_IQdiv(t_02, (t_01+t_02)),_IQ(1));
  212.                 }
  213.                 else
  214.                 {
  215.                     t1=t_01;
  216.                     t2=t_02;
  217.                 }
  218.                 Tc=_IQmpy(_IQ(0.5),(_IQ(1)-t1-t2));
  219.                 Ta=Tc+t1;
  220.                 Tb=Ta+t2;
  221.             }

  222.             MfuncD1=_IQmpy(_IQ(2),(_IQ(0.5)-Ta));//倒三角计算
  223.             MfuncD2=_IQmpy(_IQ(2),(_IQ(0.5)-Tb));
  224.             MfuncD3=_IQmpy(_IQ(2),(_IQ(0.5)-Tc));
  225.     //======================================================================================================
  226.     //EVA全比较器参数赋值,用于驱动电机
  227.     //======================================================================================================
  228.             MPeriod = (int16)(T1Period * Modulation);/*MPeriod = 3750 * 1 =3750 */
  229. /*PWM1 占空比的赋值*/
  230.             Tmp = (int32)MPeriod * MfuncD1;/*Tmp -3750~3750 */
  231.             Tmp = (Tmp>>16) + (T1Period>>1);/*Tmp  -1875~1875 + 3750/2 = 0~3750*/
  232.             /* PWM周期MPeriod 乘以 其占空比MfuncD1,得到比较寄存器的值,
  233.              * 但因为此时的占空比经过范围变换处理,所以还不是真正的比较寄存器的值
  234.              * Tmp 除以2,实现占空比由(-1,1)到(-0.5,0,5)的还原,
  235.              * 然后右移15位,也就是取整,将该数从Q15格式转换成Q0格式,综合起来就是(Tmp>>16)
  236.              * 然后加上0.5(对应MPeriod>>1)的偏移,把占空比还原到(0,1),此时的结果就是比较寄存器的值*/

  237.             /*
  238.             if(Tmp >MPeriod - 500)
  239.                 Tmp = MPeriod - 500;
  240.             if(Tmp < 100) Tmp = 100;
  241.             */

  242.             EPwm1Regs.CMPA.half.CMPA = (int16)(Tmp) ;//>>16) + (int16)(T1Period>>1); // Q0 = (Q15->Q0)/2 + (Q0/2)
  243. /*PWM2 占空比的赋值*/
  244.             Tmp = (int32)MPeriod * MfuncD2;                    // Q15 = Q0*Q15,计算全比较器CMPR2赋值      MduncD2去掉(int32)
  245.             Tmp = (Tmp>>16) + (T1Period>>1);
  246.             /*
  247.             if(Tmp >MPeriod - 500)
  248.                 Tmp = MPeriod - 500;
  249.             if(Tmp < 100) Tmp = 100;
  250.             */
  251.             EPwm2Regs.CMPA.half.CMPA = (int16)(Tmp);//>>16) + (int16)(T1Period>>1); // Q0 = (Q15->Q0)/2 + (Q0/2)
  252. /*PWM3 占空比的赋值*/
  253.             Tmp = (int32)MPeriod * MfuncD3;                    // Q15 = Q0*Q15,计算全比较器CMPR3赋值     MduncD3去掉(int32)
  254.             Tmp = (Tmp>>16) + (T1Period>>1);
  255.             /*
  256.             if(Tmp >MPeriod - 500)
  257.                 Tmp = MPeriod - 500;
  258.             if(Tmp < 100) Tmp = 100;
  259.             */
  260.             EPwm3Regs.CMPA.half.CMPA = (int16)(Tmp);//>>16) + (int16)(T1Period>>1); // Q0 = (Q15->Q0)/2 + (Q0/2)

  261. }


szt1993 发表于 2025-7-31 23:01 | 显示全部楼层
foc算法
fengm 发表于 2025-8-4 10:50 | 显示全部楼层
在某些应用中,电机的负载和运行条件可能变化,需要实现参数自适应算法,以动态调整PI控制器的参数。
hilahope 发表于 2025-8-4 15:33 | 显示全部楼层
需要实现死区补偿算法,以减少这种偏差对电机性能的影响。
beacherblack 发表于 2025-8-4 17:25 | 显示全部楼层
在控制回路中,需要将控制信号从旋转坐标系变回静止坐标系,再变回三相坐标系。
51xlf 发表于 2025-8-4 18:58 | 显示全部楼层
FOC算法需要较高的计算资源和实时性,选择合适的微控制器或数字信号处理器(DSP)以满足算法的计算需求。
hearstnorman323 发表于 2025-8-4 21:46 | 显示全部楼层
未加滤波器时,电机相电流噪声可能达±50mA,导致转矩波动±2%;加滤波器后可降至±5mA。
everyrobin 发表于 2025-8-5 14:38 | 显示全部楼层
FOC 的核心是通过Clark 变换(三相静止→两相静止 αβ 坐标系)和Park 变换(两相静止→两相旋转 dq 坐标系)实现转矩与磁通的解耦,其精度直接依赖于电流采样精度和转子位置角度(θ)的准确性。
loutin 发表于 2025-8-7 10:46 | 显示全部楼层
使用高精度的电流传感器来测量电机的相电流
tifmill 发表于 2025-8-7 15:26 | 显示全部楼层
FOC 算法实现涉及坐标变换、电流采样、位置检测、PID 调节、PWM 生成等多个环节,任何一个环节的误差或设计缺陷都会导致控制性能下降
louliana 发表于 2025-8-8 10:19 | 显示全部楼层
FOC的核心是​​Clarke变换(3相→2相静止坐标系)​​和​​Park变换(2相静止→2相旋转坐标系)​​,其准确性直接影响后续电流控制的效果。
biechedan 发表于 2025-8-8 14:49 | 显示全部楼层
如果使用无传感器控制,需要实现准确的速度估算算法,如基于反电动势的估算方法。
fengm 发表于 2025-8-8 16:48 | 显示全部楼层
优化算法的实现,减少计算量,确保控制回路能够在实时系统中稳定运行。
51xlf 发表于 2025-8-8 20:35 | 显示全部楼层
建立准确的电机和逆变器模型,进行仿真和分析,确保控制系统的稳定性和鲁棒性。
kkzz 发表于 2025-8-10 20:55 | 显示全部楼层
OC算法涉及大量的实时计算,需要高性能的微控制器或DSP来实现。计算资源不足会导致控制延迟和精度下降。
tifmill 发表于 2025-8-11 20:36 | 显示全部楼层
在某些运行条件下,电压矢量可能超过逆变器的最大输出能力。需要实现过调制算法,以在不牺牲电机性能的情况下最大化利用逆变器的输出能力。
timfordlare 发表于 2025-8-11 23:49 | 显示全部楼层
逻辑运算的短路特性和移位运算的溢出可能导致隐藏错误。
mikewalpole 发表于 2025-8-12 02:55 | 显示全部楼层
通过两次采样值结合基尔霍夫定律还原三相电流,解决单电阻采样的信息缺失问题
cashrwood 发表于 2025-8-12 12:47 | 显示全部楼层
设置积分上限防止超调,引入抗饱和机制提升稳定性
mollylawrence 发表于 2025-8-12 14:31 | 显示全部楼层
FOC算法的调试过程复杂,需要进行大量的实验验证。调试过程中应逐步调整参数,观察系统的响应
您需要登录后才可以回帖 登录 | 注册

本版积分规则

418

主题

10979

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部