你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

ST2.0电机库SVPWM计算求指导(后加了扇区计算对比程序分析)  

[复制链接]
单片机_电子爱好者 提问时间:2016-9-11 20:45 /
阅读主题, 点击返回1楼
2 收藏 6 评论53 发布时间:2016-9-11 20:45
53个回答
单片机_电子爱好者 回答时间:2018-9-14 11:47:22
fufudezheng 发表于 2018-9-12 21:57
楼主这个官方教程能发一下吗?

st电机库手册已上传
fufudezheng 回答时间:2018-9-19 18:01:15
单片机_电子爱好者 发表于 2018-9-4 11:21
好久没有搞FOC了,需要解释st svpwm计算的人多的话,有时间再把ST扇区计算svpwm回顾一下,把原理讲一下 ...

这个TA=(T+X-Z)/2,感觉少了个   根号3/Udc.
楼主能讲下这个TA和下边的对称pwm是怎么回事吗?
单片机_电子爱好者 回答时间:2018-9-25 09:19:14
fufudezheng 发表于 2018-9-19 18:01
这个TA=(T+X-Z)/2,感觉少了个   根号3/Udc.
楼主能讲下这个TA和下边的对称pwm是怎么回事吗? ...

这个地方我记得是由于时间和电压都进行标幺化了,即T就对应Udc,你可以看一下svpwm原理,可以看下ti的,对比一下st和ti的你基本上就懂了,现在没有什么时间看,具体的没法给你讲
龙吞潭水 回答时间:2018-9-28 08:32:15
同问,TA=(T+X-Z)/2,感觉少了个   根号3/Udc.
粗通文墨 回答时间:2018-11-6 15:34:33
谢谢,详细看看。
单片机_电子爱好者 回答时间:2018-11-13 18:04:42
龙吞潭水 发表于 2018-9-28 08:32
同问,TA=(T+X-Z)/2,感觉少了个   根号3/Udc.


我这几天推了一下,知道为什么少了根号3/Udc,主要是因为标幺话的缘故,st程序中对V alfe和Vbeta标幺成Q15格式,这个没有疑问吧,而V alfe和Vbeta的值最大等于2/3*Udc,但是我们一般不会过调制,因此V alfe和Vbeta的值最大等于2/3*Udc*cos30= Udc / 根号3 ,这样的话Udc就标幺成 根号3 *2^15 ,你不是说少了个根号3吗?由于要除以Udc,因此相当于除以( 根号3 *2^15 ),所以根号3就没有了,但是还少除了个2^15,这个东西在程序中除了131072  这个是多少呢?(这个数是许多看了ST程序的人没有看懂的地方)  等于 4*327678 4是周期放大了4倍,32768是q15格式,在这里他除了,因此刚好可以解释为什么少了根号3/Udc,                 希望可以帮到想学的人,还有不懂的可以提问,不要问的太小白了
龙吞潭水 回答时间:2018-11-29 09:29:33
单片机_电子爱好者 发表于 2018-11-13 18:04
我这几天推了一下,知道为什么少了根号3/Udc,主要是因为标幺话的缘故,st程序中对V alfe和Vbeta标幺成Q15 ...

