首页 > 其他分享 >stm32 foc 库输出波形

stm32 foc 库输出波形

时间:2024-03-13 09:58:58浏览次数:18  
标签:duty int32 波形 foc stm32 vector pHandle time OVM

前言

本文为学习st的FOC库笔记,记录FOC库实际输出的PWM波形之间的区别。

关键词:SPWM,SVPWM,Over modulation,Discontinuous PWM

标准波形输出

对应Modulation flagsNone

alt text

可以看到,输出波形为马鞍波,即生成波形为SVPWM。

alt text
对比逆克拉克变换生成的SPWM,生成的波形两者幅值相同。

alt text
对比SPWM零序注入的SVPWM,可以看到生成的波形相同,幅值不同,相差(1848 - 1416)/(1790 - 1416) * 100% = 115.5% = \(\frac{2}{\sqrt{3}}\)。

注:SPWM(七段式)零序分量为:

\[e(t) = -\frac{(max(u(A,sin),u(B,sin),u(C,sin)) + min(u(A,sin),u(B,sin),u(C,sin)))}{2} \]

因此通过分扇区计算输出的SVPWM和零序注入的SVPWM实际上是相同的,在线性区间内,SVPWM带来了更大的调制比。

参考文章《零序分量注入SPWM等效为SVPWM - 知乎 (zhihu.com)》

总结

分扇区计算和零序注入,后者更便于实现,不需要考虑各种情况;但是前者可以同时获取当前所在扇区信息,在无传感器的情况下,前者带来了更大的信息量。

过调制

对应Modulation flagsOver modulation
alt text
可以看到,输出波形为马鞍波,但是幅值大于标准的马鞍波,为\(\frac{2}{\sqrt3}\)倍。

alt text
将Vq设置为满幅值输出时,此时为了避免输出超出正六边形,将波形调制为了梯形波。

参考ST的wiki,实际上是将调制范围扩大到了非线性区间。

参考文章:《STM32 MC SDK Overmodulation (new in V5.Y) - stm32mcu (stmicroelectronics.cn)》

过调制总结

一张图对比过调制效果:
alt text
过调制即最大幅值SVPWM,本质上是平滑的将FOC控制转变为六步换向控制(个人猜的),以获得最大的电压利用效率。

DPWM

对应Modulation flagsDiscontinuous PWM

alt text

看波形,DPWM本质也是SVPWM,只是无论任何时候总有一路输出始终为0,MOS管开关频率要低于SVPWM。标准SVPWM(又称CPWM)在一个扇区内有7次电压变换,DPWM有5次,因此又分别称为七段式SVPWM和五段式SVPWM。

参考文章:什么是DPWM调制方式? - 知乎 (zhihu.com)

DPWM总结

由于DPWM的调制方式,使得MOS管的切换频率降低,因此在调制比较高时,可以降低开关MOS管带来的损耗,获得更高的效率。

相关测试代码

void usb_printf(const char *format, ...)
{
  static char buffer[128];
  va_list args;
  va_start(args, format);
  vsnprintf(buffer, 127, format, args);
  va_end(args);

  CDC_Transmit_FS((uint8_t *)buffer,strlen(buffer));
}

/**
  * @brief  Trigonometrical functions type definition
  */
typedef struct
{
  int16_t hCos;
  int16_t hSin;
} Trig_Components;
/* CORDIC FUNCTION: COSINE q1.15 */
#define CORDIC_CONFIG_COSINE    (LL_CORDIC_FUNCTION_COSINE | LL_CORDIC_PRECISION_6CYCLES | LL_CORDIC_SCALE_0 |\
         LL_CORDIC_NBWRITE_1 | LL_CORDIC_NBREAD_1 |\
         LL_CORDIC_INSIZE_16BITS | LL_CORDIC_OUTSIZE_16BITS)


__weak Trig_Components MCM_Trig_Functions(int16_t hAngle)
{
  union u32toi16x2 {
    uint32_t CordicRdata;
    Trig_Components Components;
  } CosSin;

  WRITE_REG(CORDIC->CSR, CORDIC_CONFIG_COSINE);
  LL_CORDIC_WriteData(CORDIC, ((uint32_t)0x7FFF0000) + ((uint32_t)hAngle));
  CosSin.CordicRdata = LL_CORDIC_ReadData(CORDIC);
  return (CosSin.Components);
 
}


