PLECS学习记录17-3:三相逆变器SVPWM调制--C-Script实现三相调制波的计算
三相逆变器SVPWM调制--C-Script实现三相调制波的计算
记录17-2中,已经使用数学方法算出了调制波的计算公式,现在就用Plecs中的C-Script模块来实现调制波的输出:
打开Plecs软件,新建一个仿真模型,并添加一个C-Script模块,如下图:

双击C-Script模块,弹出菜单,用于设置C-Script模块的参数:

因为我们要计算三相调制波,根据三相调制波的计算公式,我们需要设置一些变量,例如当Vm位于 第0扇区时,
三相调制波的计算公式如下:


我们需要计算三相调制波的表达式的话,我们就需要知道Tx、Ty的,然后Tx、Ty的计算,就需要知道正六边形的边长,即2Vin/3,也就是数=说需要知道Vin;
然后还需要知道待合成的矢量Vm位于哪个扇区,也就是需要提供待合成的矢量Vm的位置,而待合成的矢量Vm的位置是由它的横坐标和纵坐标来指定,所以C-Script模块需要给它3个输入:
Vin
矢量Vm的横坐标
矢量Vm的纵坐标
然后C-Script模块的输出也是有3个:
Vma、
Vmb
Vmc
这三个调制波的大小
因为我们需要在每个开关周期都要更新一下调制波的大小,所以Sample time(采样时间)设置为开关周期,所以可以设置为1/fs
然后在计算过程中,也会用到开关周期Ts,所以Parameters设置为fs,然后在程序里转换成开关周期即可:
所以C-Script模块的参数设置如下:

下面就开始程序的并编写:
先选择代码声明的选项:

为了方便,我们将三个输入定义为宏的形式:

然后选择输出功能代码选项,开始程序代码的编写:

代码编写:

如上图,使用IsSampleHit(0)来判断每个开关周期是否达到,如果达到就执行If下面对应的代码。
然后我们需要编写代码:

我们需要判断Vm这个向量位于正六边形的哪个扇区,定义一个函数:
Int getSector()

这个函数需要的参数是:Valpha(Vm的横坐标),Vbeta(Vm的纵坐标):

我们在计算Tx、Ty等这些值的话,需要知道Vm这个向量的幅值和角度的,所以我们直接在getSector()这个函数中一并算出来这两个需要的参数,
但是由于在C语言中函数无法直接返回多个值,即getSector()的返回值只有一个,所以我们只能通过指针将幅值和角度返回,

因为使用了Vm的幅值和角度,所以需要在程序中声明一下:

根据以前的推导,我们知道Tx、Ty的结果如下:


根据Tx、Ty的计算公式,我们可以编写Tx、Ty、T0的程序:
先在程序中声明一下Tx、Ty、T0:

然后根据公式编写程序:

上面完成之后,我们就可以,根据Vm位于哪个扇区,再根据记录62推导的计算公式,来编写计算程序:
首先我们把getSector()函数返回值赋值给sector这个变量,sector就对应了Vm位于哪个扇区的扇区值,

然后就可以根据sector的值写程序,使用switch()进行判断执行的操作:(计算公式见记录62)
代码如下:

现在来编写getSector()函数的程序代码:
getSector()函数写在代码声明里面:

使用atan2()这个函数,它是在知道横坐标x和纵坐标y的情况下,用来计算并返回α角度的:


使用atan2()函数得到了与水平轴的夹角globalAlpha:

.
得到了夹角globalAlpha之后,用它除以60°就可以得到Vm所在的扇区:


现在我们来求Vm这个矢量的长度Vm,我们知道Vm这个矢量的横坐标valpha和纵坐标vbeta,所以平方开根号就是它的长度:

然后我们来求解Vm所在的某个扇区时的α角度:
我们使用globalAlpha减去(扇区的编号乘以60°),就可以得到Vm所在某个扇区与Tx的夹角:
即:α = globalAlpha -(sector✖60°)

然后让程序返回所处的扇区值:

至此程序编写差不多了,点击apply会报错:


报错内容基本如下:

现在来改程序:
使用了atan2()、sqrt()等函数,但是没有在程序中包含头文件,需要加上<math.h>:

然后程序中多处使用fs,但是声明中没有定义,而且·fs是系统中的变量,需要使用ParamRealData()来得到用系统中的变量



完成上面的修改后,再次点击Apply,仍有几个报错,如下:

提示M_PI即π 没有定义,虽然我们包含了math.h这个头文件,但因为Plecs版本升级的原因,
新版本的PLECS安装路径中找到math.h文件,在里面搜索M_PI,前面有个宏定义判断,说是在没有定义__STRICT_ANSI__的情况下才M_PI宏才会被定义,你在C-Script中的code declaration中包含math.h那一行的前面写上#undef __STRICT_ANSI__就行,如下:

至此程序基本完成,完整的程序如下:


完成后,我们开始进行仿真验证:
添加constant,用于Vin:

设置为500V:

然后添加一个正弦波形、一个余弦波形,使用Sin模块:

一个正弦模块就可以设置输出正弦和余弦两个信号:


添加混合模块mux:

双击将它的输入改成[1 2],表示第一个输入有1路信号,第二个输入有2路信号:

添加示波器,并连接电路,如下:

然后设置仿真参数:
为系统中的fs、fg等赋值:


设置完成后,即可运行仿真:
仿真结果如下:

从波形中可以看出,中间一段波形有问题,
查找原因,调试的话,我们可以在程序中把sector这个值打印出来,查看是不是因为sector得到的值是有问题的:
在程序中添加一个打印命令,打印sector的值:

因为使用了printf()函数,所以声明中要包含它的头文件<stdio.h>:

修改完成之后,我们打开Plecs的命令行窗口:

然后运行仿真,这时可以看到sector的数值:

原因是因为atan2()函数:

atan2()函数返回的是-π到π之间的角度,而Vm是在0-2π之间,所以需要修改一下程序:
添加一个判断条件:

修改后,再次运行仿真,sector的值就正常了:

仿真波形也正常了,得到的结果如下:

结果正确。
完整程序代码如下:
1、Code declarations
#undef __STRICT_ANSI__
#include<math.h>
#include<stdio.h>
#define fs ParamRealData(0,0)
#define Vin Input(0)
#define Valpha Input(1)
#define Vbeta Input(2)
double vm, localAlpha;
double Tx, Ty, T0;
int getSector(double valpha, double vbeta, double *vm, double *localAlpha)
{
double globalAlpha = atan2(vbeta, valpha); //求与水平轴之间的夹角
if(globalAlpha < 0)
{
globalAlpha = globalAlpha + 2*M_PI;
}
int sector = floor(globalAlpha / (M_PI/3)); //求Vm所处的扇区
*vm = sqrt(valpha*valpha + vbeta*vbeta); //求Vm的长度
*localAlpha = globalAlpha-(sector * (M_PI/3)); //求Vm的与Tx之间的夹角
return sector;
}
2、Output function code
if(IsSampleHit(0))
{
int sector = getSector(Valpha, Vbeta, &vm, &localAlpha);//调用函数求Vm处于哪个扇区
//printf("sector = %d\n",sector);
Tx = sqrt(3)/fs*vm*cos(localAlpha + M_PI/6)/Vin; //计算Tx
Ty = sqrt(3)/fs*vm*sin(localAlpha)/Vin; //计算Ty
T0 = 1/fs - Tx - Ty; //计算T0
switch(sector)
{
case 0: //第0扇区
Output(0) = (T0 + 2*Ty +2*Tx)*fs -1;
Output(1) = (T0 + 2*Ty)*fs -1;
Output(2) = (T0)*fs -1;
break;
case 1: //第1扇区
Output(0) = (T0 +2*Tx)*fs -1;
Output(1) = (T0 + 2*Tx + 2*Ty)*fs -1;
Output(2) = (T0)*fs -1;
break;
case 2: //第2扇区
Output(0) = (T0)*fs -1;
Output(1) = (T0 + 2*Ty +2*Tx)*fs -1;
Output(2) = (T0 + 2*Ty)*fs -1;
break;
case 3: //第3扇区
Output(0) = (T0)*fs -1;
Output(1) = (T0 + 2*Tx)*fs -1;
Output(2) = (T0 + 2*Tx +2*Ty)*fs -1;
break;
case 4: //第4扇区
Output(0) = (T0 + 2*Ty)*fs -1;
Output(1) = (T0)*fs -1;
Output(2) = (T0 + 2*Ty +2*Tx)*fs -1;
break;
case 5: //第5扇区
Output(0) = (T0 + 2*Tx +2*Ty)*fs -1;
Output(1) = (T0)*fs -1;
Output(2) = (T0 + 2*Tx)*fs -1;
break;
}
}
3、仿真电路图:


DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)