Monday, December 12, 2016

How to improve the packet reception rate of your sky nodes

Objective

The objective of this tutorial is to improve the packet reception rate of your sky nodes. For this tutorial, i am going to be using sky CM5000 nodes, Contiki V3.x and Lubuntu 16.04.

Problem

In this section i am going to describe the problem that i had with the CM5000 sky nodes. When i got my CM5000 nodes, the first thing that i wanted to test was sending a unicast message from node 2 to node 1. To that end, i used an example from the rime stack named example-unicast.c located in /home/YOUR_USER/Desktop/contiki/examples/rime. This example is very straightforward since it sends unicast messages from a node to node 1. However, when you run this example you have to make sure that a node within the network has address 1. In order to set one node with address 1, you can see the following tutorial:

http://contiki-iot.blogspot.com.co/2016/06/setting-node-id-for-sky-motes.html

The unicast rime example runs fine. You can see that the messages from node 2 to node 1 arrives. However, the problem is that a huge amount of messages are lost. You may wonder why. Why a huge amount of messages are lost in a simple unicast message sent from node 2 to node 1? What is the problem with the rime unicast example?

Solution to the problem

At first i thought that the wireless channel had a lot of interference. Then, i read in the book Internet of things in 5 days (link below) that wireless channels 15, 20, 25 and 26 do not overlap with WiFi. Besides, the default wireless channel used by Contiki rime is 26, hence, there should not be any interference problems. Additionally, i used the Spectrum Analizer Application available in Contiki, (which is explained in the link below) and i realized that there were no other transmissions in channel 26. In conclusion, the problem was not interference on the wireless channel. So, what was the problem? Why a huge amount of messages were lost when using the rime unicast example?

http://wireless.ictp.it/school_2015/book/#_ieee_802_15_4_channels_and_pan_id

After discarding wireless interference, i started reading about the Contiki stack (See link below). Then, i realized that there was a layer called Radio Duty Cycling which was in charge of turning the radio on and off to save energy.

http://anrg.usc.edu/contiki/index.php/Network_Stack

The default Radio Duty Cycling used by Contiki is called ContikiMAC. To understand the ContikiMAC, please go to the following link:

https://github.com/contiki-os/contiki/wiki/Radio-duty-cycling

After reading the above link, i understood that the receivers periodically turn on their radios to inspect for messages in the channel. So, the answer to my problem was: A lot of messages are lost in the rime unicast example because the receiver node (node 1) does not poll the radio medium with the appropriate frecuency. So, i increased the polling rate and no more messages were lost. In Contiki the polling rate is referred as RDC_CHANNEL_CHECK_RATE. It is important to notice that the RDC_CHANNEL_CHECK_RATE is proportional to the energy consumption of the nodes, i.e. if the node has a higher RDC_CHANNEL_CHECK_RATE, then it will consume more energy.

Implementation of the solution

Before you implement the solution, you must be aware that it will increase the energy consumption of the nodes.

In order to implement the solution all you have to do is to increase the RDC_CHANNEL_CHECK_RATE. In order to do so, you must first create a project configuration file project-conf.h (Please do the following tutorial) :

http://contiki-iot.blogspot.com.co/2016/07/project-configuration-example.html

In the above tutorial i created a project configuration file and changed the necessary stuff to make it work. Besides, in the above tutorial, i changed the radio channel from 26 to 20. But in this tutorial i want to change the RDC_CHANNEL_CHECK_RATE. To do so, just add the following line to your project-conf.h file.

#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 128 //Change the rate at which the node check for radio activity in the channel

The above line says that the node will turn the radio on 128 times per second to check whether there is a packet in the channel. The default RDC_CHANNEL_CHECK_RATE is 8. So, increasing the check frequency to 128 ensures that no packet is lost.

Verify the solution

To verify that the changes were made do this: 1) upload the unicast rime example to a sky node, 2) connect to it via a serial port, 3) the reboot the node manually. You can do the first 2 steps with this command line:

make clean && make TARGET=sky example-unicast.upload && make login

After manually rebooting the node, you should see this:

Rime started with address 2.0
MAC 02:00:00:00:00:00:00:00 Contiki 3.0 started. Node id is set to 2.
nullsec CSMA ContikiMAC, channel check rate 128 Hz, radio channel 20
Starting 'Example unicast'

This is the message shown by the node when it is rebooted. This message shows that the RDC_CHANNEL_CHECK_RATE is equal to 128: channel check rate 128 Hz . If you see that message then your problem is solved. You must not have any lost packets.

Friday, December 2, 2016

How to calculate the latency in Contiki OS

Objective

