Objective
In this tutorial, i am going to show you how to use the Implicit Network Time Synchronization of Contiki OS in real nodes. I am using the sky motes CM5000, Contiki OS v3.x and Lubuntu v16.04. It is important to notice that this synchronization mechanism only works in sky nodes.
Background
The Implicit Network Time Synchronization is implemented in Contiki via 2 files: timesynch.c and timesynch.h
/home/YOUR_USER/Desktop/contiki/core/net/rime/timesynch.c /home/YOUR_USER/Desktop/contiki/core/net/rime/timesynch.h
If you want to get a deep understanding of the synchronization mechanism, please read the following 2 references:
http://anrg.usc.edu/contiki/images/f/fd/Time_Synchronization.pdf
http://dunkels.com/adam/chen07time.pdf
The first link is a presentation that explains the synchronization mechanism very clearly, and the second link is a paper of Adam Dunkels (The author of the timesynch.c.h files). Now, i am going to explain in my own words the synchronization mechanism.
Synchronization Mechanism in my own words
How the CM5000 sky mote counts the time? To count time the CM5000 sky node has a 16-bit timer (TIMER_A) capable of counting from 0 to 65535. In every clock tick the counter is incremented in 1. Besides, when the TIMER_A is equal to 32768, then 1 second has passed. And when the TIMER_A is equal to 65536, then 2 seconds has passed. Notices, than when TIMER_A = 65536, it overflows and goes back to 0 (because we have a 16-bit timer). Hence, this timer is only capable of counting up to 2 seconds, then it overflows.
How to synchronize 2 nodes? If you want to synchronize 2 nodes, then the TIMER_A of both of them must have the same value. Usually, both timers do not have the same value because it is virtually impossible to reset the 2 nodes at the same time to make that both timers start from 0 at the same time. Besides, the clock tick can be slightly different between the 2 sensor nodes. Hence, in order to synchronize the 2 nodes the timesynch file constantly sends a broadcast synchronization message that compares the TIMER_A from node 1 and the TIMER_A from node 2.
How does timesynch file work? This file constantly sends a broadcast synchonization message that compares the TIMER_A from node 1 and the TIMER_A from node 2. The difference between those values is called the offset. Let me say here, that the 2 nodes have an important parameter called Authority level, which is used to determine which node has the reference time. Here, i am going to establish that the Node ID is equal to the authority level (You can assign the authority level any way you want). The node whose authority level is lower will be the owner of the reference time. In this example (See Figure below), node 1 has an authority level of 1, hence, it is the owner of the reference time. It means that if node 1 has a TIMER_A = 15, this will be the actual time of the network, and the other nodes will have to modify their TIMER_A (by summing the offset) to agree with this time. In the next figure, i assume that node 2 has a TIMER_A = 10. Therefore, the offset (difference between node1's TIMER_A (15) and node2's TIMER_A (10) = 15 - 10 = 5 ) is equal to 5. In conclusion, the actual time of the network is node1's TIMER_A = 15, and node 2 corrects its timer by summing the offset (10 + 5 = 15), then both nodes think they synchronized (they have the same time of 15).
Test the rime broadcast example
In this section, i am just going to upload the rime broadcast example in 2 sensor nodes. In the next section i am going to enable the Implicit Network Time Synchronization for this broadcast example.
Here, i am going to use the broadcast example from rime, hence, open the following file:
cd /home/YOUR_USER/Desktop/contiki/examples/rime/ gedit /home/YOUR_USER/Desktop/contiki/examples/rime/example-broadcast.c
This file just sends a broadcast message every 2 to 4 seconds. Clean, compile and upload this file to 2 nodes using the following command:
make clean && make TARGET=sky example-broadcast.upload
Note that i am using TARGET=sky since i am working with sky CM5000 nodes (The Implicit Network Time Synchronization mechanism only works on sky nodes ). Then look to which serial your nodes are connected using this:
make TARGET=sky sky-motelist
Notice one device from the list, for example, the /dev/ttyUSB0. Then connect to one of your nodes to see the arriving broadcast messages:
make TARGET=sky login MOTES=/dev/ttyUSB0
If the broadcast messages are arriving correctly, then you should see this:
broadcast message received from X.X: 'hello' broadcast message sent
where, X.X is the address of the node that sends the message, for example, 185.144 or another number ( This number does not really matter). Besides, you see that the node connected to /dev/ttyUSB0 is actually sending messages: broadcast message sent.
Enable Implicit Network Time Synchronization for the rime broadcast example
To enable the Implicit Network Time Synchronization, you must create a project-conf.h file as follows:
cd /home/YOUR_USER/Desktop/contiki/examples/rime/ > project-conf.h gedit /home/YOUR_USER/Desktop/contiki/examples/rime/project-conf.h
The above does: 1) go to the directory of rime, 2)Create the project-conf.h file, 3) Open the file. Then, in the recently opened file copy this:
#ifndef __PROJECT_CONF_H__ #define __PROJECT_CONF_H__ //Define the network stack #define NETSTACK_CONF_NETWORK rime_driver // Define the network driver to use #define NETSTACK_CONF_MAC csma_driver // Define the MAC driver to use #define NETSTACK_CONF_RDC nullrdc_driver // Define the RDC driver to use. #define NETSTACK_CONF_FRAMER framer_802154 // Define the framer driver to use #define NETSTACK_CONF_RADIO cc2420_driver // Define the radio driver to use. #undef TIMESYNCH_CONF_ENABLED // TO ENABLE THE Implicit Network Time Synchronization #define TIMESYNCH_CONF_ENABLED 1 // TO ENABLE THE Implicit Network Time Synchronization //Define the channel to be used #define RF_CHANNEL 20 #endif /* __PROJECT_CONF_H__ */
The lines that actually enable the Implicit Network Time Synchronization are only 2, and the rest is optional (Another configuration parameters). If you just want to enable the Synchronization mechanism, then copy the following lines in your project-conf.h file.
#ifndef __PROJECT_CONF_H__ #define __PROJECT_CONF_H__ #undef TIMESYNCH_CONF_ENABLED // TO ENABLE THE Implicit Network Time Synchronization #define TIMESYNCH_CONF_ENABLED 1 // TO ENABLE THE Implicit Network Time Synchronization #endif /* __PROJECT_CONF_H__ */
Now, modify your Makefile, and include the following line:
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
To modify your Makefile do this:
cd /home/YOUR_USER/Desktop/contiki/examples/rime/ gedit /home/YOUR_USER/Desktop/contiki/examples/rime/Makefile
Copy and paste this line CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\", and your Makefile should look like this:
CONTIKI = ../.. all: unmodulated_carrier example-abc example-mesh example-collect example-trickle example-polite \ example-rudolph1 example-rudolph2 example-rucb \ example-runicast example-unicast example-neighbors CONTIKI_WITH_RIME = 1 CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" include $(CONTIKI)/Makefile.include
Then, you need to modify the contiki-conf.h file by doing this:
cd /home/YOUR_USER/Desktop/contiki/platform/sky gedit /home/YOUR_USER/Desktop/contiki/platform/sky/contiki-conf.h
In the recently opened file cut this lines:
/* include the project config */ /* PROJECT_CONF_H might be defined in the project Makefile */ #ifdef PROJECT_CONF_H #include PROJECT_CONF_H #endif /* PROJECT_CONF_H */
And paste them at the beginning of the contiki-conf.h file, then your file must look like this:
// START OF FILE (THIS IS A NOTE FROM THIS BLOG) #ifndef CONTIKI_CONF_H #define CONTIKI_CONF_H /* include the project config */ /* PROJECT_CONF_H might be defined in the project Makefile */ #ifdef PROJECT_CONF_H #include PROJECT_CONF_H #endif /* PROJECT_CONF_H */ // ANOTHER STUFF (THIS IS A NOTE FROM THIS BLOG)
That's it. You have enabled the Implicit Network Time Synchronization in Contiki.
See Debug Messages for the Implicit Network Time Synchronization
To see debug messages open the timesynch.c and add the following line at the end of the broadcasr_recv function:printf("broadcast_recv, timesynch_offset = %u timesynch_authority_level = %d \n\r", timesynch_offset(), timesynch_authority_level());
Hence, your broadcasr_recv function should look like this:
static void broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from) { struct timesynch_msg msg; memcpy(&msg, packetbuf_dataptr(), sizeof(msg)); /* We check the authority level of the sender of the incoming packet. If the sending node has a lower authority level than we have, we synchronize to the time of the sending node and set our own authority level to be one more than the sending node. */ if(msg.authority_level < authority_level) { adjust_offset(msg.timestamp + msg.authority_offset, packetbuf_attr(PACKETBUF_ATTR_TIMESTAMP)); timesynch_set_authority_level(msg.authority_level + 1); } printf("broadcast_recv, timesynch_offset = %u timesynch_authority_level = %d \n\r", timesynch_offset(), timesynch_authority_level()); }
Now, go to the step Test the rime broadcast example and run the broadcast example again. You should see the printf that we just added that shows the offset and the authority level of each node when a synchronization broadcast arrives:
broadcast_recv, timesynch_offset = {0-65535} timesynch_authority_level = {AUTHORITY_VALUE}
Notice that you can modify the timesynch_authority_level with the function timesynch_set_authority_level. If you see the message above, then you successfully configured your Implicit Network Time Synchronization mechanism.
NOTE: It is important that you notice that in this example there are 2 kinds of broadcasts. The first kind of broadcast is the 'hello' message sent by the rime example (example-broadcast.c). The second kind of broadcast is the synchronization message sent by the timesynch.c file
Thanks for these tutorials :)
ReplyDeleteNice and clear, thank you so much Sergio, please keep on spreading knowledge.
ReplyDeletePlease share me your email, something related to Contiki. Thanks
ReplyDelete