TinyOS

This page is about running the Céu programming language in the TinyOS platform.

Installation
You can either download a virtual machine preloaded with Céu, or install it manually from the git repository:


 * Céu in a Box virtual machine
 * TinyOS Manually

Examples
The distribution comes with some samples ready for playing with Céu.

After the installation, open a terminal window and cd to the TinyOS/nesC directory:

$ cd ceu-tinyos/

Blinking LEDs
The first example, blink.ceu, mimics the exact behavior of the Blink application on the TinyOS Tutorial:

par do                           // a parallel statement // 1st trail loop do                      // an infinite loop that: await 250ms;             //   - awaits 250ms _Leds_led0Toggle;      //   - toggles the led end                          //   - repeats with // 2nd trail loop do           await 500ms; _Leds_led1Toggle; end with // 3rd trail loop do           await 1000ms; _Leds_led2Toggle; end end

To compile and upload it to your board, run the following command:

$ make CEUFILE=samples/blink.ceu micaz install mib520,/dev/ttyUSB0

You should see the leds blinking, just like in the video on the right.

The program runs three loops in parallel, each blinks a led with a different frequency.

C symbols like Leds_led0Toggle must be preceded with an underscore.

The await primitive suspends the running line of execution (a trail in Céu) until the referred event occurs (e.g. 500ms).

With multiple trails, it is possible to wait for multiple events at the same time, as the example illustrates.

Sensing
The second example, sense.ceu, requires a light sensor connected to the mote.

$ make CEUFILE=samples/sense.ceu micaz install mib520,/dev/ttyUSB0

This example is derived from the Sense application on the TinyOS Tutorial:

input int Photo_readDone;               // input event from TinyOS int data; loop do       await 100ms; _Photo_read;                      // requests sensor read data = await Photo_readDone;        // awaits the response with the value _Leds_set(data/100); end

The program is an infinite loop that reads the light sensor every 100ms. On each iteration, the application requests the _Photo_read operation to read the sensor, then awaits the response, and lights on the corresponding leds.

There's no need for callbacks in Céu, the request/await pattern greatly simplifies the programming effort. Moreover, it still reflects the underlying Split-Phase mechanism of TinyOS that avoids blocking the operating system, that is, other parts of the program (in parallel) remain alive and reactive.

Communicating via radio
The third example, radio_echo.ceu, illustrates the use of the radio for communication among motes.

$ make CEUFILE=samples/radio_echo.ceu micaz install mib520,/dev/ttyUSB0      # repeat for another mote

Each time a mote receives a message, it shows the received value on the LEDs (a simple counter incremented after each send). The video on the right shows the expected behavior for the program running in two motes.

First, we need to define which events are used in the program, and also the struct</tt> for the radio message:

input int                 RADIO_STARTDONE; input (_message_t*, int)  RADIO_SENDDONE; input (_message_t*, int)  RADIO_RECEIVE; output (_message_t*, int*) RADIO_SEND; native do       typedef struct { nx_uint16_t cnt;             // a simple 16 bits counter } Msg ; end

The native do .. end</tt> block allows the definition of C structs and functions from within Céu.

The next step is to initialize the radio for communication. If you are not familiar with radio communication under TinyOS, see the mote to mote communication tutorial.

// loop to retry until the initialization is successful loop do       var int err = _Radio_start;     // requests `Radio_start' if err == _SUCCESS then err = await RADIO_STARTDONE; // awaits the confirmation if err == _SUCCESS then break;                   // everything is ok, escapes the loop end end await 1s;                        // waits 1 second before retrying end

In sequence with the radio initialization, we proceed to use the radio with two activities in parallel: one that receives the messages and show them on the LEDs, and another that sends the counter every 2 seconds:

par do       /* Receive activity */ loop do           var _message_t* pkt_rcv; var u8 len; (pkt_rcv, len) = await RADIO_RECEIVE;                      // waits for the next message var _Msg* msg_rcv = _Radio_getPayload(pkt_rcv,0);          // gets a pointer to the message payload _Leds_set(msg_rcv:cnt);                                    // shows the received end with /* Send activity */ var _message_t pkt_snd;                                        // buffer to send messages var _Msg* msg_snd = _Radio_getPayload(&pkt_snd, sizeof(_Msg)); // gets a pointer to the message payload msg_snd:cnt = 0;                                               // sets the initial value for the counter loop do           await 2s; _Radio_setDestination(&pkt_snd, _AM_BROADCAST_ADDR);       // sends the message via broadcast _Radio_setPayloadLength(&pkt_snd, sizeof(_Msg)); emit RADIO_SEND => (&pkt_snd,null); msg_snd->cnt = msg_snd->cnt + 1;                           // increments the counter for the next send end end

For the sake of simplicity, we did not test the return status of RADIO_SEND</tt>.

Ring communication
For a more complete example, check the following blog post:


 * http://thesynchronousblog.wordpress.com/2012/07/04/ceu-wireless-sensor-networks/

<!--

Simulation
Simulation is an essential requirement for WSNs, as the following list justifies:


 * does not require to deploy applications on the motes every time
 * makes debugging is easier (e.g. printf</tt>)
 * makes possible to test large networks without actually having enough motes

Céu provides an alternative simulation method that uses Lua for describing networks.

Note: simulation with TOSSIM is still available and should work as usual.

In the following example, we define a star network, where the central node receives counter messages from its neighbors.



Go to the simulation directory and edit file star.lua</tt>:

$ cd simul/     # working dir is "~/ceu/nesc/" $ leafpad star.lua

We start by defining the server node:

srv = simul.app { name = 'server',                -- name for debug messages defines = {                     -- table for C definitions: TOS_NODE_ID = 10,           --     node id        }, source =                      -- source code enclosed by `[ [´ and `] ]´    input  int         Radio_startDone;    input  _message_t* Radio_receive;    output _message_t* Radio_send;    C do        typedef struct {            nx_uint16_t cnt;        } Msg ;    end    _Radio_start;    await Radio_startDone;    loop do        _message_t* pkt_recv = await Radio_receive;        _Msg* msg_recv = _Radio_getPayload(pkt_recv,0);        _DBG("received %d from %d\n", msg_recv->cnt, _Radio_getSource(pkt_recv));    end }

