[其他ST产品] STM32f103 SMO滑膜观测器的 无感无刷FOC驱动DIY

[复制链接]
3194|20
 楼主| 逢dududu必shu 发表于 2023-1-31 16:43 | 显示全部楼层 |阅读模式

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

ky_motor Foc 测试视频


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


9768463d8d4bc451e6.png
开发板:​​​​​​​开发板链接

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



评论

———————————————— 版权声明:本文为CSDN博主「沉醉不知归路1」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/richardgann/article/details/127926835  发表于 2023-1-31 16:44
 楼主| 逢dududu必shu 发表于 2023-1-31 16:45 | 显示全部楼层
驱动芯片选用的EG2134,没什么可说的,就是图便宜,一颗大约1.5元,比国产的峰绍还要便宜个几毛钱,这难道不是我选它的理由吗?

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

          Mos用的是Irlr7843,性能很好的一颗mos,以前做航模的时候总用这个mos,就是假货比较多,我这个板子也没打算跑太大的电流,因此这个Mos不论从价格还是从性能,都能满足我的需求。
 楼主| 逢dududu必shu 发表于 2023-1-31 16:50 | 显示全部楼层
三个控制按键,复位,开始,停止。实际的程序样式也是按start电机开始转动,按stop电机停止转动,复位键用于debug调试使用。预留一个电位器接口,用来调速。

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

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

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

        使用了SMO 滑膜观测器,SMO代码精简,性能稳定,值得多花一些时间对其进行改进。比如,在反电势滤波方法上。SMO参数调整相对来说比较简单,实际调试电机过程中能很快的调出让电机稳定运行的参数。有没有参数更容易调整的观测器?有的,对传统滑模观测器添加一个自适应律,得到自适应滑模观测器。当然,最重要的还是我比较擅长SMO,其他的都不重要。
 楼主| 逢dududu必shu 发表于 2023-1-31 16:50 | 显示全部楼层
控制模式上写了三个模式,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.    
  8.    
  9.      AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
  10.      AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
  11.   /**************Clark变换****************/
  12.      ClarkI.As = AdcValue.PhaseUCurr;
  13.      ClarkI.Bs = AdcValue.PhaseVCurr;
  14.      CLARK_MARCO(ClarkI);//clark变换
  15.    
  16.   /**************Park变换****************/   
  17.      ParkI.Alpha = ClarkI.Alpha;
  18.      ParkI.Beta  = ClarkI.Beta;
  19.      ParkI.Sine  = AngleSin_Cos.IQSin;
  20.      ParkI.Cosine = AngleSin_Cos.IQCos;
  21.      PARK_MARCO(ParkI);//Park变换
  22.    
  23. /************d轴控制器*******************/   
  24.      pi_id.Ref = 0; //给定id
  25.      pi_id.Fbk = ParkI.Ds;  //反馈id     
  26.      PI_MACRO(pi_id);//  d轴控制器
  27.      
  28. /************q轴控制器*******************/   
  29.      pi_iq.Fbk = ParkI.Qs;  //反馈iq     
  30.      PI_MACRO(pi_iq);//  q轴控制器
  31.      
  32.   /************PARK逆变换*******************/     
  33.      IparkU.Ds = pi_id.Out;
  34.      IparkU.Qs = pi_iq.Out;
  35.    
  36.      IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
  37.      IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值

  38.      PARKinv_MARCO(IparkU)
  39.   
  40.      Svpwm.Ualpha = IparkU.Alpha;
  41.      Svpwm.Ubeta =  IparkU.Beta;
  42.      
  43.      SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度

  44.      SVPWM_Gen(&Svpwm); //得到占空比
  45.      PWM_CMP(); //得到PWM比较值   
  46. }
 楼主| 逢dududu必shu 发表于 2023-1-31 16:53 | 显示全部楼层
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.   
  13.     AngleSin_Cos.IQAngle =  IQAtan_Pare.IQAngle;//估算角度
  14.     pi_iq.Ref = pi_spd.Out; //速度输出
  15.    
  16.     ADC_Sample();//采集电流 得到UV电流
  17.         
  18.      AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
  19.      AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
  20.   /**************Clark变换****************/
  21.      ClarkI.As = AdcValue.PhaseUCurr;
  22.      ClarkI.Bs = AdcValue.PhaseVCurr;
  23.      CLARK_MARCO(ClarkI);//clark变换
  24.    
  25.   /**************Park变换****************/   
  26.      ParkI.Alpha = ClarkI.Alpha;
  27.      ParkI.Beta  = ClarkI.Beta;
  28.      ParkI.Sine  = AngleSin_Cos.IQSin;
  29.      ParkI.Cosine = AngleSin_Cos.IQCos;
  30.      PARK_MARCO(ParkI);//Park变换
  31.    
  32. /************d轴控制器*******************/   
  33.      pi_id.Ref = 0; //给定id
  34.      pi_id.Fbk = ParkI.Ds;  //反馈id     
  35.      PI_MACRO(pi_id);//  d轴控制器
  36.      
  37. /************q轴控制器*******************/   
  38.      pi_iq.Fbk = ParkI.Qs;  //反馈iq     
  39.      PI_MACRO(pi_iq);//  q轴控制器
  40.      
  41.   /************PARK逆变换*******************/     
  42.      IparkU.Ds = pi_id.Out;
  43.      IparkU.Qs = pi_iq.Out;
  44.    
  45.      IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
  46.      IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值

  47.      PARKinv_MARCO(IparkU)
  48.   
  49.      Svpwm.Ualpha = IparkU.Alpha;
  50.      Svpwm.Ubeta =  IparkU.Beta;
  51.      
  52.      SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度

  53.      SVPWM_Gen(&Svpwm); //得到占空比
  54.      PWM_CMP(); //得到PWM比较值   
  55. }
 楼主| 逢dududu必shu 发表于 2023-1-31 16:54 | 显示全部楼层
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.    
  13.      ThreeHallanglecale();//得到角度
  14.    
  15.      AngleSin_Cos.IQAngle = Hall_Three.ele_angleIQ;

  16.      ADC_Sample();//采集电流 得到UV电流
  17.       
  18.      AngleSin_Cos.IQSin = _IQsinPU(AngleSin_Cos.IQAngle);
  19.      AngleSin_Cos.IQCos = _IQcosPU(AngleSin_Cos.IQAngle);
  20.     /*****************************************************************************/
  21.    
  22.    
  23.   /**************Clark变换****************/
  24.      ClarkI.As = AdcValue.PhaseUCurr;
  25.      ClarkI.Bs = AdcValue.PhaseVCurr;
  26.      CLARK_MARCO(ClarkI);//clark变换
  27.    
  28.   /**************Park变换****************/   
  29.      ParkI.Alpha = ClarkI.Alpha;
  30.      ParkI.Beta  = ClarkI.Beta;
  31.      ParkI.Sine  = AngleSin_Cos.IQSin;
  32.      ParkI.Cosine = AngleSin_Cos.IQCos;
  33.      PARK_MARCO(ParkI);//Park变换
  34.    
  35. /************d轴控制器*******************/   
  36.      pi_id.Ref = 0; //给定id
  37.      pi_id.Fbk = ParkI.Ds;  //反馈id     
  38.      PI_MACRO(pi_id);//  d轴控制器
  39.      
  40. /************q轴控制器*******************/   
  41.      pi_iq.Ref = pi_spd.Out; //速度输出
  42.      pi_iq.Fbk = ParkI.Qs;  //反馈iq     
  43.      PI_MACRO(pi_iq);//  q轴控制器
  44.      
  45.   /************PARK逆变换*******************/     
  46.      IparkU.Ds = pi_id.Out;
  47.      IparkU.Qs = pi_iq.Out;
  48.    
  49.      IparkU.Sine = AngleSin_Cos.IQSin;//查表得到正弦值
  50.      IparkU.Cosine=AngleSin_Cos.IQCos;//查表得到余弦值

  51.      PARKinv_MARCO(IparkU)
  52.    
  53.      Svpwm.Ualpha = IparkU.Alpha;
  54.      Svpwm.Ubeta =  IparkU.Beta;
  55.      
  56.      SMO_Angle(ClarkI.Alpha,ClarkI.Beta,IparkU.Alpha,IparkU.Beta); //滑膜估算角度
  57.    
  58.      SVPWM_Gen(&Svpwm); //得到占空比
  59.      PWM_CMP(); //得到PWM比较值
  60.         
  61. }
 楼主| 逢dududu必shu 发表于 2023-1-31 16:55 | 显示全部楼层
  增加了一个上位机接口,用于观测电流波形Iabc,SMO和speed。上位机用的是VOFA,一个开源的上位机。