#define SECTOR_1  0U
#define SECTOR_2  1U
#define SECTOR_3  2U
#define SECTOR_4  3U
#define SECTOR_5  4U
#define SECTOR_6  5U

typedef struct
{
  int16_t alpha;
  int16_t beta;
} alphabeta_t;

typedef struct
{
  int16_t q;
  int16_t d;
} qd_t;


typedef struct PWMC_Handle
{
  uint16_t  hT_Sqrt3;
  uint16_t  PWMperiod;
  uint8_t   Sector;
  uint8_t   DPWM_Mode;
  uint16_t  CntPhA;
  uint16_t  CntPhB;
  uint16_t  CntPhC;
  
  
}PWMC_Handle_t;

#define SQRT3FACTOR ((uint16_t)0xDDB4) /* = (16384 * 1.732051 * 2)*/

PWMC_Handle_t pwmc_handle = 
{
  .hT_Sqrt3                   = (MAX_PERIOD*SQRT3FACTOR)/16384u,
  .PWMperiod                  = MAX_PERIOD,
  .DPWM_Mode                  = 1,
};

alphabeta_t Vab = 
{
  .alpha = 1,
  .beta = 0,
};
qd_t Vqd = 
{
  .q = 32767,
  .d = 0,
};

int vrefff = 0;

__weak uint16_t PWMC_SetPhaseVoltage(PWMC_Handle_t *pHandle, alphabeta_t Valfa_beta)
{
  uint16_t returnValue;
    int32_t wX;
    int32_t wY;
    int32_t wZ;
    int32_t wUAlpha;
    int32_t wUBeta;
    int32_t wTimePhA;
    int32_t wTimePhB;
    int32_t wTimePhC;

    wUAlpha = Valfa_beta.alpha * (int32_t)pHandle->hT_Sqrt3;
    wUBeta = -(Valfa_beta.beta * ((int32_t)pHandle->PWMperiod)) * 2;

    wX = wUBeta;
    wY = (wUBeta + wUAlpha) / 2;
    wZ = (wUBeta - wUAlpha) / 2;

    /* Sector calculation from wX, wY, wZ */
    if (wY < 0)
    {
      if (wZ < 0)
      {
        pHandle->Sector = SECTOR_5;
        wTimePhA = (((int32_t)pHandle->PWMperiod) / 4) + ((wY - wZ) / (int32_t)262144);
        wTimePhB = wTimePhA + (wZ / 131072);
        wTimePhC = wTimePhA - (wY / 131072) ;

        if(pHandle->DPWM_Mode == 1)
        {
          wTimePhA -= wTimePhB;
          wTimePhC -= wTimePhB;
          wTimePhB  = 0;
        }
        
      }
      else /* wZ >= 0 */
        if (wX <= 0)
        {
          pHandle->Sector = SECTOR_4;
          wTimePhA = (((int32_t)pHandle->PWMperiod) / 4) + ((wX - wZ) / (int32_t)262144);
          wTimePhB = wTimePhA + (wZ / 131072);
          wTimePhC = wTimePhB - (wX / 131072);

          if(pHandle->DPWM_Mode == 1)
          {
            wTimePhB -= wTimePhA;
            wTimePhC -= wTimePhA;
            wTimePhA = 0;
          }
          
        }
        else /* wX > 0 */
        {
          pHandle->Sector = SECTOR_3;
          wTimePhA = (((int32_t )pHandle->PWMperiod) / 4)+ ((wY - wX) / (int32_t)262144);
          wTimePhC = wTimePhA - (wY / 131072);
          wTimePhB = wTimePhC + (wX / 131072);
          
          if(pHandle->DPWM_Mode == 1)
          {
            wTimePhB -= wTimePhA;
            wTimePhC -= wTimePhA;
            wTimePhA = 0;
          }
        }
    }
    else /* wY > 0 */
    {
      if (wZ >= 0)
      {
        pHandle->Sector = SECTOR_2;
        wTimePhA = (((int32_t)pHandle->PWMperiod) / 4) + ((wY - wZ) / (int32_t)262144);
        wTimePhB = wTimePhA + (wZ / 131072);
        wTimePhC = wTimePhA - (wY / 131072);
        
        if(pHandle->DPWM_Mode == 1)
        {
          wTimePhA -= wTimePhC;
          wTimePhB -= wTimePhC;
          wTimePhC = 0;
        }
        
      }
      else /* wZ < 0 */
        if ( wX <= 0 )
        {
          pHandle->Sector = SECTOR_6;
          wTimePhA = (((int32_t )pHandle->PWMperiod) / 4) + ((wY - wX) / (int32_t)262144);
          wTimePhC = wTimePhA - (wY / 131072);
          wTimePhB = wTimePhC + (wX / 131072);
          
          if(pHandle->DPWM_Mode == 1)
          {
            wTimePhA -= wTimePhB;
            wTimePhC -= wTimePhB;
            wTimePhB = 0;
          }

        }
        else /* wX > 0 */
        {
          pHandle->Sector = SECTOR_1;
          wTimePhA = (((int32_t)pHandle->PWMperiod) / 4)+ ((wX - wZ) / (int32_t)262144);
          wTimePhB = wTimePhA + (wZ / 131072);
          wTimePhC = wTimePhB - (wX / 131072);

          if(pHandle->DPWM_Mode == 1)
          {
            wTimePhA -= wTimePhC;
            wTimePhB -= wTimePhC;
            wTimePhC = 0;
          }
          
        }
    }

    pHandle->CntPhA = (uint16_t)(MAX(wTimePhA, 0));
    pHandle->CntPhB = (uint16_t)(MAX(wTimePhB, 0));
    pHandle->CntPhC = (uint16_t)(MAX(wTimePhC, 0));

  return (returnValue);
}