楼主,能不能分析一下 FOC 2.0 无感启动过程啊?  
void STO_Start_Up(void)
{
  s16 hAux;
#ifdef NO_SPEED_SENSORS_ALIGNMENT
  static u32 wAlignmentTbase=0;
#endif  
  
  switch(Start_Up_State)
  {
  case S_INIT:
    //Init Ramp-up variables
    if (hSpeed_Reference >= 0)
    {
      hFreq_Inc = FREQ_INC;
      hI_Inc = I_INC;
      if (wTime == 0)
      {
        wStart_Up_I = FIRST_I_STARTUP *1024;
      }
    }
    else
    {
      hFreq_Inc = -(s16)FREQ_INC;
      hI_Inc = -(s16)I_INC;
      if (wTime == 0)
      {
        wStart_Up_I = -(s32)FIRST_I_STARTUP *1024;
      }
    }
    Start_Up_State = ALIGNMENT;
    break;
   
  case ALIGNMENT:
#ifdef NO_SPEED_SENSORS_ALIGNMENT
    wAlignmentTbase++;
    if(wAlignmentTbase <= SLESS_T_ALIGNMENT_PWM_STEPS)
    {                  
      hFlux_Reference = SLESS_I_ALIGNMENT * wAlignmentTbase /
                                                    SLESS_T_ALIGNMENT_PWM_STEPS;               
      hTorque_Reference = 0;
      
      Stat_Curr_a_b = GET_PHASE_CURRENTS();
      Stat_Curr_alfa_beta = Clarke(Stat_Curr_a_b);
      Stat_Curr_q_d = Park(Stat_Curr_alfa_beta, SLESS_ALIGNMENT_ANGLE_S16);  
      /*loads the Torque Regulator output reference voltage Vqs*/   
      Stat_Volt_q_d.qV_Component1 = PID_Regulator(hTorque_Reference,
                        Stat_Curr_q_d.qI_Component1, &PID_Torque_InitStructure);  
      /*loads the Flux Regulator output reference voltage Vds*/
      Stat_Volt_q_d.qV_Component2 = PID_Regulator(hFlux_Reference,
                          Stat_Curr_q_d.qI_Component2, &PID_Flux_InitStructure);

      RevPark_Circle_Limitation();

      /*Performs the Reverse Park transformation,
      i.e transforms stator voltages Vqs and Vds into Valpha and Vbeta on a
      stationary reference frame*/

      Stat_Volt_alfa_beta = Rev_Park(Stat_Volt_q_d);

      /*Valpha and Vbeta finally drive the power stage*/
      CALC_SVPWM(Stat_Volt_alfa_beta);
    }
    else
    {
      wAlignmentTbase = 0;               
      Stat_Volt_q_d.qV_Component1 = Stat_Volt_q_d.qV_Component2 = 0;
      hTorque_Reference = PID_TORQUE_REFERENCE;
      hFlux_Reference = PID_FLUX_REFERENCE;
      Start_Up_State = RAMP_UP;
      hAngle = SLESS_ALIGNMENT_ANGLE_S16;      
    }
#else
    Start_Up_State = RAMP_UP;   
#endif   
    break;
   
  case RAMP_UP:
    wTime ++;  
    if (wTime <= I_STARTUP_PWM_STEPS)
    {     
      wStart_Up_Freq += hFreq_Inc;
      wStart_Up_I += hI_Inc;
    }
    else if (wTime <= FREQ_STARTUP_PWM_STEPS )
    {
      wStart_Up_Freq += hFreq_Inc;
    }      
    else
    {
      MCL_SetFault(START_UP_FAILURE);
      //Re_initialize Start Up
      STO_StartUp_Init();
    }
   
    //Add angle increment for ramp-up
    hAux = wStart_Up_Freq/65536;
    hAngle = (s16)(hAngle + (s32)(65536/(SAMPLING_FREQ/hAux)));
        
    Stat_Curr_a_b = GET_PHASE_CURRENTS();
    Stat_Curr_alfa_beta = Clarke(Stat_Curr_a_b);
    Stat_Curr_q_d = Park(Stat_Curr_alfa_beta, hAngle);
   
    hAux = wStart_Up_I/1024;
    hTorque_Reference = hAux;      
    hFlux_Reference = 0;
           
    /*loads the Torque Regulator output reference voltage Vqs*/   
    Stat_Volt_q_d.qV_Component1 = PID_Regulator(hTorque_Reference,
                        Stat_Curr_q_d.qI_Component1, &PID_Torque_InitStructure);
    /*loads the Flux Regulator output reference voltage Vds*/
    Stat_Volt_q_d.qV_Component2 = PID_Regulator(hFlux_Reference,
                          Stat_Curr_q_d.qI_Component2, &PID_Flux_InitStructure);
   
    RevPark_Circle_Limitation();
  
    /*Performs the Reverse Park transformation,
    i.e transforms stator voltages Vqs and Vds into Valpha and Vbeta on a
    stationary reference frame*/
   
    Stat_Volt_alfa_beta = Rev_Park(Stat_Volt_q_d);
  
    /*Valpha and Vbeta finally drive the power stage*/
    CALC_SVPWM(Stat_Volt_alfa_beta);
   
    STO_Calc_Rotor_Angle(Stat_Volt_alfa_beta,Stat_Curr_alfa_beta,MCL_Get_BusVolt());
   
    if (IsObserverConverged()==TRUE)
    {      
      PID_Speed_InitStructure.wIntegral = (s32)(hTorque_Reference*256);
      STO_StartUp_Init();  
      State = RUN;
      if ((wGlobal_Flags & SPEED_CONTROL) != SPEED_CONTROL)
      {
        hTorque_Reference = PID_TORQUE_REFERENCE;
        hFlux_Reference = PID_FLUX_REFERENCE;
      }      
    }   
    break;
  default:
    break;
  }   
}

