278 lines
6.4 KiB
C
278 lines
6.4 KiB
C
//
|
|
// Created by ZK on 2023/3/16.
|
|
//
|
|
|
|
#include "SVPWM.h"
|
|
|
|
|
|
#define SVM 1
|
|
|
|
extern uint16_t cycleNum;
|
|
|
|
#define SQRT3 1.732050808f
|
|
#define LIMIT (float32_t)(0.9f / SQRT3)
|
|
#define LIMIT_UDC 16.0f
|
|
#define TS 3400
|
|
#define SQRT3_MULT_TS (float32_t)((float32_t)TS * SQRT3)
|
|
|
|
uint8_t sectionMap[7] = {0, 2, 6, 1, 4, 3, 5};
|
|
float32_t uAlpha, uBeta;
|
|
float32_t ud, uq;
|
|
uint16_t channel1, channel2, channel3,udc=12;
|
|
float uAlpha, uBeta;
|
|
float32_t iAlpha, iBeta;
|
|
float32_t id, iq;
|
|
|
|
inline void inversePark(float ud, float uq, float Theta, float *uAlpha, float *uBeta) {
|
|
float s = sinf(Theta / 57.2958f);
|
|
float c = cosf(Theta / 57.2958f);
|
|
*uAlpha = ud * c - uq * s;
|
|
*uBeta = ud * s + uq * c;
|
|
}
|
|
|
|
#ifdef false
|
|
|
|
inline int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC) {
|
|
float U1, U2, U3;
|
|
uint8_t a, b, c, n = 0;
|
|
|
|
U1 = uBeta;
|
|
U2 = (SQRT3 * uAlpha - uBeta) / 2;
|
|
U3 = (-SQRT3 * uAlpha - uBeta) / 2;
|
|
|
|
if (U1 > 0)
|
|
a = 1;
|
|
else
|
|
a = 0;
|
|
if (U2 > 0)
|
|
b = 1;
|
|
else
|
|
b = 0;
|
|
if (U3 > 0)
|
|
c = 1;
|
|
else
|
|
c = 0;
|
|
|
|
n = (c << 2) + (b << 1) + a;
|
|
|
|
switch (sectionMap[n])
|
|
{
|
|
case 0:
|
|
{
|
|
channel1 = TS / 2;
|
|
channel2 = TS / 2;
|
|
channel3 = TS / 2;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
int16_t t4 = SQRT3 * TS * U2 / udc;
|
|
int16_t t6 = SQRT3 * TS * U1 / udc;
|
|
int16_t t0 = (TS - t4 - t6) / 2;
|
|
|
|
channel1 = t4 + t6 + t0;
|
|
channel2 = t6 + t0;
|
|
channel3 = t0;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
{
|
|
int16_t t2 = -SQRT3 * TS * U2 / udc;
|
|
int16_t t6 = -SQRT3 * TS * U3 / udc;
|
|
int16_t t0 = (TS - t2 - t6) / 2;
|
|
|
|
channel1 = t6 + t0;
|
|
channel2 = t2 + t6 + t0;
|
|
channel3 = t0;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
int16_t t2 = SQRT3 * TS * U1 / udc;
|
|
int16_t t3 = SQRT3 * TS * U3 / udc;
|
|
int16_t t0 = (TS - t2 - t3) / 2;
|
|
|
|
channel1 = t0;
|
|
channel2 = t2 + t3 + t0;
|
|
channel3 = t3 + t0;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
{
|
|
int16_t t1 = -SQRT3 * TS * U1 / udc;
|
|
int16_t t3 = -SQRT3 * TS * U2 / udc;
|
|
int16_t t0 = (TS - t1 - t3) / 2;
|
|
|
|
channel1 = t0;
|
|
channel2 = t3 + t0;
|
|
channel3 = t1 + t3 + t0;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
{
|
|
int16_t t1 = SQRT3 * TS * U3 / udc;
|
|
int16_t t5 = SQRT3 * TS * U2 / udc;
|
|
int16_t t0 = (TS - t1 - t5) / 2;
|
|
|
|
channel1 = t5 + t0;
|
|
channel2 = t0;
|
|
channel3 = t1 + t5 + t0;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
{
|
|
int16_t t4 = -SQRT3 * TS * U3 / udc;
|
|
int16_t t5 = -SQRT3 * TS * U1 / udc;
|
|
int16_t t0 = (TS - t4 - t5) / 2;
|
|
|
|
channel1 = t4 + t5 + t0;
|
|
channel2 = t0;
|
|
channel3 = t5 + t0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
*tA = channel1;
|
|
*tB = channel2;
|
|
*tC = channel3;
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
#else
|
|
|
|
inline int SVPWM(float uAlpha, float uBeta, float *tA, float *tB, float *tC) {
|
|
int Sextant;
|
|
|
|
if (uBeta >= 0.0f) {
|
|
if (uAlpha >= 0.0f) {
|
|
//quadrant I
|
|
if (ONE_BY_SQRT3 * uBeta > uAlpha)
|
|
Sextant = 2; //sextant v2-v3
|
|
else
|
|
Sextant = 1; //sextant v1-v2
|
|
|
|
} else {
|
|
//quadrant II
|
|
if (-ONE_BY_SQRT3 * uBeta > uAlpha)
|
|
Sextant = 3; //sextant v3-v4
|
|
else
|
|
Sextant = 2; //sextant v2-v3
|
|
}
|
|
} else {
|
|
if (uAlpha >= 0.0f) {
|
|
//quadrant IV
|
|
if (-ONE_BY_SQRT3 * uBeta > uAlpha)
|
|
Sextant = 5; //sextant v5-v6
|
|
else
|
|
Sextant = 6; //sextant v6-v1
|
|
} else {
|
|
//quadrant III
|
|
if (ONE_BY_SQRT3 * uBeta > uAlpha)
|
|
Sextant = 4; //sextant v4-v5
|
|
else
|
|
Sextant = 5; //sextant v5-v6
|
|
}
|
|
}
|
|
|
|
switch (Sextant) {
|
|
// sextant v1-v2
|
|
case 1: {
|
|
// Vector on-times
|
|
float t1 = uAlpha - ONE_BY_SQRT3 * uBeta;
|
|
float t2 = TWO_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tA = (1.0f - t1 - t2) * 0.5f;
|
|
*tB = *tA + t1;
|
|
*tC = *tB + t2;
|
|
}
|
|
break;
|
|
|
|
// sextant v2-v3
|
|
case 2: {
|
|
// Vector on-times
|
|
float t2 = uAlpha + ONE_BY_SQRT3 * uBeta;
|
|
float t3 = -uAlpha + ONE_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tB = (1.0f - t2 - t3) * 0.5f;
|
|
*tA = *tB + t3;
|
|
*tC = *tA + t2;
|
|
}
|
|
break;
|
|
|
|
// sextant v3-v4
|
|
case 3: {
|
|
// Vector on-times
|
|
float t3 = TWO_BY_SQRT3 * uBeta;
|
|
float t4 = -uAlpha - ONE_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tB = (1.0f - t3 - t4) * 0.5f;
|
|
*tC = *tB + t3;
|
|
*tA = *tC + t4;
|
|
}
|
|
break;
|
|
|
|
// sextant v4-v5
|
|
case 4: {
|
|
// Vector on-times
|
|
float t4 = -uAlpha + ONE_BY_SQRT3 * uBeta;
|
|
float t5 = -TWO_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tC = (1.0f - t4 - t5) * 0.5f;
|
|
*tB = *tC + t5;
|
|
*tA = *tB + t4;
|
|
}
|
|
break;
|
|
|
|
// sextant v5-v6
|
|
case 5: {
|
|
// Vector on-times
|
|
float t5 = -uAlpha - ONE_BY_SQRT3 * uBeta;
|
|
float t6 = uAlpha - ONE_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tC = (1.0f - t5 - t6) * 0.5f;
|
|
*tA = *tC + t5;
|
|
*tB = *tA + t6;
|
|
}
|
|
break;
|
|
|
|
// sextant v6-v1
|
|
case 6: {
|
|
// Vector on-times
|
|
float t6 = -TWO_BY_SQRT3 * uBeta;
|
|
float t1 = uAlpha + ONE_BY_SQRT3 * uBeta;
|
|
|
|
// PWM timings
|
|
*tA = (1.0f - t6 - t1) * 0.5f;
|
|
*tC = *tA + t1;
|
|
*tB = *tC + t6;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// if any of the results becomes NaN, result_valid will evaluate to false
|
|
int result_valid = *tA >= 0.0f && *tA <= 1.0f && *tB >= 0.0f && *tB <= 1.0f && *tC >= 0.0f && *tC <= 1.0f;
|
|
|
|
return result_valid ? 0 : -1;
|
|
|
|
// TIM1->CCR1 = channelA;
|
|
// TIM1->CCR2 = channelB;
|
|
// TIM1->CCR3 = channelC;
|
|
}
|
|
|
|
#endif |