#define    OVM_ONE_POINT_ZERO     ((int32_t)32768)
#define    OVM_GAIN_ARRAY_SIZE    ((int32_t)192)
#define    OVM_GAMMA_ARRAY_SIZE   ((int32_t)100)
#define    OVM_GAMMA_ARRAY_OFFSET ((int32_t)92)
#define    OVM_VREF_MODE1_START   ((int32_t)29717)
#define    OVM_VREF_MODE2_START   ((int32_t)31186)
#define    OVM_VREF_MODE2_END     ((int32_t)32768)
#define    OVM_VREF_INDEX_STEP    ((int32_t)16)
#define    OVM_1_DIV_SQRT3        ((int32_t)18919)
#define    OVM_1_DIV_PI           ((int32_t)10430)
#define    OVM_PI_DIV_6           ((int32_t)17157)
#define    OVM_3_DIV_PI           ((int32_t)31291)
#define    OVM_SQRT3              ((int32_t)56754)

typedef struct
{
  int32_t T1;
  int32_t T2;
} Vector_Time_t;

typedef enum
{
  OVM_LINEAR = 0,   /**< Linear mode. */
  OVM_1 = 1,        /**< Overmodulation mode 1. */
  OVM_2 = 2,        /**< Overmodulation mode 2. */
  OVM_ERROR = 3     /**< Error output. */
} OVM_Mode_t;

/* CORDIC FUNCTION: MODULUS q1.15 */
#define CORDIC_CONFIG_MODULUS   (LL_CORDIC_FUNCTION_MODULUS | LL_CORDIC_PRECISION_6CYCLES | LL_CORDIC_SCALE_0 |\
         LL_CORDIC_NBWRITE_1 | LL_CORDIC_NBREAD_1 |\
         LL_CORDIC_INSIZE_16BITS | LL_CORDIC_OUTSIZE_16BITS)

static inline int16_t MCM_Modulus(int16_t alpha, int16_t beta)
{
  uint32_t temp_val;
  __disable_irq();
  /* Configure and call to CORDIC- */
  WRITE_REG(CORDIC->CSR,CORDIC_CONFIG_MODULUS);
  LL_CORDIC_WriteData(CORDIC, (((uint32_t)beta << 16U) | (uint32_t)alpha));
  /* Wait for result */
  while(LL_CORDIC_IsActiveFlag_RRDY(CORDIC) == 0U)
  {
    /* Nothing to do */
  }
  /* Read computed modulus */
  temp_val = ((LL_CORDIC_ReadData(CORDIC) << 16U) >> 16U); /* Avoid Over/underflow when cast to int16_t */
  __enable_irq();
  return ((int16_t)temp_val);

}

