|
|
@@ -2,9 +2,9 @@
|
|
|
#include "math/fast_math.h"
|
|
|
|
|
|
void svpwm(alpha_beta_t *alpha_beta, float vbus, uint32_t PWM_half_period, phase_time_t *phase_out, u8 *sector_out){
|
|
|
- float alpha = alpha_beta->alpha / (2.0f/2.0f * vbus);
|
|
|
- float beta = alpha_beta->beta / (2.0f/2.0f * vbus);
|
|
|
- uint32_t sector;
|
|
|
+ float alpha = alpha_beta->alpha / (3.0f/2.0f * vbus);
|
|
|
+ float beta = alpha_beta->beta / (3.0f/2.0f * vbus);
|
|
|
+ uint32_t sector = 0xFF;
|
|
|
|
|
|
if (beta >= 0.0f) {
|
|
|
if (alpha >= 0.0f) {
|
|
|
@@ -146,5 +146,354 @@ void svpwm(alpha_beta_t *alpha_beta, float vbus, uint32_t PWM_half_period, phase
|
|
|
phase_out->midle = midle;
|
|
|
phase_out->high = high;
|
|
|
*sector_out = sector;
|
|
|
+#if 0
|
|
|
+ static int tet_p = 0;
|
|
|
+ if (tet_p++ % 5 == 0) {
|
|
|
+ printf("$%d %d %d;", tA, tB, tC);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+#if 0
|
|
|
+static u8 __inline Calc_N(alpha_beta_t *alpha_beta){
|
|
|
+ float sqr_alpha = alpha_beta->alpha * SQRT3_BY_2;
|
|
|
+ float half_beta = 0.5f * alpha_beta->beta;
|
|
|
+ return (((sqr_alpha - half_beta > 0.0f) << 1) + (alpha_beta->beta > 0.0f)) + ((-(sqr_alpha + half_beta) > 0.0f) << 2);
|
|
|
+}
|
|
|
+
|
|
|
+static void __inline Calc_XYZ(alpha_beta_t *alpha_beta, float vbus, uint32_t PWM_Period, float *XYZ_Out) {
|
|
|
+ float modu = (1.0f / vbus) * (float)PWM_Period;
|
|
|
+ float sqr_beta = SQRT3_BY_2 * alpha_beta->beta;
|
|
|
+ float alpha = 1.5f * alpha_beta->alpha;
|
|
|
+
|
|
|
+ XYZ_Out[0] = SQRT3 * alpha_beta->beta * modu;
|
|
|
+ XYZ_Out[1] = (sqr_beta + alpha) * modu;
|
|
|
+ XYZ_Out[2] = (sqr_beta - alpha) * modu;
|
|
|
+}
|
|
|
+#endif
|
|
|
+static void __inline ModuleTime(u32 *T4, u32 *T6, u32 PWM_Period) {
|
|
|
+ u32 period = PWM_Period * 95 / 100; //95%的调制
|
|
|
+ if (*T4 + *T6 > period){
|
|
|
+ float ration = ((float)period)/((float)*T4 + (float)*T6);
|
|
|
+ *T4 *= ration;
|
|
|
+ *T6 *= ration;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 7段式SVPWM
|
|
|
+ * 返回设置3相PWM的3个CCR寄存器的值
|
|
|
+ * 这里使用的是stm32的PWM mode1,在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
|
|
|
+ * 在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
|
|
|
+*/
|
|
|
+void SVPWM_7(alpha_beta_t *alpha_beta, float vbus, u32 PWM_half_period, phase_time_t *phase_out, u8 *sector_out) {
|
|
|
+ float alpha = alpha_beta->alpha * 2.0f / 3.0f;
|
|
|
+ float beta = alpha_beta->beta * 2.0f / 3.0f;
|
|
|
+ u8 sector = 0xFF;
|
|
|
+ u32 A_duty, B_duty, C_duty;
|
|
|
+ u32 low, midle, high;
|
|
|
+ u32 T1, T2;
|
|
|
+ float X, Y, Z;
|
|
|
+ float modu = (float)(PWM_half_period) / vbus;
|
|
|
+
|
|
|
+ if (beta >= 0.0f) {
|
|
|
+ if (alpha >= 0.0f) {
|
|
|
+ //quadrant I
|
|
|
+ if (ONE_BY_SQRT3 * beta > alpha) {
|
|
|
+ sector = SECTOR_2;
|
|
|
+ } else {
|
|
|
+ sector = SECTOR_1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //quadrant II
|
|
|
+ if (-ONE_BY_SQRT3 * beta > alpha) {
|
|
|
+ sector = SECTOR_3;
|
|
|
+ } else {
|
|
|
+ sector = SECTOR_2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (alpha >= 0.0f) {
|
|
|
+ //quadrant IV5
|
|
|
+ if (-ONE_BY_SQRT3 * beta > alpha) {
|
|
|
+ sector = SECTOR_5;
|
|
|
+ } else {
|
|
|
+ sector = SECTOR_6;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //quadrant III
|
|
|
+ if (ONE_BY_SQRT3 * beta > alpha) {
|
|
|
+ sector = SECTOR_4;
|
|
|
+ } else {
|
|
|
+ sector = SECTOR_5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //X = SQRT3 * beta * modu;
|
|
|
+ X = TWO_BY_SQRT3 * beta * modu;
|
|
|
+ //Y = (1.5f * alpha + SQRT3_BY_2 * beta) * modu;
|
|
|
+ Y = (alpha + ONE_BY_SQRT3 * beta) * modu;
|
|
|
+ //Z = (-1.5f * alpha + SQRT3_BY_2 * beta) * modu;
|
|
|
+ Z = (-alpha + ONE_BY_SQRT3 * beta) * modu;
|
|
|
+ switch(sector) {
|
|
|
+ case SECTOR_1: // 3
|
|
|
+ T1 = -Z;
|
|
|
+ T2 = X;
|
|
|
+ break;
|
|
|
+ case SECTOR_2: // 1
|
|
|
+ T1 = Z;
|
|
|
+ T2 = Y;
|
|
|
+ break;
|
|
|
+ case SECTOR_3: // 5
|
|
|
+ T1 = X;
|
|
|
+ T2 = -Y;
|
|
|
+ break;
|
|
|
+ case SECTOR_4: // 4
|
|
|
+ T1 = -X;
|
|
|
+ T2 = Z;
|
|
|
+ break;
|
|
|
+ case SECTOR_5: // 6
|
|
|
+ T1 = -Y;
|
|
|
+ T2 = -Z;
|
|
|
+ break;
|
|
|
+ case SECTOR_6: // 2
|
|
|
+ T1 = Y;
|
|
|
+ T2 = -X;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ModuleTime(&T1, &T2, PWM_half_period);
|
|
|
+ u32 ta = (PWM_half_period - T1 - T2) / 2;
|
|
|
+ u32 tb = ta + T1 ;
|
|
|
+ u32 tc = tb + T2 ;
|
|
|
+ switch(sector) {
|
|
|
+ case SECTOR_1: // 3
|
|
|
+ A_duty = (PWM_half_period - T1 - T2) / 2;
|
|
|
+ B_duty = A_duty + T1;
|
|
|
+ C_duty = B_duty + T2;
|
|
|
+
|
|
|
+ low = A_duty;
|
|
|
+ midle = B_duty;
|
|
|
+ high = C_duty;
|
|
|
+ break;
|
|
|
+ case SECTOR_2: // 1
|
|
|
+ B_duty = (PWM_half_period - T1 - T2) / 2;
|
|
|
+ A_duty = B_duty + T1;
|
|
|
+ C_duty = A_duty + T2;
|
|
|
+
|
|
|
+ low = B_duty;
|
|
|
+ midle = A_duty;
|
|
|
+ high = C_duty;
|
|
|
+ break;
|
|
|
+ case SECTOR_3: // 5
|
|
|
+ A_duty = tc;
|
|
|
+ B_duty = ta;
|
|
|
+ C_duty = tb;
|
|
|
+
|
|
|
+ low = B_duty;
|
|
|
+ midle = C_duty;
|
|
|
+ high = A_duty;
|
|
|
+ break;
|
|
|
+ case SECTOR_4: // 4
|
|
|
+ A_duty = tc;
|
|
|
+ B_duty = tb;
|
|
|
+ C_duty = ta;
|
|
|
+
|
|
|
+ low = C_duty;
|
|
|
+ midle = B_duty;
|
|
|
+ high = A_duty;
|
|
|
+ break;
|
|
|
+ case SECTOR_5: // 6
|
|
|
+ A_duty = tb;
|
|
|
+ B_duty = tc;
|
|
|
+ C_duty = ta;
|
|
|
+
|
|
|
+ low = C_duty;
|
|
|
+ midle = A_duty;
|
|
|
+ high = B_duty;
|
|
|
+ break;
|
|
|
+ case SECTOR_6: // 2
|
|
|
+ A_duty = ta;
|
|
|
+ B_duty = tc;
|
|
|
+ C_duty = tb;
|
|
|
+
|
|
|
+ low = A_duty;
|
|
|
+ midle = C_duty;
|
|
|
+ high = B_duty;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ phase_out->A = A_duty;
|
|
|
+ phase_out->B = B_duty;
|
|
|
+ phase_out->C = C_duty;
|
|
|
+ phase_out->low = low;
|
|
|
+ phase_out->midle = midle;
|
|
|
+ phase_out->high = high;
|
|
|
+ *sector_out = sector;
|
|
|
+#if 0
|
|
|
+ static int tet_p = 0;
|
|
|
+ if (tet_p++ % 5 == 0) {
|
|
|
+ printf("$%d %d %d;", A_duty, B_duty, C_duty);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+// printf("3sec %d, A:%d, B:%d, C:%d\n", sector, A_duty, B_duty, C_duty);
|
|
|
}
|
|
|
|
|
|
+#if 0
|
|
|
+
|
|
|
+void XYZ_step(void)
|
|
|
+{
|
|
|
+ real_T rtb_Product1;
|
|
|
+ real_T rtb_Product2;
|
|
|
+ real_T rtb_Product3;
|
|
|
+
|
|
|
+ /* Product: '<S1>/Product' incorporates:
|
|
|
+ * Inport: '<Root>/Ts'
|
|
|
+ * Inport: '<Root>/Udc'
|
|
|
+ * Math: '<S1>/Math Function'
|
|
|
+ *
|
|
|
+ * About '<S1>/Math Function':
|
|
|
+ * Operator: reciprocal
|
|
|
+ */
|
|
|
+ rtb_Product1 = 1.0 / rtU.Udc * rtU.Ts;
|
|
|
+
|
|
|
+ /* Gain: '<S1>/Gain2' incorporates:
|
|
|
+ * Inport: '<Root>/Ubeta'
|
|
|
+ */
|
|
|
+ rtb_Product2 = 0.8660254037844386 * rtU.Ubeta;
|
|
|
+
|
|
|
+ /* Gain: '<S1>/Gain' incorporates:
|
|
|
+ * Inport: '<Root>/Ualpha'
|
|
|
+ */
|
|
|
+ rtb_Product3 = 1.5 * rtU.Ualpha;
|
|
|
+
|
|
|
+ /* Outport: '<Root>/XYZ' incorporates:
|
|
|
+ * Gain: '<S1>/Gain1'
|
|
|
+ * Inport: '<Root>/Ubeta'
|
|
|
+ * Product: '<S1>/Product1'
|
|
|
+ * Product: '<S1>/Product2'
|
|
|
+ * Product: '<S1>/Product3'
|
|
|
+ * Sum: '<S1>/Add'
|
|
|
+ * Sum: '<S1>/Add1'
|
|
|
+ */
|
|
|
+ rtY.XYZ_d[2] = (rtb_Product2 - rtb_Product3) * rtb_Product1;
|
|
|
+ rtY.XYZ_d[1] = (rtb_Product2 + rtb_Product3) * rtb_Product1;
|
|
|
+ rtY.XYZ_d[0] = 1.7320508075688772 * rtU.Ubeta * rtb_Product1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* Model step function */
|
|
|
+void T1T2_step(void)
|
|
|
+{
|
|
|
+ real_T rtb_Subtract;
|
|
|
+ real_T rtb_T1;
|
|
|
+ real_T rtb_T2;
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch' incorporates:
|
|
|
+ * Gain: '<S1>/Gain'
|
|
|
+ * Gain: '<S1>/Gain1'
|
|
|
+ * Gain: '<S1>/Gain2'
|
|
|
+ * Inport: '<Root>/N'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ switch ((int32_T)rtU.N) {
|
|
|
+ case 1:
|
|
|
+ rtb_T1 = rtU.XYZ[2];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = rtU.XYZ[1];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ rtb_T1 = rtU.XYZ[1];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Gain: '<S1>/Gain'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = -rtU.XYZ[0];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 3:
|
|
|
+ rtb_T1 = -rtU.XYZ[2];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Gain: '<S1>/Gain2'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = rtU.XYZ[0];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 4:
|
|
|
+ rtb_T1 = -rtU.XYZ[0];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Gain: '<S1>/Gain'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = rtU.XYZ[2];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 5:
|
|
|
+ rtb_T1 = rtU.XYZ[0];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Gain: '<S1>/Gain1'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = -rtU.XYZ[1];
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ rtb_T1 = -rtU.XYZ[1];
|
|
|
+
|
|
|
+ /* MultiPortSwitch: '<S1>/Multiport Switch1' incorporates:
|
|
|
+ * Gain: '<S1>/Gain1'
|
|
|
+ * Gain: '<S1>/Gain2'
|
|
|
+ * Inport: '<Root>/XYZ'
|
|
|
+ */
|
|
|
+ rtb_T2 = -rtU.XYZ[2];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* End of MultiPortSwitch: '<S1>/Multiport Switch' */
|
|
|
+
|
|
|
+ /* Sum: '<S1>/Subtract' */
|
|
|
+ rtb_Subtract = rtb_T1 + rtb_T2;
|
|
|
+
|
|
|
+ /* Switch: '<S1>/Switch' incorporates:
|
|
|
+ * Inport: '<Root>/Tpwm'
|
|
|
+ * Sum: '<S1>/Subtract1'
|
|
|
+ * Switch: '<S1>/Switch1'
|
|
|
+ */
|
|
|
+ if (rtU.Tpwm - rtb_Subtract > 0.0) {
|
|
|
+ /* Outport: '<Root>/T1 ' */
|
|
|
+ rtY.T1 = rtb_T1;
|
|
|
+
|
|
|
+ /* Outport: '<Root>/T2' */
|
|
|
+ rtY.T2 = rtb_T2;
|
|
|
+ } else {
|
|
|
+ /* Outport: '<Root>/T1 ' incorporates:
|
|
|
+ * Product: '<S1>/Divide'
|
|
|
+ * Product: '<S1>/Product'
|
|
|
+ */
|
|
|
+ rtY.T1 = rtb_T1 * rtU.Tpwm / rtb_Subtract;
|
|
|
+
|
|
|
+ /* Outport: '<Root>/T2' incorporates:
|
|
|
+ * Product: '<S1>/Divide1'
|
|
|
+ * Product: '<S1>/Product1'
|
|
|
+ */
|
|
|
+ rtY.T2 = 1.0 / rtb_Subtract * (rtb_T2 * rtU.Tpwm);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* End of Switch: '<S1>/Switch' */
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|