Engee documentation
Notebook

Code generation for Arduino (Flashing LED on finite automata)

In this example, we will develop a simple model in Engee to control the built-in LED of Arduino-compatible boards using the Finite Automata library.

Introduction

The Engee** library of finite automata serves as a useful and efficient tool for developing control algorithms, including those for target platforms. Representing an algorithm as a graph with several defined states and conditional transitions between them makes it more visual and easy to debug and modernise. Thus, the speed of control programme development is increased and the probability of error is reduced.

The purpose of this example is to show the process of creating a blinking LED control algorithm for Arduino-compatible platforms using the finite automata library. The example is essentially a variant of the demo example arduino_blink and includes a description and demonstration of the model blink_chart. In this model, the state of the LED (on/off) and the switching delay are determined by the block chart.

Hardware

Any Arduino-compatible platform can be used to test the algorithm. The multiplatform nature of engee models is due to the fact that the generated C code is imported as C plug-in files, while the hardware configuration takes place in third-party software.

In this example we use a debug board Iskra Neo from Amperka. It is connected to PC via USB to USB-micro cable. To compile the user program and load it into the controller we use Arduino IDE, and we need a driver for the interface chip. To demonstrate the work of the programme on the hardware, a portable digital oscilloscope DSO Quad Alloy Black from Seeed Studio is used.

hardware.png

Model Description

The inbuilt LED control model of the Arduino board consists of one block Chart, which reproduces the control algorithm, and two output pins Outport: out_LED_BUILTIN and Сhart. The first signal is linked as a variable in the Arduino sketch to the output pin (GPIO) number 13, which is also the control pin of the integrated LED. The second signal outputs the state of the block's internal counter Chart. Both signals are also used for logging in the model.

modelscreeen.JPG

Two output signals are used in the chart block: out, the initial value is "true" and cnt

State diagram

The state diagram (the contents of the block Chart) has 4 states:

  1. init - Initial state of the algorithm, the initial value of the counter is set when entering the state cnt = 0;.
  2. increment - The main state of the algorithm, here the counter value is compared with the transition conditions (transitions numbered 1, 2, 3) and the counter value is increased when entering the state cnt = cnt + 1;. Increase of the counter value by "1" corresponds in reality to its increase by 1 ms, as the algorithm calculation will take place after 1 ms, which will be defined further in the Arduino sketch code.
  3. ON - The condition where the counter is incremented if its value is less than 499 ms. When this condition is fulfilled, the output signal controlling the LED is set to "true".
  4. OFF - The condition that causes the counter to increment if its value is greater than or equal to 499 ms. When this condition is fulfilled, the output signal controlling the LED is set to "false".

When the counter reaches a value greater than or equal to 998 ms, the diagram enters the state init. The counter is limited to 998 ms due to the fact that it takes two more 2 ms cycles to calculate the init state, which does not directly control the LED. Thus, the total duration of the LED flicker period is 1000 ms.

image.png

Another important point to consider when developing the model is the order of execution of the transitions. This is the order in which the conditions of transition from the state in the conditional construct if(){} elseif(){} ... else{} of the generated C file will be prescribed.

For example, in this model, the period end condition [cnt >= 998] is checked first, although if its order was 3, then successful execution of the condition [cnt >= 499] would prevent it from being checked and the period counter would not reset. On the other hand, checking the end-of-period condition in each calculation cycle is not efficient, and this transition should be assigned an order of 3 and the transition condition of OFF should be changed to [(cnt >= 499) && (cnt < 998)]

Simulation results

Let's load the described model:

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);

From the obtained data of the model, plot the change in the value of the counter:

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

As can be seen, the counter value varies between 0 - 1000, with a periodicity of 1000 ms. Now plot the graph of the signal out_LED_BUILTIN, which controls the inbuilt LED of the Arduino.

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]:

We have obtained a periodic rectangular signal with a period of 1000 ms and a fill factor of 50%.

Execution of the algorithm on Arduino

To transfer the developed model to the target device, let's generate C code:

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"

Plug-in files have been generated in the specified directory. Also in the directory sketch_blink_chart_custom there is a pre-written Arduino sketch with the name of this directory sketch_blink_chart_custom.ino. In it, the header file obtained during code generation is connected, the periphery of the microcontroller is initialised, and functions for controlling the LED are called. A detailed description of the sketch is given in the comments of its code.

To execute the code on Arduino, you need to download the sketch_blink_chart_custom directory and load the sketch_blink_chart_custom.ino sketch from Arduino IDE into the target device. In our case, as stated earlier, it is Amperka's Iskra Neo.

After compilation of the sketch, a message about the success of the operation and the size of the output file is displayed:

compilation.JPG

Capturing signals from the Arduino board

After loading the code into the Arduino, you can observe a blinking LED on the debug board. For clarity in the description of the example, let's connect the measuring contact of the oscilloscope to pin 13 on the debug board and take an oscillogram.

firstoscillogramma.jpg

As can be seen from the captured oscillogram, a periodic rectangular signal with a fill time of 500 ms and a period of 1000 ms is formed on pin 13 of the debug board.

Conclusion

In the considered example, a model of digital output control for Arduino-compatible platforms was developed using the finite automata library Engee, and the principles of correct and efficient operation during code generation were described.

The code was generated from the developed model and uploaded to the target device. The result of program execution on the debug board fully corresponds to the results of modelling.

Blocks used in example