In this tutorial, you will implement the very same (simple) behaviour, at different levels of abstraction. This journey through abstraction levels will help you to identify the pros and cons of each level, and the importance of model-driven engineering and domain-specific languages to reason about domains.

An “hands on” version of this tutorial uses an Arduino Board as IoT platform. If you do not have the appropriate hardware, it is possible to rely on classical simulators such as SimulIDE.


The tutorial will guide you through the realization of a simple application, defined at several levels of abstraction. The application is divided into two parts:

  • Switch the light on!: An LED is connected to a push-button. When pressing the button, the LED is switched off. Pressing it again, and the LED is switched on again. Rinse and repeat. 
  • Count to 9!: A 7-segment display is used to display digits from 0 to 9, and then back to 0. The display period is one second. When the push-button is pressed, the counter is reset to 0.

Then, it will be your responsibility to compose the two applications together, considering that the physical push-button is shared between the two applications.


This is an example of the expected behaviour of the application:

  1. Tick #1 to #10: At the beginning, the LED is switched on, and the counter starts at 0 and counts to 9
  2. Tick #11: It automatically goes back to 0 
  3. Tick #14: the user presses the button. The counter goes back to 0, and the LED is now switched off.
  4. Tick #17: the user presses the button again. The counter goes back to 0, and the LED is now switched on.
  5. Tick #18: the user presses the button again. The counter stays at 0, and the LED is now switched off.

Start here:

Using a simulator and containerized environment

(Optional) Setting up the hardware

(Optional) Setting up the software

Accessing the kickstart code