Welcome to the modern embedded systems programming channel.
My name is Miro Samek, and in this
video I will show you how to program Arduino
the modern way with the graphical modeling
tool called QM.
To get started, point your browser to state-machine.com/arduino
and scroll down. You will need two pieces
of software to get started and both of them
are available from SourceForge.net open source
repository.
First you need to download the QP Development
Kit for Arduino. Click on the SourceForge
logo and choose the latest version. Click
on the ZIP file to download it.
You also need the free QM graphical modeling
tool. From state-machine.com, click on the
SourceForge logo and choose the latest version.
QM installers are available for Windows, Linux,
and Mac hosts. Here I choose the QM installer
for Windows.
Before installing the downloaded files, make
sure that you have downloaded and unzipped
the standard Arduino sofware on your machine.
Open the qp_arduino ZIP file and extract it
into the directory, in which you have installed
the standard Arduino software.
In the process of extracting the files, confirm
that you want to merge the folders libraries
and tools.
You might want to check that the arduino libraries
folder now contains the qp library and that
the arduino tools folder contains qtools.
Installing the free QM modeling tool is also
very easy. You simply open the downloaded
QM installer and run it.
Accept the simple End User License Agreement
and choose installation folder. The default
location works just fine, but I like to install
all my tools into C:\tools folder. The ReadMe
file shown at the end of the installation
provides some basic information about QM.
The first example I'd like to show you is
the very simple blinky project, which simply
blinks the LED on the Arduino UNO board once
a second. This example is included in the
QP library, which you copied to the Arduino
libraries directory.
To open the blinky example, launch the QM
tool using the desktop shortcut, and open
the blinky QM model in the Arduino libraries
directory. Alternatively, you can first find
the blinky project in the file explorer and
double-click on the blinky.qm model to open
it in QM.
Before I explain how the Blinky project works
in QM, let me open a very similar Blink example
provided in the standard Arduino software.
That way, you can compare the traditional
and the graphical approaches side by side.
The Arduino Blink code is purely sequential.
The loop function starts with turning the
LED on. Next, it waits in-line for a 1000
milliseconds; turns the LED off, and waits
for another 1000 milliseconds. The code uses
100% of the CPU cycles, mostly to wait between
changing the LED state.
Although this approach is functional for small
projects like the Blink, it doesn't work very
well when there are multiple possible sources
of events whose arrival times and order you
cannot predict and where it is important to
handle the events in a timely manner.
The fundamental problem is that while a sequential
program is waiting for one kind of event (e.g.,
a time delay), it is not doing any other work
and is not responsive to
other events (e.g., a button press).
Another big problem with the sequential program
structure is wastefulness in terms of power
dissipation. Regardless of how much or how
little actual work is being done, the Arduino
processor is always running at top speed,
which drains the battery quickly and prevents
you from making truly long-lasting battery-powered
devices.
The QM modeling tool offers a different approach
called event-driven programming, which requires
a distinctly different way of thinking than
conventional sequential programming. In an
event-driven system, your code is called only
to handle events and returns quickly, without
ever wasting CPU cycles to wait for events
in-line. The waiting for all possible events
is centralized in an event-driven infrastructure,
also known as a framework, which can easily
handle thousands of events per second. This
arrangement allows the system to remain extensible
and responsive to events.
Events are handled in QM in state machines,
which are a very clever mechanism to make
event handling dependent both on the event
type and the current state or mode of the
system.
For example, the state machine for the Blinky
project handles the single TIMEOUT event in
two states off and on.
When the TIMEOUT event arrives in the off
state, the state machine transitions to the
ON state and turns the LED on in the entry
action to ON.
However, if the TIMEOUT event arrives in the
ON state, the state machine transitions to
OFF and turns the LED off in the entry action.
So, as you can see, the single TIMEOUT event
is handled differently, depending on the current
state of the system.
Every state machine has also a special initial
transition, which is taken once at the very
beginning. In this initial transition the
Blinky state machine requests the TIMEOUT
event to arrive every half second, so that
the LED can stay on for a half second and
off for another half. Of course you can very
easily change the timing to whatever you like.
The QM tool turns the state machine just described
into code by generating the blinky.ino file.
This file is defined as part of the model
and contains both hand-written code and generated
code.
In the hand-written part of the code you must
include the standard Arduino.h header file.
To generate code you use special directives.
$declare generates the declaration of the
Blinky state machine,
while $define directive generates the definition,
that is the code for the Blinky state machine.
Just as in any other Arduino sketch, you define
the setup function, in which you start the
Blinky object.
However, you don't define the loop() function,
because loop is already defined in the QP
framework, which runs your application.
In this version of QM, you can very conveniently
build and upload the code to your Arduino
board directly from QM, without the Arduino
IDE. All the tools are already pre-configured
for Arduino. You only need to adjust the location
of the standard Arduino software on your machine.
Open the Manage Exteranal Tools dialog box
and adjust the environment variable ARDUINO_HOME,
which contains the full path to the standard
Arduino software. Here, I just copy and paste
the path from the Windows Explorer.
To build your code, click on the "make" button.
The first time build takes a bit longer, because
you build all the libraries used in your code,
such as the Arduino library, the QP library,
etc.
To upload your code to the Arduino board,
click on the upload button. The program runs
as soon as the upload completes. Note that
the LED starts blinking about once per second.
Let's now change the code a bit and go through
the build-download cycle again. For example,
let's increase the TIMEOUT frequency to four
times per second. Rebuild and notice how fast
the code builds this time. Upload the code
again and watch the LED blink about twice
per second.
The next QP project I'd like to demonstrate
is the Pedestrian Light Controlled (PELICAN)
crossing. This slightly more interesting example
shows the benefits of event-driven state machines
and modeling a little more convincingly than
the primitive Blinky project.
Let me very quickly summarize the operation
of a PELICAN crossing. A pedestrian approaches
a crossing an presses a button. After a while,
the cars get the yellow light and then red
light and the pedestrian gets the walk signal,
which after a while changes to blinking DON't
WALK signal. Finally, the DON't WALK signal
stops blinking and cars get green light and
the cycle repeats, although cars always get
guaranteed several seconds of green light,
even if the button is pressed immediately.
The behavior that I've just described is modeled
in the PELICAN state machine. I won't go into
the details here, because they are described
in the Application Note included in the doc
directory, but I only want to mention that
this is an advanced hierarchical state machine.
The main advantage here is that states can
nest in one another and by doing so a nested
state inherits transitions from the surrounding
states. This allows you to avoid repeating
common transitions and so it counteracts the
phenomenon known as "transition explosion"
that plagues the classical non-hierarchical
state machines.
You build the PELICAN example exactly as the
Blinky sketch. Don't forget to adjust the
ARDUINO_HOME variable for your system.
Just as before, the first time build takes
a little longer, but all the subsequent builds
are very fast.
You already know how to upload the PELICAN
code to your Arduino board by means of the
upload tool. However, to run the code, you
need to launch an external serial terminal.
You can do this from QM by clicking on the
tool button labeled TeraTerm. TeraTerm is
an external serial terminal program that you
can download from the Internet. Most likely
you will need to adjust the settings for this
external tool in the Manage External Tools
dialog box. But I hope that by now you get
an idea how to do this.
To trigger the button press event for the
PELICAN crossing, type p into the serial terminal.
After this, your terminal should show the
changes of the signals for cars and pedestrians.
Finally, the last example included in the
QP Development Kit for Arduino is the classical
Dining Philosophers Problem. This example
demonstrates multiple state machines cooperating
together and also shows how to run your application
under the preemptive kernel called QK. A preemptive
kernel requires a bit more stack space, but
allows you to execute the highest-priority
state machines very timely, with time accuracy
of microseconds, regardless of the event processing
time of lower-priority state machines.
You build the DPP-QK example in the same way
as before. I just wanted to point your attention
to the QK_PREEMPTIVE argument of the arduinomake
script. This argument configures the QP library
to use the preemptive QK kernel instead of
the default cooperative kernel.
After uploading the code to the Arduino board,
you also need to launch the serial terminal
to watch the output.
So now, you are ready to create your own projects.
The simplest way to get started is to open
one of the provided examples and click the
File->Save As menu to save it to a directory
of your choice and modify it. That way your
project will inherit all the settings and
external tools.
This concludes this quick introduction to
event-driven programming and modeling for
Arduino. To learn more, please refer to the
Application Note "Event-Driven Programming
for Arduino", which is included in the doc
directory of the QP Development Kit.
