IoT: attached instructions
15LLP108_Demo4_LedBlinking.pdf
1. Introduction
In Demo3, we have learned how to read sensor values of light, temperature and humidity of a node
and output these values to the console. In this demonstration, we will use the code from Demo3 and
learn how to turn on/off the LEDs and make them blinking regularly on the sensor node XM1000,
meanwhile to count how many times the LED has blinked and output the count to the console.
2. Timer In order to make the blue LED on the XM1000 sensor node to blink in every half second (i.e. On 0.5S and Off 0.5S), we also need a timer. Follow the instructions in Demo3 for configure and reset a timer.
We aslo need to create an infinite while() loop so that it runs our functions repeatedly, such as
counting the times the LED has blinked, output the counter’s value and actually turn on or off the
LEDs to make it blinking.
Please follow timer and while() loop structure in Demo3.
3. LED Blinking
To get access to the LED functionalities in Contiki, we need to include the LED header file in the
source code:
#include "leds.h" // file is in directory /home/user/contiki/core/dev
After the process begin, we have to initialise the LEDs on the sensor node by calling the following
function:
leds_init(); // Initialise the LEDs
And finally we can turn on, off, or blink the LEDs by the following functions:
void leds_on(unsigned char leds);
void leds_off(unsigned char leds);
void leds_toggle(unsigned char leds);
void leds_invert(unsigned char leds);
For example, if you want to blink the Blue LED, yon need to call the toggle function as:
void leds_toggle(LEDS_BLUE); // Toggle the blue LED
4. Exercise
Modify the program from Demo3 with periodic timer to make the BLUE led blinking in every half
second, also to count the blinking times and output the counted number to the console.
Can your change the code so that the BLUE LED is lighted for 1 second and off for 0.5 second
periodically?
15LLP108 – Internet of Things and Applications
Lab Session 2: Demo 4 – LED Blinking
Prepared by Xiyu Shi
5. Source code
Here is the source code for reference
#include "contiki.h"
#include "leds.h"
#include <stdio.h> /* for printf() */
static struct etimer timer;
/*____________________________________________________*/
PROCESS(led_blinking_process, "LED Blinking Process");
PROCESS(LED_process, "LED process");
AUTOSTART_PROCESSES(&LED_process);
/*____________________________________________________*/
PROCESS_THREAD(LED_process, ev, data)
{
static int count = 0;
PROCESS_BEGIN();
etimer_set(&timer, CLOCK_CONF_SECOND/2); // 0.5S timer
leds_init(); // intialise the LEDs
while(1) {
PROCESS_WAIT_EVENT_UNTIL(ev==PROCESS_EVENT_TIMER); // wait for timer event
count++; // count the blinking times
process_start(&led_blinking_process, NULL); // to blink the BLUE Led
printf("Count: %d\n", count); // output the counter number to console
etimer_reset(&timer); // reset the timer
}
PROCESS_END();
}
/*____________________________________________________*/
PROCESS_THREAD(led_blinking_process, ev, data)
{
PROCESS_BEGIN();
leds_toggle(LEDS_BLUE); // Blinking the Blue LED
PROCESS_END();
}
15LLP108_Demo2_HelloWorld_CodeExample.pdf
1. Introduction
In this Demonstration, we are going to code and run our first application on the XM1000 sensor
node. As in any programming language, we start our demonstration with a “Hello World” program
on a sensor node that displays Hello World on the console. We have the following goals for this
demonstration:
Code and understand Contiki programming in C
Compile and deploy code on a sensor node
Connect the sensor node to output console for information display
2. Hello World! Code Example
Figure 1 Source code of hello-world.c
Here we give a description of the example code line by line:
15LLP108 – Internet of Things and Applications
Lab Session 1: Demo 2 – Hello World!
Prepared by Xiyu Shi
Line 1: the Contiki header file, contiki.h, is included. This will include the Contiki OS into the compile
program and allow to access the scheduling and abstraction of APIs of Contiki. Contiki follows the
Protothreads concurrent programming model with a low-overhead.
Line 3: includes the standard input/output library needed to write to the standard output.
Line 7: defines the processes to be executed and included during runtime. In this case we include only one process; the hello_world_process. It is possible and usually the case to define several concurrent processes, one for processing and collecting data, one for transmitting or receiving data. Line 8: define which process to start when the sensor node is started up (i.e. power on or reset) Line 11: start the definition of a process called “hellow_world_process”. Line 12 and 18: all codes of a process must be enclosed within a pair of bracket. Line 13: declare the beginning of the process Line 17: declare the end of the process Line 15: is where the node really does what I want it to do, to output “Hello World” to the console via the printf() function. Most of the Contiki functions rely on standard-C. 3. The Makefile In Linux-alike OS, we need “Makefile” to tell the OS how to compile the program for a specific platform or hardware/software configuration. Contiki relies on two Makefiles to for compilation: the file “Makefile.target” (Fig. 2) defines the platform the code has to be compiled for, and the file “Makefile” (Fig. 3) tells the compiler where the Contiki header files can be found.
Figure 2 Makefile.target
Figure 3 Makefile
4. Exercise by Compiling and Running on the Sensor Node Create the c source file and the two Makefiles in fold “/home/user/contiki/examples/demo1” and run the following commands:
make TARGET=xm1000 savetarget
make
make hello-world.upload
make login
Or simple follow the instructions in document “15LLP108-Demo1_HelloWorld_HowToCompile”. Bonus: Extend your code to print some random numbers between 0 and 1.
15LLP108_Demo1_HelloWorld_HowToCompile.pdf
In this Demonstration, we will learn how to compile, upload and run a simple node application on
the Contiki platform.
1. Enter the example code subdirectory
Open a Linux terminal window to run commands.
cd contiki/example/hello-world
2. Compile the hello-world project
make TARGET=xm1000 savetarget
make // this will take several seconds
3. Connect the Node to your PC/Laptop
a. Connect the XM1000 mote node to one of the USB socket on the PC or laptop. Wait for the
completion of software/drivers for the node on Windows.
b. A popup window is displayed on the WMware Player to tell you how to install the device
node on the virtual machine. Follow the advice:
c. On the top-left WMware Player windows menu list, clicking “Player”->”Removable Devices”-
>”Future Devices MTM-XM1000MSP”->”Connect”
d. A window message is poped up, click “OK”
4. Upload to the node
Get into hello-world project directory and running the following command:
make hello-world.upload
If error happened, such as “could not open port /dev/ttyUSB0: [Errno 13] Permission denied:
'/dev/ttyUSB0'”, it means that the node device is not in “write” mode. Changing the write
permission by running: “sudo chmod 777 /dev/ttyUSB0”, when promoted a password, input “user”.
Now run the upload to programming the node device again by “make hello-world.upload”. The
program code will be programmed to the xm1000 node device. You will notice that the red and
green LEDs are flashing during the programming.
5. Run the application
a. Once the application is uploaded to the node, login to the console of the connected sensor
node:
make login
15LLP108 – Internet of Things and Applications
Lab Session 1: Demo 1 – How to Compile an Application on Contiki
Prepared by Xiyu Shi
The console will display the following message:
using saved target 'xm1000'
../../tools/sky/serialdump-linux -b115200 /dev/ttyUSB0
connecting to /dev/ttyUSB0 (115200) [OK]
b. Now pressing the Red button on the sensor device and see the output of the console. It will
show something like this:
Rime started with address 43.84
MAC 2b:54:00:00:00:00:00:00 Contiki-2.6 started. Node id is not set.
CSMA ContikiMAC, channel check rate 8 Hz, radio channel 26
Starting 'Hello world process'
Hello, world
Notice that the last line printed on the console, which is what the device is programmed to do.
15LLP108_Demo5_MultiThreading.pdf
1. Introduction
The aim of this demonstration is to show how multi-threads can be implemented for complex tasks.
You will develop a temperature indicator, which is able to measure the temperature 4 times every
second, to average them and to print the average temperature through another thread process.
You need to have two threads in the application, a measurement thread and a print thread. The
main thread is used to measure the temperature four times in a second, then to average the four
measurements and pass the value to the print process thread.
2. Passing data from one process thread to another In order to pass data from one process thread to another you have to:
a. Remember every process thread is defined as: PROCESS_THREAD(A_process, ev, data)
where the argument “ev” is the event that passed to this thread from its parent thread and the “data” argument is the data that passed to this thread from its parent thread.
b. Initialise the storage event_data_ready = process_alloc_event();
c. Post the measurement data to another thread called print_process: Process_post(&print_process, event_data_ready, &measurement);
d. In another thread (in this case it is print_process), wait for event to occur: PROCESS_WAIT_EVENT_UNTIL(ev == event_data_ready);
e. And get data from the process thread input argument "data". The application structure is shown in Figure 1, in next page.
3. Exercise
To read the temperature, you may need to look at Demo3 again and use the following function:
sht11_sensor.value(SHT11_SENSOR_TEMP);
You need also to include the relevant header files in your code.
15LLP108 – Internet of Things and Applications
Lab Session 3: Demo 5 – Multi-threading
Prepared by Xiyu Shi
Figure 1 Multi-threads program structure
4. Source code
Here is the source code for reference
#include "contiki.h" #include <stdio.h> /* For printf() */ /* Include temperature sensor driver */ #include "dev/sht11-sensor.h" /* Number of values used in averaging process */ #define MAX_VALUES 4 /* Variables: the application specific event value */ static process_event_t event_data_ready; /* digits before decimal point */ unsigned short d1(float f) { return((unsigned short)f); } /* digits after decimal point */ unsigned short d2(float f) { return(1000*(f-d1(f))); } /*---------------------------------------------------------------------------*/ /* Declare the two processes */ PROCESS(temp_process, "Temperature process"); PROCESS(print_process, "Print process"); /* the temperature measurement processes is started automatically at beginning */ AUTOSTART_PROCESSES(&temp_process, &print_process); /*---------------------------------------------------------------------------*/ /* Implementation of the first process thread, the temperature measurement*/ PROCESS_THREAD(temp_process, ev, data) { /* Variables are declared static to ensure their values are kept */ /* between kernel calls. */ static struct etimer timer; static int count = 0; static float average = 0, valid_measure = 0; /* This variable is recomputed at every run, therefore it is not */ /* necessary to declare them static. */ float measure; /* Any process must start with this. */ PROCESS_BEGIN(); /* Allocate the required event */ event_data_ready = process_alloc_event(); /* Initialise the temperature sensor */ SENSORS_ACTIVATE(sht11_sensor); /* Initialise variables */ count = 0; average = 0;
valid_measure = 0; measure = 0; /* Set the etimer module to generate an event in 0.25 second. */ etimer_set(&timer, CLOCK_CONF_SECOND/4); while (1) { /* Wait here for the timer to expire */ PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER); /* Get temperature measurement and convert it to degrees */ measure = 0.01 * sht11_sensor.value(SHT11_SENSOR_TEMP) - 39.6; /* Sum temperature measurements */ average += measure; /* Count how many temperature measurement we have summed up */ count++; if (count == MAX_VALUES) { /* Average the sum and store */ valid_measure = average / MAX_VALUES; /* Reset variables */ average = 0; count = 0; /* Post an event to the print process */ /* and pass a pointer to the last measure as data */ process_post(&print_process, event_data_ready, &valid_measure); }
/* Reset the timer so it will generate another event */ etimer_reset(&timer); } /* Any process must end with this, even if it is never reached. */ PROCESS_END(); } /*---------------------------------------------------------------------------*/ /* Implementation of the second process, the print temperature thread */ PROCESS_THREAD(print_process, ev, data) { PROCESS_BEGIN(); while (1) { /* Wait until we get a data_ready event */ PROCESS_WAIT_EVENT_UNTIL(ev == event_data_ready); /* Use 'data' variable to retrieve data and then display it */ printf("temperature = %u.%u\n", d1(*(float *)data), d2(*(float *)data)); } PROCESS_END(); } /*---------------------------------------------------------------------------*/