static Vector_Time_t PWMC_RecalcT1T2_OVM(Vector_Time_t time, OVM_Mode_t mode, int16_t gamma)
{
  int32_t sum_t1_t2;
  int32_t offset;
  int32_t gain;
  int32_t t1_temp;
  Vector_Time_t time_prime;

  time_prime.T1 = 0;
  time_prime.T2 = 0;

  if ((OVM_LINEAR == mode) || (OVM_1 == mode))
  {
    sum_t1_t2 = time.T1 + time.T2;

    if (sum_t1_t2 > OVM_ONE_POINT_ZERO)
    {
      time_prime.T1 = ((time.T1 * OVM_ONE_POINT_ZERO) / sum_t1_t2);
      time_prime.T2 = OVM_ONE_POINT_ZERO - time_prime.T1;
    }
    else
    {
      time_prime.T1 = time.T1;
      time_prime.T2 = time.T2;
    }
  }
  else if (OVM_2 == mode)
  {
    if (time.T1 > OVM_ONE_POINT_ZERO)
    {
      time_prime.T1 = OVM_ONE_POINT_ZERO;
      time_prime.T2 = 0;
    }
    else if (time.T2 > OVM_ONE_POINT_ZERO)
    {
      time_prime.T1 = 0;
      time_prime.T2 = OVM_ONE_POINT_ZERO;
    }
    else
    {
      offset = (OVM_3_DIV_PI * gamma) / OVM_ONE_POINT_ZERO;
      gain = (OVM_PI_DIV_6 * OVM_ONE_POINT_ZERO) / (OVM_PI_DIV_6 - gamma);

      sum_t1_t2 = time.T1 + time.T2;
      sum_t1_t2 = ((0 == sum_t1_t2) ? 1 : sum_t1_t2);
      t1_temp = (time.T1 * OVM_ONE_POINT_ZERO) / sum_t1_t2;
      t1_temp = t1_temp - offset;
      if (t1_temp < 0)
      {
        t1_temp = 0;
      }
      else
      {
        /* Nothing to do */
      }
      if (gain > OVM_ONE_POINT_ZERO)
      {
        gain = gain / OVM_ONE_POINT_ZERO;
        time_prime.T1 = t1_temp * gain;
      }
      else
      {
        time_prime.T1 = (t1_temp * gain) / OVM_ONE_POINT_ZERO;
      }
      if (time_prime.T1 > OVM_ONE_POINT_ZERO)
      {
        time_prime.T1 = OVM_ONE_POINT_ZERO;
      }
      else
      {
        /* Nothing to do */
      }
      time_prime.T2 = OVM_ONE_POINT_ZERO - time_prime.T1;
    }
  }
  

  else  /* Error mode output 0 to protect */
  {
    time_prime.T1 = 0;
    time_prime.T2 = 0;
  }
  return (time_prime);
}

