• STM32f103 SMO滑膜观测器的FOC驱动DIY


            小时候玩航模了解到无刷电机,又从方波控制了解到FOC控制,在接触了一些开源项目的时候,感叹做的真好,不论是方波的还是Foc的启动都是那么丝滑,软件做的虽然好,但在这几年电机驱动芯片和部分型号的单片机价格都居高不下,做一个低成本的Foc驱动器利用网上开源资料已经不够用了。

    ky_motor Foc 测试视频

            假期趁着有时间做一套Foc驱动器,从硬件到软件,从夏天到冬天,真是不容易,总算差不多了。

    开发板:​​​​​​​开发板链接

            硬件选用了STM32F103单片机,程序内容并不是很多,103c8,103rb都可以满足需求,为了后期可以扩展资源,我选用了rbt6,价格大约16元一颗,不是用的ST电机库,因此程序可以移植到国产芯片上,不过我没有移植过,毕竟我不太相信国产芯片(个人观点)。

            驱动芯片选用的EG2134,没什么可说的,就是图便宜,一颗大约1.5元,比国产的峰绍还要便宜个几毛钱,这难道不是我选它的理由吗?

             运放选用的是LM324,也是几毛钱的物料,追求更好的效果可以选用精度更高的运放,而不是我选用的这个玩具级,运放采样做的是一个差分输入的方式,看电流波形还可以。

              Mos用的是Irlr7843,性能很好的一颗mos,以前做航模的时候总用这个mos,就是假货比较多,我这个板子也没打算跑太大的电流,因此这个Mos不论从价格还是从性能,都能满足我的需求。

           三个控制按键,复位,开始,停止。实际的程序样式也是按start电机开始转动,按stop电机停止转动,复位键用于debug调试使用。预留一个电位器接口,用来调速。

           电阻采样用了三颗0.05R的采样电阻,通过三电阻采样的方式保证了电流采样的精度(当然,运放有些拉跨)。

            剩下的就是辅助电路了,预留了IIC接口,SPI接口,后期方便加传感器或者OLED。

            硬件介绍完了,剩下的就是软件部分了,当然也是最精彩的部分了,篇幅有限,我简单介绍一下功能,后面有时间我会在专栏里给大家详细的讲解一下Foc的控制方法。

            使用了SMO 滑膜观测器,SMO代码精简,性能稳定,值得多花一些时间对其进行改进。比如,在反电势滤波方法上。SMO参数调整相对来说比较简单,实际调试电机过程中能很快的调出让电机稳定运行的参数。有没有参数更容易调整的观测器?有的,对传统滑模观测器添加一个自适应律,得到自适应滑模观测器。当然,最重要的还是我比较擅长SMO,其他的都不重要。

            控制模式上写了三个模式,Hallloop(霍尔闭环),SMOloop(滑膜闭环),Openloop(开环)这三个模式。我先把这部分代码贴上来,后期测试的视频我在传上来。

            Openloop

    1. void Motor_IFStart(void)
    2. {
    3. Angle_Acc(Angle);
    4. AngleSin_Cos.IQAngle = Angle.Set;//角度
    5. pi_iq.Ref = IqStart; //启动电流设置
    6. ADC_Sample();//采集电流 得到UV电流
    7. AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
    8. AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
    9. /**************Clark变换****************/
    10. ClarkI.As = AdcValue.PhaseUCurr;
    11. ClarkI.Bs = AdcValue.PhaseVCurr;
    12. CLARK_MARCO(ClarkI);//clark变换
    13. /**************Park变换****************/
    14. ParkI.Alpha = ClarkI.Alpha;
    15. ParkI.Beta = ClarkI.Beta;
    16. ParkI.Sine = AngleSin_Cos.IQSin;
    17. ParkI.Cosine = AngleSin_Cos.IQCos;
    18. PARK_MARCO(ParkI);//Park变换
    19. /************d轴控制器*******************/
    20. pi_id.Ref = 0; //给定id
    21. pi_id.Fbk = ParkI.Ds; //反馈id
    22. PI_MACRO(pi_id);// d轴控制器
    23. /************q轴控制器*******************/
    24. pi_iq.Fbk = ParkI.Qs; //反馈iq
    25. PI_MACRO(pi_iq);// q轴控制器
    26. /************PARK逆变换*******************/
    27. IparkU.Ds = pi_id.Out;
    28. IparkU.Qs = pi_iq.Out;
    29. IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
    30. IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值
    31. PARKinv_MARCO(IparkU)
    32. Svpwm.Ualpha = IparkU.Alpha;
    33. Svpwm.Ubeta = IparkU.Beta;
    34. SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度
    35. SVPWM_Gen(&Svpwm); //得到占空比
    36. PWM_CMP(); //得到PWM比较值
    37. }

            SMOloop

    1. void SMO_SpeedLoop(void)
    2. {
    3. PWMZD_count++;
    4. if(PWMZD_count==25)
    5. {
    6. PWMZD_count=0;
    7. SMO_Speedcale();
    8. pi_spd.Ref = SpeedRef;
    9. pi_spd.Fbk = Speed_estPare.Speed_RPM;
    10. PI_SPEED_MACRO(pi_spd);//速度环PI
    11. }
    12. AngleSin_Cos.IQAngle = IQAtan_Pare.IQAngle;//估算角度
    13. pi_iq.Ref = pi_spd.Out; //速度输出
    14. ADC_Sample();//采集电流 得到UV电流
    15. AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
    16. AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
    17. /**************Clark变换****************/
    18. ClarkI.As = AdcValue.PhaseUCurr;
    19. ClarkI.Bs = AdcValue.PhaseVCurr;
    20. CLARK_MARCO(ClarkI);//clark变换
    21. /**************Park变换****************/
    22. ParkI.Alpha = ClarkI.Alpha;
    23. ParkI.Beta = ClarkI.Beta;
    24. ParkI.Sine = AngleSin_Cos.IQSin;
    25. ParkI.Cosine = AngleSin_Cos.IQCos;
    26. PARK_MARCO(ParkI);//Park变换
    27. /************d轴控制器*******************/
    28. pi_id.Ref = 0; //给定id
    29. pi_id.Fbk = ParkI.Ds; //反馈id
    30. PI_MACRO(pi_id);// d轴控制器
    31. /************q轴控制器*******************/
    32. pi_iq.Fbk = ParkI.Qs; //反馈iq
    33. PI_MACRO(pi_iq);// q轴控制器
    34. /************PARK逆变换*******************/
    35. IparkU.Ds = pi_id.Out;
    36. IparkU.Qs = pi_iq.Out;
    37. IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
    38. IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值
    39. PARKinv_MARCO(IparkU)
    40. Svpwm.Ualpha = IparkU.Alpha;
    41. Svpwm.Ubeta = IparkU.Beta;
    42. SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度
    43. SVPWM_Gen(&Svpwm); //得到占空比
    44. PWM_CMP(); //得到PWM比较值
    45. }

    Hallloop

    1. void Mode_Hall_loop(void)
    2. {
    3. PWMZD_count++;
    4. if(PWMZD_count==25)
    5. {
    6. PWMZD_count=0;
    7. Hall_Three_Speedcale();
    8. pi_spd.Ref = SpeedRef;
    9. pi_spd.Fbk = Hall_Three.Speed_RPM;
    10. PI_SPEED_MACRO(pi_spd);//速度PI控制器
    11. }
    12. ThreeHallanglecale();//得到角度
    13. AngleSin_Cos.IQAngle = Hall_Three.ele_angleIQ;
    14. ADC_Sample();//采集电流 得到UV电流
    15. AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
    16. AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
    17. /*****************************************************************************/
    18. /**************Clark变换****************/
    19. ClarkI.As = AdcValue.PhaseUCurr;
    20. ClarkI.Bs = AdcValue.PhaseVCurr;
    21. CLARK_MARCO(ClarkI);//clark变换
    22. /**************Park变换****************/
    23. ParkI.Alpha = ClarkI.Alpha;
    24. ParkI.Beta = ClarkI.Beta;
    25. ParkI.Sine = AngleSin_Cos.IQSin;
    26. ParkI.Cosine = AngleSin_Cos.IQCos;
    27. PARK_MARCO(ParkI);//Park变换
    28. /************d轴控制器*******************/
    29. pi_id.Ref = 0; //给定id
    30. pi_id.Fbk = ParkI.Ds; //反馈id
    31. PI_MACRO(pi_id);// d轴控制器
    32. /************q轴控制器*******************/
    33. pi_iq.Ref = pi_spd.Out; //速度输出
    34. pi_iq.Fbk = ParkI.Qs; //反馈iq
    35. PI_MACRO(pi_iq);// q轴控制器
    36. /************PARK逆变换*******************/
    37. IparkU.Ds = pi_id.Out;
    38. IparkU.Qs = pi_iq.Out;
    39. IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
    40. IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值
    41. PARKinv_MARCO(IparkU)
    42. Svpwm.Ualpha = IparkU.Alpha;
    43. Svpwm.Ubeta = IparkU.Beta;
    44. SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度
    45. SVPWM_Gen(&Svpwm); //得到占空比
    46. PWM_CMP(); //得到PWM比较值
    47. }

            增加了一个上位机接口,用于观测电流波形Iabc,SMO和speed。上位机用的是VOFA,一个开源的上位机。

     这是Iabc的波形。

    这是SMO波形 

    这是 速度speed波形

    整体测试还算好吧,后续还有很多工作需要做。最后是测试视频 

  • 相关阅读:
    2023App测试必掌握的核心测试:UI、功能测试
    #机器学习--高等数学基础--第四章:不定积分
    通过DSSM算法进行商品推荐 代码+数据
    Java8 中新增的 Stream 流操作
    项目之利用 V4L2应用程序框架 进行视频录制
    9D电影是怎样的?(+维度空间常识)
    【C++】多态
    过去将来时习题
    全国工企专利匹配数据(1998-2014)
    AOP中5种通知的注解
  • 原文地址:https://blog.csdn.net/richardgann/article/details/127926835