5684563d8d76438bc6.png
 楼主| 逢dududu必shu 发表于 2023-1-31 16:56 | 显示全部楼层
这是Iabc的波形。
1657563d8d7c55df30.png
 楼主| 逢dududu必shu 发表于 2023-1-31 16:59 | 显示全部楼层
这是SMO波形 7850963d8d7d7ea338.png
 楼主| 逢dududu必shu 发表于 2023-1-31 16:59 | 显示全部楼层
这是 速度speed波形 3691063d8d87603d09.png 整体测试还算好吧,后续还有很多工作需要做。最后是测试视频

评论

SMO的代码可以看下吗?  发表于 2024-11-18 18:37
jiangyimfs 发表于 2023-4-11 20:22 | 显示全部楼层
很不错,学习了,这么好的帖子这么没人回复

评论

是个不错的帖子,提供了很多思路和方法,能像版主一样玩出来的已经很不错了  发表于 2024-12-12 11:02
公羊子丹 发表于 2024-4-22 08:17 | 显示全部楼层

会占用PCB的空间,成本也会更高。
万图 发表于 2024-4-22 09:20 | 显示全部楼层

对于信号回路的峰值电压防护电路不应动作,通常在信号回路中,防护电路的动作电压是信号回路的峰值电压的1.3~1.6倍。
帛灿灿 发表于 2024-4-22 12:19 | 显示全部楼层

开关管T交替工作于通/断两种状态,当开关管关断时,脉冲变压器处于“空载”状态,其中储存的磁能将被积累到下一个周期
周半梅 发表于 2024-4-22 15:18 | 显示全部楼层

选择测试方法和测试参数是检测过程中的重要步骤
童雨竹 发表于 2024-4-22 18:17 | 显示全部楼层

对于环氧树脂而言,一般把导热系数为0.5W/M·K的导热性能已经被定义为高导热
heimawenxuan 发表于 2025-5-6 16:56 | 显示全部楼层
EG2134  最近有个产品需要找人写驱动,如何才能联系到楼主?   
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

494

帖子

2

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