uint16_t PWMC_SetPhaseVoltage_OVM(PWMC_Handle_t *pHandle, alphabeta_t Valfa_beta)
{
  /* Private variables ----------------------------------------------------------*/
  /* Overmodulation gain array */
  static const uint16_t aOVMGain[OVM_GAIN_ARRAY_SIZE]={\
  31291,31291,31293,31295,31298,31300,31302,31306,31309,31314,\
  31319,31322,31328,31334,31338,31344,31350,31357,31364,31371,\
  31379,31386,31394,31402,31410,31419,31427,31439,31448,31457,\
  31470,31479,31492,31502,31515,31526,31539,31554,31568,31579,\
  31594,31609,31624,31639,31655,31675,31691,31707,31728,31745,\
  31766,31783,31805,31827,31845,31868,31891,31914,31942,31966,\
  31990,32019,32044,32074,32104,32134,32165,32202,32233,32271,\
  32303,32341,32386,32425,32470,32516,32562,32609,32662,32716,\
  32777,32838,32907,32982,33059,33144,33236,33343,33466,33612,\
  33797,34106,34463,34507,34551,34596,34640,34684,34729,34779,\
  34824,34869,34920,34971,35017,35068,35120,35178,35230,35282,\
  35340,35392,35451,35509,35568,35627,35686,35752,35811,35877,\
  35943,36009,36075,36148,36214,36287,36360,36434,36507,36581,\
  36661,36742,36822,36903,36990,37078,37159,37253,37342,37436,\
  37531,37627,37729,37831,37933,38042,38152,38261,38378,38495,\
  38612,38736,38860,38991,39122,39261,39399,39545,39691,39844,\
  40004,40165,40332,40507,40682,40871,41061,41264,41469,41680,\
  41906,42139,42387,42649,42911,43188,43488,43801,44137,44487,\
  44866,45275,45713,46195,46715,47300,47958,48720,49629,50759,\
  52346,56660,\
  };

  /* Overmodulation gamma array */
  static const int16_t aOVMGamma[100]={\
  52,154,255,354,453,551,648,757,852,947,\
  1052,1157,1249,1352,1454,1566,1666,1765,1875,1972,\
  2079,2186,2291,2395,2499,2612,2713,2824,2934,3042,\
  3150,3266,3372,3486,3599,3711,3821,3931,4049,4166,\
  4281,4395,4517,4637,4748,4875,4992,5115,5238,5359,\
  5487,5614,5739,5870,6000,6129,6263,6396,6528,6665,\
  6800,6941,7080,7224,7367,7514,7659,7809,7963,8115,\
  8272,8432,8590,8757,8922,9096,9268,9442,9624,9809,\
  10001,10200,10395,10597,10810,11028,11255,11487,11731,11987,\
  12254,12539,12835,13158,13507,13895,14335,14853,15530,17125,\
  };

  uint16_t retvalue;
    int32_t wX;
    int32_t wY;
    int32_t wZ;
    int32_t wUAlpha;
    int32_t wUBeta;
    int32_t vref;
    int32_t gain;
    int32_t neg_beta_cmd_div_sqrt3;
    int32_t duty_a;
    int32_t duty_b;
    int32_t duty_c;
    int32_t gama = 0;
    int16_t index;

    OVM_Mode_t ovm_mode_flag;
    Vector_Time_t vector_time;

    /* Transfer vref to vcmd */
    vref = (int32_t)MCM_Modulus( Valfa_beta.alpha, Valfa_beta.beta );

    vrefff = vref;
    
    if (vref < OVM_VREF_MODE1_START)      /* Linear range */
    {
      wUAlpha = Valfa_beta.alpha;
      wUBeta = Valfa_beta.beta;
      ovm_mode_flag = OVM_LINEAR;
    }
    else if (vref < OVM_VREF_MODE2_START) /* OVM mode 1 range */
    {
      index = (int16_t)((vref - OVM_VREF_MODE1_START) / OVM_VREF_INDEX_STEP);
      gain = (int32_t)aOVMGain[index];
      wUAlpha = (Valfa_beta.alpha * gain) / OVM_ONE_POINT_ZERO;
      wUBeta = (Valfa_beta.beta * gain) / OVM_ONE_POINT_ZERO;
      ovm_mode_flag = OVM_1;
    }
    else if (vref < OVM_VREF_MODE2_END)  /* OVM mode 2 range */
    {
      index = (int16_t)((vref - OVM_VREF_MODE1_START) / OVM_VREF_INDEX_STEP);
      gain = (int32_t)aOVMGain[index];
      wUAlpha = (Valfa_beta.alpha * gain) / OVM_ONE_POINT_ZERO;
      wUBeta = (Valfa_beta.beta * gain) / OVM_ONE_POINT_ZERO;
      if (index > OVM_GAMMA_ARRAY_OFFSET)
      {
        gama = aOVMGamma[index - OVM_GAMMA_ARRAY_OFFSET];
      }
      else
      {
        gama = aOVMGamma[0];
      }
      ovm_mode_flag = OVM_2;
    }
    else      /* Out of OVM mode 2 range only a protection to prevent the code to a undefined branch */
    {
      wUAlpha = 0;
      wUBeta = 0;
      ovm_mode_flag = OVM_ERROR;
    }

    /* Vcmd to X, Y, Z */
    neg_beta_cmd_div_sqrt3 = ((-wUBeta) * OVM_1_DIV_SQRT3) / OVM_ONE_POINT_ZERO;
    wX = neg_beta_cmd_div_sqrt3 * 2;           /* x=-(2/sqrt(3))*beta */
    wY = wUAlpha + neg_beta_cmd_div_sqrt3;     /* x=alpha-(1/sqrt(3))*beta */
    wZ = -wUAlpha + neg_beta_cmd_div_sqrt3;;   /* x=-alpha-(1/sqrt(3))*beta */

    /* Sector calculation from wX, wY, wZ */
    if (wY < 0)
    {
      if (wZ < 0)
      {
        pHandle->Sector = SECTOR_5;
        vector_time.T1 = -wY;
        vector_time.T2 = -wZ;
        vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama );

        duty_a = 16384 + ((-vector_time.T1 + vector_time.T2) / 2);
        duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
        duty_b = 16384 + ((-vector_time.T1 - vector_time.T2) / 2);
        duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
        duty_c = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
        duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

      }
      else /* wZ >= 0 */
        if (wX <= 0)
        {
          pHandle->Sector = SECTOR_4;
          vector_time.T1 = wZ;
          vector_time.T2 = -wX;
          vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama );
          duty_a = 16384 + ((- vector_time.T1 - vector_time.T2) / 2);
          duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
          duty_b = 16384 + ((vector_time.T1 - vector_time.T2) / 2);
          duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
          duty_c = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
          duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

        }
        else /* wX > 0 */
        {
          pHandle->Sector = SECTOR_3;
          vector_time.T1 = wX;
          vector_time.T2 = -wY;
          vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama );
          duty_a = 16384 + ((-vector_time.T1 - vector_time.T2) / 2);
          duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
          duty_b = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
          duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
          duty_c = 16384 + ((- vector_time.T1 + vector_time.T2) / 2);
          duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

        }
    }
    else /* wY > 0 */
    {
      if (wZ >= 0)
      {
        pHandle->Sector = SECTOR_2;
        vector_time.T1 = wY;
        vector_time.T2 = wZ;
        vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama);
        duty_a = 16384 + ((vector_time.T1 - vector_time.T2) / 2);
        duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
        duty_b = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
        duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
        duty_c = 16384 + ((-vector_time.T1 - vector_time.T2) / 2);
        duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

      }
      else /* wZ < 0 */
        if (wX <= 0)
        {
          pHandle->Sector = SECTOR_6;
          vector_time.T1 = -wX;
          vector_time.T2 = wY;
          vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama);
          duty_a = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
          duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
          duty_b = 16384 + ((-vector_time.T1 - vector_time.T2) / 2);
          duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
          duty_c = 16384 + ((vector_time.T1 - vector_time.T2) / 2);
          duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

        }
        else /* wX > 0 */
        {
          pHandle->Sector = SECTOR_1;
          vector_time.T1 = -wZ;
          vector_time.T2 = wX;
          vector_time = PWMC_RecalcT1T2_OVM( vector_time, ovm_mode_flag, (int16_t)gama);
          duty_a = 16384 + ((vector_time.T1 + vector_time.T2) / 2);
          duty_a = (((int32_t)pHandle->PWMperiod) * duty_a) >> 16;
          duty_b = 16384 + ((-vector_time.T1 + vector_time.T2) / 2);
          duty_b = (((int32_t)pHandle->PWMperiod) * duty_b) >> 16;
          duty_c = 16384 + ((-vector_time.T1 - vector_time.T2) / 2);
          duty_c = (((int32_t)pHandle->PWMperiod) * duty_c) >> 16;

        }
    }

    pHandle->CntPhA = (uint16_t)duty_a ;
    pHandle->CntPhB = (uint16_t)duty_b ;
    pHandle->CntPhC = (uint16_t)duty_c;
  return (retvalue);
}

