The Synchronous Blog

A blog about reactive programming languages.

Posts Tagged ‘arduino

[ANN] Céu in a Box

leave a comment »

Céu in a Box (CiB) is a distribution of Xubuntu 12.04 [1] that comes pre-installed with the Céu Programming Language environment [2].

The distribution contains the compiler together with bindings for the Arduino and TinyOS target platforms.

CiB is distributed as a single .ova file to be used wit VirtualBox [3].
[1]: http://xubuntu.org
[2]: http://www.ceu-lang.org
[3]: http://www.virtualbox.org

Advertisements

Written by francisco

July 9, 2012 at 11:54 am

Céu + Arduino

leave a comment »

A couple of months ago I acquired an Arduino Uno board [1] and started working on integrating it with Céu [2].

In this blog post, I depict a demo game that uses an LCD shield on the Arduino.

In the game, the player controls a “ship” that moves on screen and has to avoid collisions with meteors.

The video shows the game executing:

The game gets faster and more meteors appear on each phase. When the ship hits a meteor, the game restarts.

The code

The outermost loop of the game runs forever and restarts the game on every new phase or on “game over”:

    1: loop do
 2-12:     // CODE 1: set game attributes
   13:
   14:     _map_generate();
   15:     _redraw(step, ship, points);
   16:     await Key; // starting key
   17:
   18:     win =
19-45:         // CODE 2: the central loop
   46:
47-60:     // CODE 3: game over
   61: end

 

We split the remaining code in three blocks (to be expanded further):

  • CODE 1: sets (or resets) the game attributes, such as the ship position, speed, and game points
  • CODE 2: executes the main logic of the game, such as moving the ship and detecting collisions
  • CODE 3: executes the after game code, based on the result of “CODE 2” (win or !win)

Every time the outermost loop is executed (lines 1-61), it resets the game attributes (CODE 1, lines 2-12), generates a new map, and redraws it on screen (lines 14-15).
Then, it waits for a starting key (line 16), and executes the main logic of the game in the central loop (CODE 2, lines 18-45) until the ship reaches the finish line or collides with a meteor. Based on the return status (line 18), the “game over” code (CODE 3, lines 47-60) may display an animation before restarting the game.

The game attributes (CODE 1) change depending on the result of the previous iteration of the outermost loop:

     // CODE 1: set game attributes
 2:  ship = 0;        // 1st LCD row
 3:  if !win then
 4:      dt = 500;    // game speed (500ms/step)
 5:      step = 0;    // current step
 6:      points = 0;  // number of steps alive
 7:  else
 8:      step = 0;
 9:      if dt > 100 then
10:          dt = dt - 50;
11:      end
12:  end

 

For the first game execution and whenever the ship collides with a meteor, variable `win´ is set to 0 (we omitted global declarations), hence, the attributes are reset to their initial values (lines 4-6). Otherwise, if the player reached the finish line (win=1), then the game gets faster, keeping the current points (lines 8-11).

The central loop of the game (CODE 2) is responsible for moving the ship as time elapses and for checking whether the ship reached the finish line or collided with a meteor:

     // CODE 2: the central loop
19:  par do
20:     loop do
21:        await(dt)ms;
22:        step = step + 1;
23:        _redraw(step, ship, points);
24:
25:        if _MAP[ship][step] == '#' then
26:           return 0;  // a collision
27:        end
28:
29:        if step == _FINISH then
30:           return 1;  // finish line
31:        end
32:
33:        points = points + 1;
34:     end
35:  with
36:     loop do
37:        int key = await Key;
38:        if key == _KEY_UP then
39:           ship = 0;
40:        end
41:        if key == _KEY_DOWN then
42:           ship = 1;
43:        end
44:     end
45:  end;

 

The central loop is actually split in two other loops in parallel: one to run the game steps (lines 20-34), and the other to handle input from the player (lines 36-44).

The game steps run periodically, depending on the current speed of the game (line 21). For each loop iteration, the step is incremented and the screen is redrawn (lines 22-23).
Then, the ship is checked for collision with meteors (lines 25-27), and with the finish line (lines 29-31).
Céu supports returning from blocks with an assignment, hence, lines 26 and 30 escape the whole par and assign to the `win´ variable in the outer loop (line 18).
The points are incremented before each iteration of the loop (line 33).

To handle input events, we wait for key presses in a loop (line 37) and change the ship position accordingly (lines 39, 42).
Note that there are no possible race conditions on variable `ship´ because the two loops in the par statement react to different events (i.e. wall-clock time and keys).

After returning from the central loop, we run the code for the “game over” behavior, which executes an animation if the ship collided with a meteor:

     // CODE 3: game over
47:  par/or do
48:     await Key;
49:  with
50:     if !win then
51:        loop do
52:           await 100ms;
53:           _lcd.setCursor(0, ship);
54:           _lcd.write('');
58:        end
59:     end
60:  end

 

The animation loop (lines 51-58) continuously displays the ship in the two directions, suggesting that it has hit a meteor.
The animation is interrupted when the player presses a key (line 48), proceeding to the game restart.

Finally, we need to generate the key events to the program itself. As we use a third-party push-button component, the default Arduino binding does not provide event handling for it.
We place the whole program in parallel with the input key generator:

   0:  par do
1-61:     // CODE FOR THE GAME
  62:  with
  63:     int key = _KEY_NONE;
  64:     loop do
  65:        int read1 = _analog2key(_analogRead(0));
  66:        await 50ms;
  67:        int read2 = _analog2key(_analogRead(0));
  68:        if read1==read2 && key!=read1 then
  69:           key = read1;
  70:           if key != _KEY_NONE then
  71:              async do
  72:                 emit Key = read1;
  73:              end
  74:           end
  75:        end
  76:     end
  77:  end

 

The code samples data of an analog port with a delay of 50ms to avoid bouncing (lines 65-67).
If two consecutive reads point to the same key and they are different from the previous change (line 68), then we change the key (line 69) and generate a new event (in the case of a key press, lines 70-74).
The `async´ block is mandatory for generating input events to the program.