In this tutorial i am going to show you how to calculate the latency of a packet in a wireless link. I am using Contiki v3.x, sky (CM5000) nodes and lubuntu 16.04. First of all, to compute the latency of a packet you need to have the nodes synchronized. In order to synchronize the nodes of the network, you can use the Implicit Network Time Synchronization of Contiki, which i explain in the following tutorial:

http://contiki-iot.blogspot.com.co/2016/11/implicit-network-time-synchronization_28.html

It means that you must to do the above tutorial if you want to calculate the latency of a packet.

NOTE: Since the Implicit Network Time Synchronization mechanism of Contiki only works on sky nodes, this latency computation only works on sky nodes too.

Step 1: Synchronize your nodes

As mentioned above, you must have your nodes synchronized to calculate the latency of a packet. In order to synchronize your nodes, go to the following tutorial:

http://contiki-iot.blogspot.com.co/2016/11/implicit-network-time-synchronization_28.html

Step 2: Modify your example-broadcast.c

I am going to calculate the latency of a packet in the broadcast rime example. I got the basic idea from an example named shell-rime-debug.c which is located in /home/YOUR_USER/Desktop/contiki/apps/shell. So, you can go and check that file in order to get the information directly from a contiki source file.

Next, i am going to explain the changes that i made to the example-broadcast.c file:

  • Create a latency structure: We create a latency structure to save the timestamp of the message, i.e. the time when the message was sent.
  • Send a broadcast with the timestamp: The normal/original example-broadcast.c file sends a broadcast with a 'hello' message, in this tutorial, we are going to send a broadcast with the timestamp. So, we comment/delete the 'hello' message and add our timestamp to the broadcast.
  • Receive a broadcast with the timestamp and compute the latency: We receive the broadcast that includes the timestamp. Then, we compute the time difference between the current time (timesynch_time()) and the broadcast timestamp (msg.timestamp), that difference (timesynch_time() - msg.timestamp) is equal to the latency.

Now, we show you the full code:

/*
 * Copyright (c) 2007, Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Contiki operating system.
 *
 */

/**
 * \file
 *         Testing the broadcast layer in Rime
 * \author
 *         Adam Dunkels 
 */

#include "contiki.h"
#include "net/rime/rime.h"
#include "random.h"

#include "dev/button-sensor.h"

#include "dev/leds.h"

#include 


/*--------------------------------------*/

struct latency_structure{ // Structure to save the time when the message was send

   rtimer_clock_t timestamp;// Time when the message was send

};
/*---------------------------------------------------------------------------*/
PROCESS(example_broadcast_process, "Broadcast example");
AUTOSTART_PROCESSES(&example_broadcast_process);
/*---------------------------------------------------------------------------*/

//Receive a broadcast with the timestamp and compute the latency
static void
broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from)
{
  struct latency_structure msg;
  rtimer_clock_t latency;

  packetbuf_copyto( &msg ); // Copy the message from the packet buffer to the structure called msg

#if TIMESYNCH_CONF_ENABLED
  latency = timesynch_time() - msg.timestamp;
#else
  latency = 0;
#endif

  printf("broadcast message received from %d.%d with latency %lu ms\n",
         from->u8[0], from->u8[1], (1000L * latency) / RTIMER_ARCH_SECOND );
}
static const struct broadcast_callbacks broadcast_call = {broadcast_recv};
static struct broadcast_conn broadcast;
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(example_broadcast_process, ev, data)
{
  struct latency_structure *msg;

  static struct etimer et;

  PROCESS_EXITHANDLER(broadcast_close(&broadcast);)

  PROCESS_BEGIN();

  broadcast_open(&broadcast, 129, &broadcast_call);

  while(1) {

    /* Delay 2-4 seconds */
    etimer_set(&et, CLOCK_SECOND * 4 + random_rand() % (CLOCK_SECOND * 4));

    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));

#if TIMESYNCH_CONF_ENABLED
      msg->timestamp = timesynch_time();
#else
      msg->timestamp = 0;
#endif

    // Do not send the normal/original 'hello' message. Instead, send a message with the timestamp.
    packetbuf_copyfrom(msg,   sizeof(*msg) ); // This message msg includes the timestamp
    //packetbuf_copyfrom("Hello", 6);
    broadcast_send(&broadcast);
    printf("broadcast message sent\n");
  }

  PROCESS_END();
}
/*---------------------------------------------------------------------------*/


Step 3: Upload the code to 2 or more sky nodes

Since the Implicit Network Time Synchronization mechanism of Contiki only works on sky nodes, this latency computation only works on sky nodes. In order to upload the code to the sky nodes, do this:

make clean && make TARGET=sky example-broadcast.upload && make login

If everything is working correctly you should see a message like this:

broadcast message received from X.X with latency 1167 ms

When i tested the code the latency varies from 12ms to 1652 ms. Notice that X.X is the address of the node that sent the broadcast. In my example, the sky node has address 185.144