__weak alphabeta_t MCM_Rev_Park(qd_t Input, int16_t Theta)
{
  int32_t alpha_tmp1;
  int32_t alpha_tmp2;
  int32_t beta_tmp1;
  int32_t beta_tmp2;
  Trig_Components Local_Vector_Components;
  alphabeta_t Output;

  Local_Vector_Components = MCM_Trig_Functions(Theta);

  /* No overflow guaranteed */
  alpha_tmp1 = Input.q * ((int32_t)Local_Vector_Components.hCos);
  alpha_tmp2 = Input.d * ((int32_t)Local_Vector_Components.hSin);

  Output.alpha = (int16_t)(((alpha_tmp1) + (alpha_tmp2)) >> 15);
  
  beta_tmp1 = Input.q * ((int32_t)Local_Vector_Components.hSin);
  beta_tmp2 = Input.d * ((int32_t)Local_Vector_Components.hCos);

  Output.beta = (int16_t)((beta_tmp2 - beta_tmp1) >> 15);
  return (Output);
}

typedef struct
{
  int16_t a;
  int16_t b;
  int16_t c;
} abc_t;

__weak abc_t MCM_REV_Clarke(alphabeta_t Input)
{
  abc_t Output;

  int32_t b_SQRT3_tmp;
  int32_t wbeta_tmp;
  int16_t hbeta_tmp;

  /*qIas = qIalpha*/
  Output.a = Input.alpha;

  b_SQRT3_tmp = (SQRT3FACTOR) * ((int32_t)Input.beta) >> 15;

  /* qIbs = (sqrt(3) * qIbeta - qIalpha) / 2 */
  wbeta_tmp = ((b_SQRT3_tmp) - (int32_t)Input.alpha) >> 1;
  /* Check saturation of Ibeta */
  if (wbeta_tmp > INT16_MAX)
  {
    hbeta_tmp = INT16_MAX;
  }
  else if (wbeta_tmp < (-32768))
  {
    hbeta_tmp =  ((int16_t)-32768);
  }
  else
  {
    hbeta_tmp = ((int16_t)wbeta_tmp);
  }

  Output.b = hbeta_tmp;

  if (((int16_t )-32768) == Output.b)
  {
    Output.b = -32767;
  }
  else
  {
    /* Nothing to do */
  }
  
  /* qIcs = (- sqrt(3) * qIbeta - qIalpha) / 2 */
  wbeta_tmp = (-(b_SQRT3_tmp) - (int32_t)Input.alpha) >> 1;
  /* Check saturation of Ibeta */
  if (wbeta_tmp > INT16_MAX)
  {
    hbeta_tmp = INT16_MAX;
  }
  else if (wbeta_tmp < (-32768))
  {
    hbeta_tmp =  ((int16_t)-32768);
  }
  else
  {
    hbeta_tmp = ((int16_t)wbeta_tmp);
  }

  Output.c = hbeta_tmp;

  if (((int16_t )-32768) == Output.c)
  {
    Output.c = -32767;
  }
  else
  {
    /* Nothing to do */
  }
  
//  SPWM
//  {
//  pwmc_handle.CntPhA = (Output.a + 0x7fff) * MAX_PERIOD >> 17;
//  pwmc_handle.CntPhB = (Output.b + 0x7fff) * MAX_PERIOD >> 17;
//  pwmc_handle.CntPhC = (Output.c + 0x7fff) * MAX_PERIOD >> 17;
//  }
// SVPWM
  {
  int16_t et = -(MAX3(Output.a, Output.b,Output.c) + MIN3(Output.a,Output.b,Output.c))/2;

  pwmc_handle.CntPhA = (Output.a + et + 0x7fff) * MAX_PERIOD >> 17;
  pwmc_handle.CntPhB = (Output.b + et + 0x7fff) * MAX_PERIOD >> 17;
  pwmc_handle.CntPhC = (Output.c + et + 0x7fff) * MAX_PERIOD >> 17;
  }
  return (Output);
}


