Engee 文档
Notebook

Arduino的代码生成(在有限状态机上闪烁LED)

在这个例子中,我们将在Engee中开发最简单的模型,用于使用库有限自动机控制Arduino兼容板的内置LED。

导言

Engee有限状态机库**是开发控制算法(包括目标平台)的有用而有效的工具。 将算法表示为具有多个定义状态和它们之间的条件转换的图,使得调试和升级更加直观和方便。 这增加了控制程序开发的速度并降低了出错的可能性。

此示例的目的是展示使用有限自动机库为Arduino兼容平台创建闪烁LED控制算法的过程。
该示例实际上是演示示例的变体。 arduino_blink 它包括模型如何工作的描述和演示。 blink_chart. 在该模型中,LED状态(开/关)和开关延迟量由单元决定 chart.

硬件支持

要测试算法,您可以使用任何兼容Arduino的平台。 Engee模型的多平台性质是由于生成的C代码作为插件c文件导入,硬件配置在第三方软件中进行。

在这个例子中,我们使用[Iskra Neo调试板从Amperka](https://amperka.ru/product/iskra-neo )。 它通过USB-USB-micro电缆连接到PC。 [Arduino IDE]用于编译用户程序并将其上传到控制器(https://www.arduino.cc/en/software /),并且还需要接口芯片驱动程序。 便携式数字示波器[来自Seeed Studio的DSO Quad Alloy Black]用于演示程序如何在硬件上工作(https://amperka.ru/product/dso-quad-oscilloscope )。

hardware.png

模型描述

Arduino板的集成LED控制模型由一个单元组成 Chart 再现控制算法,以及两个输出触点 Outport: out_LED_BUILTINСhart. 作为变量的第一个信号在Arduino草图中与输出引脚(GPIO)编号13相关联,该引脚也是内置LED的控制触点。 第二信号显示单元内部计数器的状态 Chart. 这两个信号也用于在模型中记录。

ModelScreeen.JPG

在街区里 chart 使用两个输出信号: out,初始值为"真"和 cnt

状态图

状态图(块内容 Chart)有4个状态:

  1. init -算法的初始状态,计数器的初始值在进入状态时设置 cnt = 0;.
  2. increment -算法的主要状态,这里将计数器值与过渡条件(编号为1,2,3的过渡)进行比较,并在进入状态时增加计数器值 cnt = cnt + 1;. 计数器值增加"1"实际上相当于增加1毫秒,因为算法的计算将在1毫秒内进行,这将在Arduino草图代码中进一步定义。
  3. ON -如果计数器的值小于499毫秒,则计数器增加的状态。当满足此条件时,控制LED的输出信号被设置为"真"。
  4. OFF -如果计数器的值大于或等于499毫秒,则计数器增加的状态。当满足此条件时,控制LED的输出信号被设置为"假"。

当计数器达到大于或等于998ms的值时,关系图切换到状态 init. 计数器被限制在998毫秒,因为它需要两个2毫秒的周期来计算init状态,它不直接控制LED。 因此,LED闪烁周期的总持续时间为1000毫秒。

image.png

在开发模型时要考虑的另一个要点是执行转换的顺序。 正是按照这个顺序,将规定从一个国家过渡到一个有条件的结构的条件。 if(){} elseif(){} ... else{} 生成的C文件。


例如,在此模型中,条件是周期结束 [cnt >= 998] 它首先被检查,尽管如果它的订单是3,那么条件的成功实现 [cnt >= 499] 它将防止它被检查,并且周期计数器不会重置。 另一方面,在每个计算周期中检查周期的结束条件是无效的,并且这种转变应该被分配顺序3并且转变条件应该被改变为状态 OFF[(cnt >= 499) && (cnt < 998)]

模拟结果

让我们加载描述的模型:

In [ ]:
if "blink_chart" in [m.name for m in engee.get_all_models()]
    m = engee.open( "blink_chart" );
else
    m = engee.load( "$(@__DIR__)/blink_chart.engee" );
end

data = engee.run(m);

从获得的模型数据中,我们将绘制计数器值的变化。:

In [ ]:
using Plots
plot(data["Cnt"].time, data["Cnt"].value,
    label="Cnt", size=(900,300), lw=2)
xlims!(0.0,3.0)
Out[0]:

如您所见,计数器的值从0到1000不等,频率为1000ms。 out_LED_BUILTIN,它控制内置的Arduino LED。

In [ ]:
plot(data["out_LED_BUILTIN"].time, data["out_LED_BUILTIN"].value,
    label="out_LED_BUILTIN", size=(900,300), lw=2)   
xlims!(0.0,3.0)
Out[0]:

我们收到一个周期为1000ms的周期性矩形信号,填充因子为50%。

在Arduino上运行算法

要将开发的模型传输到目标设备,我们将生成一个C代码。:

In [ ]:
engee.generate_code( "$(@__DIR__)/blink_chart.engee",
                     "$(@__DIR__)/sketch_blink_chart_custom/blink_chart_code" )
Out[0]:
"Created directory - /user/start/examples/codegen/arduino_blink_chart/sketch_blink_chart_custom/blink_chart_code"

插件文件是在指定的目录中生成的。 也在目录中 sketch_blink_chart_custom 已经发布了带有此目录名称的预先编写的Arduino草图。 sketch_blink_chart_custom.ino. 它连接在代码生成过程中获得的头文件,初始化微控制器的外围设备,并调用函数来控制LED。 草图的详细描述在其代码的注释中给出。


要在Arduino上执行代码,您需要下载目录 sketch_blink_chart_custom 并上传草图 sketch_blink_chart_custom.ino 从Arduino IDE到目标设备。 在我们的例子中,如前所述,这是来自Amperka的Iskra Neo。


草图编译后,会显示一条消息,说明操作成功和输出文件的大小。:

Compilation.JPG

从Arduino板移除信号

将代码加载到Arduino后,您可以在调试板上看到闪烁的LED。 为了清楚起见,在示例的描述中,我们将将示波器的测量触点连接到调试板上的引脚13并取下示波器。

FirstOscillogramma.jpg

从取出的波形可以看出,在调试板的引脚13上形成填充时间为500ms、周期为1000ms的周期性矩形信号。

结论

在考虑的示例中,使用Engee有限状态机库为Arduino兼容平台开发了数字输出控制模型,并描述了代码生成期间正确高效操作的原则。


从开发的模型生成代码并上传到目标设备。 程序在调试板上执行的结果与仿真结果完全一致。

示例中使用的块