SVPWM实现

SVPWM实现

    • 按SVPWM原理按部就班实现
    • 查表法实现
    • 总结

继上一篇SVPWM原理之后,这篇来讲讲SVPWM的C语言实现。实现方法列举了两种,其本质都是上篇文章中所提到过的。

按SVPWM原理按部就班实现

bool A, B, C;
int N, flag;
double alf, beta, u_1, u_2, u_3, K, x, y, z, t_x, t_y, t_xy, t_a, t_b, t_c;

alf = (*u_alf);
beta = (*u_beta);

u_1 = beta;
u_2 = 1.732*alf-beta;
u_3 = -1.732*alf-beta;
if(u_1>0) A=1; else A=0;
if(u_2>0) B=1; else B=0;
if(u_3>0) C=1; else C=0;
N = 4*C+2*B+A;

K = 1.732 * T / u_dc;
x = K*u_1;
y = 0.5*K*u_2;
z = 0.5*K*u_3;
switch (N)
{
    case 1: flag = 2; t_x = -y, t_y = -z; break;
    case 2: flag = 6; t_x = -z, t_y = -x; break;
    case 3: flag = 1; t_x = y, t_y = x; break;
    case 4: flag = 4; t_x = -x, t_y = -y; break;
    case 5: flag = 3; t_x = x, t_y = z; break;
    case 6: flag = 5; t_x = z, t_y = y; break;
}
if(t_x+t_y>T)
{
    t_xy = t_x+t_y;
    t_x = t_x*T/t_xy;
    t_y = t_y*T/t_xy;
}
t_a = (T-t_x-t_y)/4;
t_b = t_a+t_x/2;
t_c = t_b+t_y/2;
switch (flag)
{
    case 1: (*t_cmp1) = t_a; (*t_cmp2) = t_b; (*t_cmp3) = t_c; break;
    case 2: (*t_cmp1) = t_b; (*t_cmp2) = t_a; (*t_cmp3) = t_c; break;
    case 3: (*t_cmp1) = t_c; (*t_cmp2) = t_a; (*t_cmp3) = t_b; break;
    case 4: (*t_cmp1) = t_c; (*t_cmp2) = t_b; (*t_cmp3) = t_a; break;
    case 5: (*t_cmp1) = t_b; (*t_cmp2) = t_c; (*t_cmp3) = t_a; break;
    case 6: (*t_cmp1) = t_a; (*t_cmp2) = t_c; (*t_cmp3) = t_b; break;
}
/* %%%-SFUNWIZ_wrapper_Outputs_Changes_END --- EDIT HERE TO _BEGIN */
}

查表法实现

void MySVPWM(_SVPWM_Struct * sv)
{
    const uint8 SVPWM_Table[6][5] = { { 2, 3, 2, 1, 3 },
			{ 3, 1, 1, 3, 2 }, { 2, 1, 1, 2, 3 }, { 1, 2, 3, 2, 1 }, \
			{ 1, 3, 3, 1, 2 }, { 3, 2, 2, 3, 1 } };
	uint8 SectorMap = 0;
	float32 U[4];
	float32 T1 = 0, T2 = 0;
	float32 T[4];
	float32 Valpha, Vbeta;

	sv->PWM_PRS = 0.5f;
	sv->PWM_PRS_Inv = 2.0f;

	Valpha = sv->va;
	Vbeta  = sv->vb;

	U[1] = Vbeta;
	U[2] = 0.866f * Valpha - 0.5f * Vbeta;
	U[3] = -0.866f * Valpha - 0.5f * Vbeta;

	//SectorMap calculate && calculate abs(V)
	if (U[1] > 0)		SectorMap += 1;
	else				U[1] = -U[1];
	if (U[2] > 0)		SectorMap += 2;
	else				U[2] = -U[2];
	if (U[3] > 0)		SectorMap += 4;
	else				U[3] = -U[3];

	if (SectorMap <= 0 || SectorMap >= 7) {
		sv->comp[0] = sv->PWM_PRS*0.5f;
		sv->comp[1] = sv->PWM_PRS*0.5f;
		sv->comp[2] = sv->PWM_PRS*0.5f;
	} else {
		T1 = U[SVPWM_Table[SectorMap - 1][0]];
		T2 = U[SVPWM_Table[SectorMap - 1][1]];

		if ((T1 + T2) > 1.0f) {
			T1 = T1 / (T1 + T2) * 1.0f;
			T2 = 1.0f - T1;
		}

		T[1] = (1.0f - T1 - T2) * 0.5f;
		T[2] = T[1] + T1 * 1.0f;
		T[3] = T[2] + T2 * 1.0f;

		
		sv->comp[0] = T[SVPWM_Table[SectorMap - 1][2]] * sv->PWM_PRS;
		sv->comp[1] = T[SVPWM_Table[SectorMap - 1][3]] * sv->PWM_PRS;
		sv->comp[2] = T[SVPWM_Table[SectorMap - 1][4]] * sv->PWM_PRS;
	}

}

总结

仔细对比两段代码可以发现它们其实是一样的;但又略有差别。其差别在于上篇SVPWM原理中PWM逆变器输出基本电压矢量部分,从该部分的表格中不难看出六个基本输出电压矢量幅值均为 2/3 倍的直流母线电压,再由八个空间电压矢量位置图看到最大的输出电压矢量圆的半径为 cos30° 与基本电压矢量幅值的乘积,即 (1 / 3^(1/2)) 倍直流母线电压。

最后附上基于 Matlab R2017a 的 simulink ,采用 S-function 分别实现的两种 SVPWM 。
(SVPWM.7z)

你可能感兴趣的:(运动控制)