MCSDK 库输出波形测试
前言
本文为学习st的电机库MCSDK
笔记,实际输出的PWM波形之间的区别。
关键词:MCSDK
,SPWM
,SVPWM
,Over modulation
,Discontinuous PWM
,
标准波形输出
对应Modulation flags
为None
可以看到,输出波形为马鞍波,即生成波形为SVPWM。
对比逆克拉克变换生成的SPWM,生成的波形两者幅值相同。
对比SPWM零序注入的SVPWM,可以看到生成的波形相同,幅值不同,相差(1848 - 1416)/(1790 - 1416) * 100% = 115.5% = \(\frac{2}{\sqrt{3}}\)。
注:SPWM(七段式)零序分量为:
因此通过分扇区计算输出的SVPWM和零序注入的SVPWM实际上是相同的,在线性区间内,SVPWM带来了更大的调制比。
参考文章《零序分量注入SPWM等效为SVPWM - 知乎 (zhihu.com)》
总结
分扇区计算和零序注入,后者更便于实现,不需要考虑各种情况;但是前者可以同时获取当前所在扇区信息,在无传感器的情况下,前者带来了更大的信息量。
过调制
对应Modulation flags
为Over modulation
可以看到,输出波形为马鞍波,但是幅值大于标准的马鞍波,为\(\frac{2}{\sqrt3}\)倍。
将Vq设置为满幅值输出时,此时为了避免输出超出正六边形,将波形调制为了梯形波。
参考ST的wiki,实际上是将调制范围扩大到了非线性区间。
参考文章:《STM32 MC SDK Overmodulation (new in V5.Y) - stm32mcu (stmicroelectronics.cn)》
过调制总结
一张图对比过调制效果:
过调制即最大幅值SVPWM,本质上是平滑的将FOC控制转变为六步换向控制(个人猜的),以获得最大的电压利用效率。
DPWM
对应Modulation flags
为Discontinuous PWM
看波形,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;
}