int angle = 0;

void app_main_loop(void)
{
  Vab = MCM_Rev_Park(Vqd,angle);
//  PWMC_SetPhaseVoltage_OVM(&pwmc_handle,Vab);
  PWMC_SetPhaseVoltage(&pwmc_handle,Vab);
//  MCM_REV_Clarke(Vab);
  usb_printf("%d,%d,%d,%d,%d,%d\r\n",Vab.alpha,Vab.beta,pwmc_handle.CntPhA,pwmc_handle.CntPhB,pwmc_handle.CntPhC,vrefff);
  HAL_Delay(0);
  angle+= 0x0f;
  angle %= 0xffff;
}

标签:duty,int32,波形,foc,stm32,vector,pHandle,time,OVM
From: https://www.cnblogs.com/USTHzhanglu/p/18065519

相关文章

  • STM32模拟IIC读取ACD10红外二氧化碳数据
    引脚介绍ACD10通过IIC来通信我们使用下图右边四个引脚就可以了,系统默认模式为IIC通信方式,他也支持USART串口通信不过需要配置pin5引脚(低电平)。模拟IIC通信配置比较简单,在单片机上面随便找两个引脚就可以。用来配置SDA数据与SCL时钟引脚。读取数据命令官方给我们命令行列......
  • 基于STM32F103C8T6单片机学习(江科大版本)
    学习内容1:用库函数来控制IO输出控制LED闪烁,LED流水灯,蜂鸣器主要用到GPIO_unit()函数配置GPIO口和RCC外设时钟控制函数,GPIO的写函数,setbitsresitbits,write等函数 1.led闪烁1.文件配置LED闪烁硬件电路图​​​​​ 首先打开文件管理器,在STM32>工程项目文件......
  • 在stm32f767中使用fmc外挂dram
    `uint16_tbuf[6]attribute((at(0xd0000000)))={0};//将缓冲数组分配到外部dram中。voidTestDram(void){uint16_txxx[6]={0x1111,0x2222,0x3333,0x4444,0x5555,0x6666};for(inti=0;i<5;i++){buf[i]=xxx[i];}for(inti=0;i<5;i++){ if(xxx[i]!......
  • stm32 TIM输出比较(OC) PWM
    stm32P6-4 05:00  ([6-4]PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱动直流电机_哔哩哔哩_bilibili)1.stm32f10x.tim.h部分头文件讲解voidTIM_DeInit(TIM_TypeDef*TIMx);​​​​​​​voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct......
  • STM32 LwIP学习过程问题总结(一):LwIP ping不通,抓包发现ICMP校验和为0x0000
    一、问题今天在将之前的STM32LwIP1.4.1版本程序移植到2.1.2版本上时,发现ping不同,但是开发板有ICMP回复包,黄颜色警告checksum为0x0000。说明LwIP移植应该是没问题,数据处理这一块出错了。 在网上找了下相关的错误,ST论坛有个问题和我这个一样。HardwareIPv4checksumonanST......
  • STM32标准库通用定时器输出比较
    STM32标准库通用定时器输出比较1.初始化voidTIM2_Init(){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟 GPIO_InitTypeDefGPIO_InitSt......
  • STM32标准库通用定时器输入捕获
    STM32标准库定时器输入捕获1.输入捕获介绍输入捕获为STM32定时器的一个功能,可以用来测量输入信号的频率和占空比。具体原理:当输入信号经过比较捕获通道时,STM32会依据通道的极性设置决定是否触发捕获中断TIM_IT_CCx。此时定时器会将当前计数值TIMx->CNT的值保存在TIMx->CCRx中,通......
  • STM32移植完FATFS的ROM不够解决方法
    1.移植完FatFs之后会有语言包的支持,在map文件中也可以查看到也就是cc936.c这个文件现在cc936占用ROM大约为175030,在本项目中不需要中文支持所以取消掉即可,取消方法如下第一种方法(通过CubeMX配置的代码)不要使能中文文件名称就好了,记得改这个 第二种方法(库函数或者HAL库没有......
  • PARA第6部分:提升专注、创造力和判断力的小批量项目 (Small-Batch Projects for Focus,
    内容简介:这部分主要讲的是把项目拆成小项目,再去执行的重要性。对这些小项目的要求是:短期内可以完成、结果明确并且有最后的完成期限。把项目拆小的好处:可以让我们聚焦于小项目,不再焦虑;有助于捕捉灵感,提高创造力;有助于产生新鲜感,再枯燥的项目也不怕。正文在P.A.R.A第一部分中,我......
  • 转载:用示波器对单片机I2C时序进行图形波形分析的试验小结
    对于嵌入式开发的朋友来说,I2C协议实在是再熟悉不过了,有太多的器件,采用的都是通过I2C来进行相应的设置。今天,我们就随便聊聊这个I2C协议。I2C协议中最重要的一点是I2C地址。这个地址有7位和10位两种形式。7位能够表示127个地址,而在实际使用中基本上不会挂载如此多的设置,所以很多......