The variable srv</tt> holds the table describing the server application. The source code is a loop that continuously receives radio messages and show the value and source node. The DBG</tt> function behaves similar to TOSSIM's dbg</tt>.

Note: it is also possible to define the source code in a separate file.

Then, we create five clients to interact with the server:

local clts = {}                       -- table to hold the clients local N = 5 clt_source =                        -- same source for all clients    input  int         Radio_startDone;    input  _message_t* Radio_receive;    output _message_t* Radio_send;    C do        typedef struct {            nx_uint16_t cnt;        } Msg ;        end    _Radio_start;    await Radio_startDone;    _message_t pkt_send;    _Radio_setSource(&pkt_send, _TOS_NODE_ID);          // client address    _Radio_setDestination(&pkt_send, 10);               // server address    _Radio_setPayloadLength(&pkt_send, sizeof<_Msg>);    _Msg* msg_send = _Radio_getPayload(&pkt_send, sizeof<_Msg>);    msg_send->cnt = 1;    loop do        await 2s;        emit Radio_send(&pkt_send);        msg_send->cnt = msg_send->cnt + 1;    end for i=1, N do                         -- create five clients clts[i] = simul.app { name = 'client '..i,           defines = { TOS_NODE_ID  = 50+i, TOS_COLLISION = 30+i*10,  -- % of packet loss },           source = clt_source, }   end

The variable clts</tt> is a table that holds the five clients. We use the same source code for the clients. The for</tt> create the five clients, each with a different id (51-55) and a different percentage of packet loss (40%-80%).

Finally we define the topology and initiate the simulation:

simul.topology { [srv] = { clts[1], clts[2], clts[3], clts[4], clts[5] }, [clts[1]] = { }, [clts[2]] = { srv }, [clts[3]] = { srv }, [clts[4]] = { srv }, [clts[5]] = { srv }, }   simul.shell

The server is in the range of all clients, and each client is only in the range of the server. Note that the connection from clts[1]</tt> to the server is broken (regardless of its packet loss).

The call to simul.shell</tt> starts the simulation and listen for commands to start/kill nodes and create/destroy link between nodes.

To run the simulation file, run it with lua</tt>:

lua star.lua    # working dir is "~/ceu/nesc/simul"

The video on the right shows the simulation running.

The following list summarizes the supported features in simulation with Céu:


 * different source files for nodes
 * adjustment of the topology during simulation
 * simulation of input events (e.g. sensor reads)
 * simple pseudo-random collision of packets
 * respects timings

[download] The current version of Céu for TinyOS.

The Céu compiler requires Lua and LPeg installed.

We assume you are using a Linux-like programming environment.

After downloading Céu for TinyOS, unpack it, adjust the Makefile</tt>, and run make</tt> for your mote:

$ tar xvzf ceu_nesc_*.tgz $ cd ceu_nesc_* $ vi Makefile $ make micaz install mib520,/dev/ttyUSB0

You should see the LEDs blinking, just like in the video on the right.

By default, Céu compiles the file samples/blink.ceu</tt>, as defined in the Makefile. However, it's possible to pass a different file to <tt>make</tt>:

$ make CEUFILE=samples/sense.ceu micaz

The sending process is very similar to the radio initialization.

C Binding
Céu requires a master application that binds the TinyOS operating system with the language and is responsible for issuing events to the program. For instance, the previous example uses the input event <tt>Photo_readDone</tt> to communicate with the TinyOS platform.

Fortunately, the distribution of Céu for TinyOS already provides a default binding ready for use. Follows a simplified version of its nesC module file:

implementation {       /* Initialization */ event void Boot.booted { ceu_go_init(NULL, call Timer.getNow);            // initializes Céu call Timer.startPeriodic(10);                      // starts a periodic Timer to feed Céu }       event void Timer.fired  { ceu_go_time(NULL, call Timer.getNow);            // feeds Céu with the "wall clock" }       /* Input Events */ event void Photo.readDone(error_t err, uint16_t val) { int v = val; ceu_go_event(NULL, IO_Photo_readDone, &v); }       ...        /* Request Operations */ int Photo_read { return call Photo.read; }       ...    }

The input events of Céu map to nesC's events. Note that nesC's commands need to be packed into functions to overcome the <tt>call</tt> syntax.

Céu represents input events with <tt>IO_*</tt> constants (i.e. <tt>IO_Photo_readDone</tt>), which are passed to <tt>ceu_go_event</tt> along with the actual event value.

All TinyOS events above run synchronously (i.e. they are never interrupted), but extra care must be taken for asynchronous events (see Concurrency in TinyOS).

What's next?

 * Examples in the <tt>samples/</tt> directory.
 * Tutorial on Céu.

Did you like Céu? Would you like to use it? Please, let me know, I can help you!

http://www.lua.inf.puc-rio.br/~francisco -->