Conclusion

Arduino is an interesting target platform for Céu, given its memory constraints and lack of a high-level programming alternative.

The demo shows how complementary activities can be written in separate to run in parallel, reducing complexity.
The code does not become polluted with tons of globals for controlling state, easing the code maintenance.

The complete source code is around 170 lines and also includes all C definitions to generate the map, redraw the scene on the LCD, etc.

[1] http://arduino.cc/

[2] http://www.ceu-lang.org/

Written by francisco

July 8, 2012 at 10:25 pm

Posted in Examples

Tagged with , , ,

The case for synchronous concurrency

with 4 comments

The point of this post is to show that it is wrong to rely on timing issues in preemptive multithreading for activites that require a synchronized behavior. I compare the same program specification in three different implementations.

The example program is supposed to blink two leds with different frequencies (400ms and 1000ms) on an Arduino board. They must blink together every 2 seconds.

The first two implementations use different RTOSes with preemptive multithreading. The third implementation uses the synchronous language Céu.

(UPDATE) The complete source files can be found here.

 

The first implementation uses the ChibiOS RTOS. I omitted all code related to creating and starting the threads (which run with the same priority).

Follows the code and video for the implementation in ChibiOS:

static msg_t Thread1(void *arg) {
    while (TRUE) {
        digitalWrite(11, HIGH);
        chThdSleepMilliseconds(400);
        digitalWrite(11, LOW);
        chThdSleepMilliseconds(400);
    }
}
static msg_t Thread2(void *arg) {
    while (TRUE) {
        digitalWrite(12, HIGH);
        chThdSleepMilliseconds(1000);
        digitalWrite(12, LOW);
        chThdSleepMilliseconds(1000);
    }
}

You can see that around 1:00 the leds loose synchronism among them, and also with the metronome.

 

The second implementation uses the DuinOS RTOS. I also omitted all code related to creating and starting the threads (which run with the same priority).

In this example the leds were well synchronized, so I included another task that uses the serial port with a different frequency.

Follows the code and video for the implementation in DuinOS:

taskLoop (T1) {
    digitalWrite(11, HIGH);
    delay(400);
    digitalWrite(11, LOW);
    delay(400);
}

taskLoop (T2) {
    digitalWrite(12, HIGH);
    delay(1000);
    digitalWrite(12, LOW);
    delay(1000);
}

int c = 0;
taskLoop (T3) {
    delay(77);
    Serial.print(c++);
}

Since the beginning you can see that the leds loose synchronism among them, and also with the metronome.

 

The third implementation uses the synchronous language Céu.

In this example the leds were well synchronized, even with the third activity that uses the serial port.

Follows the code and video for the implementation in Céu:

par do
    loop do
        _digitalWrite(11, _HIGH);
        await 400ms;
        _digitalWrite(11, _LOW);
        await 400ms;
    end
with
    loop do
        _digitalWrite(12, _HIGH);
        await 1s;
        _digitalWrite(12, _LOW);
        await 1s;
    end
with
    int c = 0;
    loop do
        await 77ms;
        c = c + 1;
        _Serial.print(c);
    end
end

 

Conclusion:

The execution model of preemptive multithreading does not ensure implicit synchronization among threads.

There’s nothing wrong with the RTOSes and the example implementations: the behavior shown in the videos is perfectly valid.

The problem is that usually the very first examples for these systems use blinking leds (supposely synchronized) to show how easy is to write multithreaded code. This is not true!

Preemptive multithreading should not be used as is to write this kind of highly synchronized applications. Adding semaphores or other synchronization primitives to these codes won’t help alone, they require a single thread to handle timers that is responsible to dispatching others.

I used timers in the example, but any kind of high frequency input would also behave nondeterministically in multithreaded systems.

In synchronous languages like Céu, the execution model enforces that all activities are synchronized all the time.

Written by francisco

March 23, 2012 at 10:20 pm

Céu is born!

leave a comment »

Céu is a reactive language targeted at embedded systems, aiming to offer a higher-level and safer alternative to C.

Céu can be described as a reactive, imperative, concurrent, synchronous, and deterministic language.

Céu has a memory footprint of around 3Kb of ROM and 100b of RAM (on a 16bits platform).

Currently, Céu is restricted to static-only applications.

(See also the two previous blog posts.)

Website: http://ceu-lang.org (you can try Céu online!)

Git project: http://github.com/fsantanna/ceu

I’m looking for embedded systems developers interested in using Céu.

I can help with all support (i.e. coding) to integrate Céu with your platform.

The distribution of Céu already provides support for Arduino:

http://www.ceu-lang.org/wiki/index.php?title=Arduino

*** UPDATE (1): Looks like dreamhost (where ceu-lang is hosted) is in trouble.

*** UPDATE (2): Dreamhost is up again!

Written by francisco

January 30, 2012 at 3:10 am