三相正弦波发生器
在本演示中,我们将了解如何嵌入由 Engee 模型子系统生成的代码。
简介
本例的目的是建立一个三相正弦波发生器模型。发电机的输入信号是振幅 [V] 和频率 [Hz] 输出信号:瞬时相电压。正弦信号的相位差等于 。
在示例过程中,我们将在Engee模型中进行算法建模、代码生成、嵌入和测试,并在目标设备(Arduino 兼容平台)上进行嵌入和测试。
模型描述
所开发的模型sine_generator.engee
表示子系统SinGen
中包含的三相正弦波发生器的算法。子系统的输入为振幅值Amp = 1.0
和频率值Freq = 25.0
。输出正弦信号Sin_A
、Sin_B
和Sin_C
。
模型计算的步长为 0.001 秒。

子系统SinGen
的内容如下图所示。

该子系统使用以下公式重现标准计算:
建模结果
让我们加载并执行所述模型:
if "sine_generator" in [m.name for m in engee.get_all_models()]
m = engee.open( "sine_generator" );
else
m = engee.load( "$(@__DIR__)/sine_generator.engee" );
end
data = engee.run(m);
根据获得的模型数据,我们绘制输出变量--瞬时相电压SinGen.Sin_A
,SinGen.Sin_B
,SinGen.Sin_C
。
using Plots
plotlyjs()
plot(data["SinGen.Sin_A"].time, data["SinGen.Sin_A"].value,
label="V_a", size=(900,300), lw=2, st=:step)
plot!(data["SinGen.Sin_B"].time, data["SinGen.Sin_B"].value,
label="V_b", size=(900,300), lw=2, st=:step)
plot!(data["SinGen.Sin_C"].time, data["SinGen.Sin_C"].value,
label="V_c", size=(900,300), lw=2, st=:step,
legend=:topleft)
xlabel!("Время, сек")
ylabel!("Напряжение, В")
建模得到的输出信号图为频率为 25 Hz、振幅为 1 V、相移为 的三相正弦电压V_a
,V_b
,V_c
。
代码生成
要嵌入所开发的算法,必须从子系统SinGen
生成代码:
engee.generate_code( "$(@__DIR__)/sine_generator.engee",
"$(@__DIR__)/sine_generator_SinGen_code";
subsystem_name="SinGen" )
执行代码生成命令后,在指定目录下创建了main.c
、sine_generator_SinGen.h
和sine_generator_SinGen.c
文件。

现在,让我们看看并测试一下嵌入模型生成的代码的方法。
将代码嵌入 Engee 模型
为了测试生成的代码,我们将其嵌入 Engee 模型sine_generator_test.engee
中。算法的输入和输出参数与原始模型sine_generator.engee
中的参数相同。不过,算法本身是在嵌入到块C Function
中的生成 C 文件的基础上实现的。

代码嵌入包括以下内容。在程序块C Function
中,指定生成文件的位置,初始化输入和输出变量,并调用模型生成的计算函数。
程序块C Function
的选项卡</> OutputCode
的内容:
// engee-cfunction-start
//
// 生成源文件 /user/start/examples/codegen/sine_generator/sine_generator_SinGen_code/sine_generator_SinGen.c
// build include_directories /user/start/examples/codegen/sine_generator/sine_generator/sine_generator_SinGen_code
// 生成库目录
// 联编头文件 sine_generator_SinGen.h
// 联编定义
// 联编库
//
// 名称 范围 标签 类型 大小 端口
// 符号 A 输入 'A' 双 1 1
// 符号 F 输入 'F' 双 1 2
// 符号 Va 输出'Va' double 1 1
// 符号 Vb 输出'Vb' double 1 2
// 符号 Vc 输出'Vc' double 1 3
//
// 功能结束
//
// 将频率和振幅值传输到结构体中
正弦生成器_SinGen_U.频率 = F;
sine_generator_SinGen_U.Amplitude = A;
sine_generator_SinGen_step();
// 从结构中按相转移瞬时电压值
Va = sine_generator_SinGen_Y.Sin_A;
Vb = sine_generator_SinGen_Y.Sin_B;
Vc = 正弦发电机_SinGen_Y.Sin_C;
块C Function
的选项卡</> StartCode
的内容 :
// 调用初始化函数
sine_generator_SinGen_init();
C Function
块的</> TerminateCode
选项卡内容 :
// 调用终止函数
sine_generator_SinGen_term();
嵌入代码建模
让我们加载并执行sine_generator_test.engee
模型,以测试生成的代码:
if "sine_generator_test" in [n.name for n in engee.get_all_models()]
n = engee.open( "sine_generator_test" );
else
n = engee.load( "$(@__DIR__)/sine_generator_test.engee" );
end
test = engee.run(m);
根据获得的模型数据,绘制输出变量 - 瞬时相电压SinGen.Sin_A
,SinGen.Sin_B
,SinGen.Sin_C
。
plot(test["SinGen.Sin_A"].time, test["SinGen.Sin_A"].value,
label="V_a", size=(900,300), lw=2, st=:step)
plot!(test["SinGen.Sin_B"].time, test["SinGen.Sin_B"].value,
label="V_b", size=(900,300), lw=2, st=:step)
plot!(test["SinGen.Sin_C"].time, test["SinGen.Sin_C"].value,
label="V_c", size=(900,300), lw=2, st=:step,
legend=:topleft)
xlabel!("Время, сек")
ylabel!("Напряжение, В")
从获得的图形中可以看出,测试模型中产生的电压信号也是正弦波形式,具有指定的频率、振幅和相移。
让我们再比较一下原始模型和测试模型 A 相正弦信号的建模结果:
plot(data["SinGen.Sin_A"].time, data["SinGen.Sin_A"].value,
label="V_a", size=(900,300), lw=4, st=:step)
plot!(test["SinGen.Sin_A"].time, test["SinGen.Sin_A"].value,
label="V_a_test", size=(900,300), lw=2, st=:step,
legend=:topleft)
xlabel!("Время, сек")
ylabel!("Напряжение, В")
从上图可以看出,初始模型的模拟结果与测试代码生成结果完全一致。
将代码嵌入 Arduino 草图
为了在目标设备上测试开发的算法,有必要将生成的文件sine_generator_SinGen.c
和sine_generator_SinGen.h
插入用户程序项目中。
本示例使用 Amperka 公司的 Iskra Neo 控制器进行演示。在目标设备上执行算法时,控制器会将生成的信号值传输到串行端口。传输值的显示将通过 Arduino IDE 工具完成。
为了嵌入算法代码,我们之前开发了一个用于 Arduino IDEsine_generator.ino
的草图,该草图也附在本演示的文件夹中。该草图的内容与 Engee 测试模型C Function
块的内容在功能上完全相同,除了与外设的工作功能和维持计算步骤的周期。代码注释中给出了草图操作的详细说明。
在 Arduino 上执行代码
成功编译并将草图加载到目标设备后,让我们打开 Arduino IDE 工具箱中的 "串行绘图仪"。带输出信号的绘图仪截图如下图所示。

从绘图仪绘制的图中可以看出,所得到的信号也具有指定的振幅、频率和相移。
结论
在本演示中,开发了一个具有指定振幅、频率和相移等参数的三相正弦波发生器模型。在 Engee 模型中调试了发生器算法,然后将生成的代码文件嵌入 Engee 模型中进行测试,最后将生成的 C 文件加载到自定义草图中,并在目标设备上进行测试。
这样,通过一个简单的正弦波发生器例子,我们了解了从Engee模型生成代码的可能性。