为 Arduino 生成代码(生成 PWM 信号)¶
在本示例中,我们将向您展示如何在Engee中生成程序代码,以便在 Arduino 平台上生成 PWM 信号。
简介¶
创建脉宽调制(PWM)信号的方法有很多。我们将用基本元件实现一个模型,尽可能与演示示例arduino_blink
相似。也就是说,我们将控制 LED 亮起和熄灭之间的时间延迟。
其他可以使用的方法:
- 将平滑变化的模拟信号与锯齿波信号进行比较,并在交点时刻切换二极管。
- 使用 Arduino 的一个内置功能
平台准备¶
本示例需要一个 Arduino 兼容平台(Uno、Leonardo、Iskra 等)和一根合适的 USB 电缆。您还需要在计算机上安装 Arduino IDE,查找并安装 附加驱动程序(如有必要),并通过 USB 连接现有电路板。
型号说明¶
在这个示例中,我们将从模型pwm.engee
生成代码。
该模型的界面与arduino_blink
示例中的界面相同。在计算的每一步,它都会
- 利用
out_LED_BUILTIN
的输出切换 LED 的状态(最初等于 1,每个周期变为 "相反")、 - 利用
param_WAIT_MS
的输出向 Arduino 返回延时值(以毫秒为单位)。
有效值将随程序块Sine
中设置的频率变化为正弦波。最大值在同一程序块中设置为振幅,此处设置的偏移量可使延迟值永远不小于 0,否则 Arduino 平台会出错并停止程序执行。
在param_WAIT_MS
值的帮助下,我们将控制脉冲宽度,用不同长度的脉冲打开或关闭 Arduino 平台的 "板载 "LED。
PWM 信号的特点是,在$T_d$ 的固定周期内,它会改变状态1
和状态0
,其持续时间总计等于$T_d$ ,但其比例可通过参数$w$ (脉冲宽度)来改变。
。
我们将使用该信号在 Arduino 平台上模拟 LED 亮度的平滑控制。
数据类型转换¶
在大多数情况下,Engee 模型块直接反映在 Arduino 的代码中。并非所有平台都使用相同的 C/C++ 语言标准。当然,在创建代码时,您始终需要考虑底层的实现细节。
在本例中,我们在Engee中克服的问题是自动类型转换。在 Arduino 平台上
- 将布尔数据类型添加到数值数据类型时,输出为布尔型。
- 将双倍数据类型添加到无符号整数时,输出为无符号整数(如果不指定特殊数据类型,正弦波将无法正常工作)。
数据类型的问题出在哪里?
因此,我们需要设想数据类型的操作在 C 代码中的表现形式,并相应地配置模型块(用绿色"√"标记):
*Constant
模块应返回数据类型Float32
*Compare To Zero
模块不应返回bool
,而应返回uint8
所有这些设置都在相应的块中设置。有时,这些问题可以通过使用Data Type Conversion
块来解决,这种转换也会传递到生成的代码中。
模型测试¶
半自然建模过程 包括在模拟环境中运行模型进行调试和优化,随后在硬件平台上控制相同的算法。
在我们的案例中,值得考虑的是 Arduino 以自己的时钟频率运行,不同的命令可以在不同的时钟周期内执行。为了依赖真实物理时间,最好创建一个基于实时系统的代码生成模板。
不过,我们已经可以展示我们的解决方案将如何工作。
if "pwm" in [m.name for m in engee.get_all_models()]
m = engee.open( "pwm" );
else
m = engee.load( "$(@__DIR__)/pwm.engee" );
end
data = engee.run(m);
让我们绘制一个 LED 开关延迟时间图(参数传递给delay()
)。
using Plots
plot( data["param_WAIT_MS"].time, data["param_WAIT_MS"].value,
label="param_WAIT_MS", st=:step, size=(900,300))
# Подкрасим переменное время задержки (LED вкл/выкл)
plot!( data["param_WAIT_MS"].time, [iseven(i) ? d : NaN for (i,d) in enumerate(data["param_WAIT_MS"].value)],
label="задержка при выключенном LED", st=:step, size=(900,300), c=:black, lw=2)
plot!( data["param_WAIT_MS"].time, [isodd(i) ? d : NaN for (i,d) in enumerate(data["param_WAIT_MS"].value)],
label="задержка при включенном LED", st=:step, size=(900,300), c=:red, lw=2)
我们看到了什么?延时param_WAIT_MS
在时间上的变化是这样的:每两个相邻值相加总是在 10 毫秒左右。正弦波给出了调节这一过程的规律。
<br
如果我们将两个输出信号正确地组合在一起,就会看到控制 LED 输出端电流开关的 PWM 信号。
plot( cumsum(data["param_WAIT_MS"].value),
data["out_LED_BUILTIN"].value,
st=:step, size=(900,200))
该模型并非用于模拟实际运行时间,因此您可能会注意到模型时间(2 秒-模拟持续时间)与 CPU 时间不相等(根据图表,约为 1 秒,公差较大)。为了提供这种特性,您需要以不同的方式建立模型。
代码生成¶
在本演示中,我们建议使用以下命令生成代码:
engee.generate_code( "$(@__DIR__)/pwm.engee",
"$(@__DIR__)/sketch_pwm_custom/pwm_code" )
结果,在sketch_pwm_custom
目录中,我们将找到pwm_code
文件夹,在该文件夹中,我们将找到.c
和.h
文件,其中包含我们模型的代码。
项目文件¶
我们的项目中只有一个模型。在生成的文件中,我们只需要包含该模型代码的文件:源代码pwm.c
和头文件pwm.h
。
值得注意的是项目文件和目录的结构:
- 文件
sketch_pwm_custom.ino
包含模型-Arduino 接口的描述、sketch_pwm_custom
级目录必须与`.ino` 文件命名相同(Arduino IDE 要求)、 - 目录
pwm_code
包含生成代码的文件,我们将把这些代码包含在文件*.ino
中。
将模型传输到 Arduino¶
将项目转移到 Arduino 的标准步骤如下:
1.从文件浏览器下载目录sketch_pwm_custom
,解压压缩包; 2.
打开文件sketch_pwm_custom.ino
,点击按钮Upload
结果如下(LED 灯平稳闪烁):
结论¶
我们创建了一个比闪烁的 LED 稍为复杂的模型。这种创建 PWM 信号的方法可让您控制 LED 或伺服电机等简单机械。
我们必须考虑数据类型转换在目标平台上是如何工作的。不过,我们已经看到,Engee 平台可以通过代码生成,为几乎可以在硬件平台上无缝运行的组件建模。