/*******************************************************************************
* Function Name : STO_StartUp_Init
* Description : This private function initializes the sensorless start-up
* Input : details the input parameters.
* Output : details the output parameters.
* Return : details the return value.
*******************************************************************************/
void STO_StartUp_Init(void)
{
  //Re_initialize Start Up
  Start_Up_State = S_INIT;  
  hAngle = 0;
  wTime = 0;
  wStart_Up_Freq = 0;
  bConvCounter = 0;
}      
单片机_电子爱好者 回答时间:2018-12-3 10:31:33
龙吞潭水 发表于 2018-11-29 09:29
楼主,能不能分析一下 FOC 2.0 无感启动过程啊?  
void STO_Start_Up(void)
{

无感,我有时间看下,其实2.0的库是没有什么启动算法的比较简单,没有必要一定要照搬他的,按照一般的定位,开环,闭环就好了
单片机_电子爱好者 回答时间:2018-12-10 16:57:30
龙吞潭水 发表于 2018-11-29 09:29
楼主,能不能分析一下 FOC 2.0 无感启动过程啊?  
void STO_Start_Up(void)
{

我今天看了一下,st的无感启动流程大致是三步:预定位 强拖 闭环
预定位: 转矩电流给0  励磁电流给设定的最大电流值(从0增加到SLESS_I_ALIGNMENT) 把D轴吸到90度位置,执行时间是SLESS_T_ALIGNMENT设定的值默认700ms   时间已到完成预定位
强拖:    励磁电流给0  转矩电流从FIRST_I_STARTUP增加到设定的最大电流值FINAL_I_STARTUP执行时间I_START_UP_DURATION(默认FIRST_I_STARTUP=FINAL_I_STARTUP),并且在电流增加的过程角速度dpp从0增加到FINAL_START_UP_SPEED,执行时间FREQ_START_UP_DURATION,并且一直检测无感算法是否收敛,如果收敛闭环,否则继续拖,如果时间大于FREQ_START_UP_DURATION还未收敛,认为启动失败
闭环 : 就是无感估算位置啦
其实说白了就是BLDC的升压升频拖动,默认恒压升频拖动,讲的够详细了吧,个人愚见,有更好的启动算法可以讨论
龙吞潭水 回答时间:2018-12-11 12:26:10
单片机_电子爱好者 发表于 2018-12-10 16:57
我今天看了一下,st的无感启动流程大致是三步:预定位 强拖 闭环
预定位: 转矩电流给0  励磁电流给设定 ...

十分感谢您的讲解, 看来收益匪浅,  但是小弟还是有个问题不明白,转矩电流给定零的话,我理解成没有扭矩,即使D轴给了一个电流, 又怎么吸到90度位置啊 ?
单片机_电子爱好者 回答时间:2018-12-11 13:40:32
龙吞潭水 发表于 2018-12-11 12:26
十分感谢您的讲解, 看来收益匪浅,  但是小弟还是有个问题不明白,转矩电流给定零的话,我理解成没有扭 ...

转矩的定义是一直超前转子产生磁场力90度的力这样转矩做功才会最大,而励磁则是和磁场方向在同一直线上,但是这个定义的前提是知道转子的位置,而启动前位置不知道,其实给励磁或者给转矩效果是一样的,你可以试一下,用带霍尔的看下实际位置有什么区别,我理解用转矩拖动到90度的位置时开环拖动时的角度应该超前该角度90度即180度开始,而用励磁给多少度开环拖动就是从多少度开始拖,因此此处可以理解成吸,这个还得实际去验证,理论上是这样
单片机_电子爱好者 回答时间:2018-12-11 13:47:11
本帖最后由 单片机_电子爱好者 于 2018-12-11 14:03 编辑
龙吞潭水 发表于 2018-12-11 12:26
十分感谢您的讲解, 看来收益匪浅,  但是小弟还是有个问题不明白,转矩电流给定零的话,我理解成没有扭 ...


我之前回复了不知道为什么没了,转矩的定义是和转子磁场力成90度夹角,励磁是和磁场力在同一个直线上,正常控制时如果Ld=lq,我们Id=0,控制就可以实现最优的控制,但是在预定位阶段我们不知道转子的位置,这时候我们给定的励磁或者转矩其实对于电机是一样的,只不过这两个力之间有90度的夹角,只给转矩时,角度给90度时,转子被拖动到90度,但是由于我们的控制转矩是要超前转子90度的,则在开环拖动时起始的角度应该是要给180度;如果只给励磁,角度给90度时,转子被拖动到90度时,但此时的90度是相对于励磁而言的,因此拖动时初始位置直接给90度就好,因此可以叫吸到90度,实际你可以试下两种方法用霍尔看下转子的实际位置在哪个地方
龙吞潭水 回答时间:2018-12-12 10:14:28
嗯,小白对于您的讲解,总算明白了一些。另外请教一个PI 参数, 为啥要除以1024  或者 16384 等一些列参数
QQ图片20181212101343.png
单片机_电子爱好者 回答时间:2018-12-13 14:04:50
龙吞潭水 发表于 2018-12-12 10:14
嗯,小白对于您的讲解,总算明白了一些。另外请教一个PI 参数, 为啥要除以1024  或者 16384 等一些列参数 ...

因为在pi系数中乘了啊,你测试了2.0的无感吗?效果怎么样
龙吞潭水 回答时间:2018-12-14 12:15:52
单片机_电子爱好者 发表于 2018-12-13 14:04
因为在pi系数中乘了啊,你测试了2.0的无感吗?效果怎么样

我在看5.0的代码,发现看不懂, 转2.0的代码,2.0的代码清晰很多   实际电机没有调试过

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版