Monthly Archives: December 2014

Maximum data throughput on a link in the WiSense LPWMN

WiSense CC1101 based nodes are configured to operate at a physical data rate of 38383 bps (bits per second). How many MAC PDUs per second does this translate to assuming each MAC PDU needs to be acknowledged by the receiver ?

Let us calculate the time taken to transmit one maximum sized PHY PDU. The CC1101 transmit and receive FIFOs are 64 bytes each. The maximum MAC PDU which can be sent/received is only 61 bytes. The CC1101 is configured to send a 4 byte preamble and 4 byte SYNC word. This is followed by the MAC PDU. The last 2 bytes contain the CRC calculated over the MAC PDU.

data_phy_pdu

.

.

.

.

.

At 38383 bps, this PHY PDU of total length 71 bytes (containing the data frame) will take 14.798 milli-seconds to transmit.

Now let us look at the PHY PDU containing the acknowledgment frame sent by the data frame’s recepient.

ack_phy_pdu

.

.

.

.

.

At 38383 bps, the PHY PDU (of length 22 bytes) containing the MAC acknowledgment packet will take  4.585 milli-seconds to transmit.

CSMA/CA backoffs can randomly vary between 0 to a maximum of 133  milli-seconds (at 38383 bps). Let us ignore CSMA/CA delay in our calculation.

Ignoring the CC1101 turn around (tx -> rx and rx -> tx) time, the max throughput (in packets) should be 1000 / (14.798 + 4.585). This comes out to 51.6 packets per second. Data throughput (in bps) is then 51.6 * 51 * 8 -> 21052 bps.

I then got some actual numbers by configuring an FFD to continuously send data packets to the coordinator. FFD will send one data packet, get the acknowledgment and then send the next data packet. I disabled CSMA/CA on the FFD before running the test.  I got 15 packets per seconds which is far less than the theoretical max of 51.6 packets/second. My calculation of 51.6 packets/second assumed that the time by the MSP430 to run all the code involved in the test would be negligible (in microseconds) and the UART on the LPWMN coordinator would be able to send all the packets (received from the FFD) to the application running on the laptop (to which the coordinator was connected). One simple mistake was that the UART was configured to operate at just 9600 bps while the data traffic rate in this test is 21052 bps. I increased the UART baud rate to 38400 bps.

Then I did some profiling using a logic analyzer (to get the time taken for the involved code sections to execute using couple of GPIOs on the MSP43) which turned up some surprising results. Code execution was taking a significant time. I made some more changes.

  • One change was to increase the MSP430 operating frequency from 8 MHz to 16 MHz.
  • The second change was to change the SPI bus operating frequency from 0.5 MHz to 8 MHz. Note that the MSP430 communicates with the radio chip (CC1101) over the SPI bus. when the SPI bus is operated at 0.5 MHz, it will take almost 1 millisecond to transfer a packet of (max allowed) size 61 bytes from the MSP430 to the CC1101 or vice versa. When operated at 8 MHz, the same packet will take 62 micro-seconds.

I repeated the traffic test.  This time I got 35 packets per second.  There is more work to be done. I see some inefficiency in the function which reads received data packets from the CC1101’s receive FIFO. I will have another post (or more) on my way to the target (51 packets per second).

I have a pic of the gateway app (running on a laptop under Cygwin) receiving data packets (sent by the FFD via the LPWMN coordinator).

traff_pic

Finding bugs in the WiSense firmware

I am a big fan of the “assert( )” macro. I put in a lot of asserts in my code to catch bugs, race conditions and corner conditions. I use the “assert()” macro whenever the code detects a condition which should never happen. Is is better to “assert( )” rather than let the system run further. This will just hide an obvious bug or worse the system can get trashed and present you with strange symptoms which will almost always take a long time to debug.

When we have a distributed system such as a wireless mesh network, “assert( )” is not going to help if the asserting node is not being debugged (running under JTAG / SPY-BI-WIRE etc). I started off by defining a function “SYS_fatal( )” in the WiSense node firmware. I call this function instead of the macro “assert()”. This function has a infinite loop which simply blinks the two on board LEDs alternately giving me a visual indication that a particular node has asserted and there is now a bug or more to fix. I have been using this method for a long time. I never fail to use an expletive when I find some node giving me the “blink”.

Later I added a 16 bit argument to “SYS_fatal( )”. This argument identifies the location of the code which called “SYS_fatal( )”. I have around 200 “SYS_fatal( )” calls sprinkled throughout the code including the MAC layer, the network layer, the APP layer, driver code etc. I added a unique 16 bit identifier to each of these calls.  For example –

if (condition)  
    SYS_fatal(SYS_FATAL_ERR_X);

I added code (to SYS_fatal()) to store the passed 16 bit argument to the 256 byte EEPROM memory (at byte offset 0) on the AT24MAC602 on board every WiSense node. The function then blinks the two LEDs as before to indicate that the node has asserted.  On reset/power up, a WiSense node reads the last saved 16 bit assert id from the EEPROM and saves it in RAM. Then the EEPROM location containing the 16 bit assert is cleared (set to 0x0000). Assert id 0x0000 indicates that the node was not in a fault/asserted condition before it was reset or power cycled. The 16 bit assert id (read from the EEPROM) then gets sent to the LPWMN coordinator within the ASSOC_REQUEST message (as part of the network joining process).

When the LPWMN coordinator gets an ASSOC_REQUEST from a node, it copies the 16 bit last saved assert id received in the message into the node’s entry in the list of registered nodes maintained in RAM.

The gateway UI (which runs under Linux/Cygwin) has a command “gnlfe” which allows a user to retrieve any registered node’s last saved assert/fault id.

The firmware thus has a mechanism to determine the location of the code which asserted without having to reproduce the scenario with the node in question under JTAG/SPY-BI-WIRE control. This is a big time saver.

Let me end this post by an example of WiSense firmware code which calls SYS_fatal( ).

sts = PLTFRM_startTimerA0(ackTmoMilliSecs, 0, MAC_ackTmoHndlr);
if (sts != PLTFRM_STS_SUCCESS)  
    SYS_fatal(SYS_FATAL_ERR_18);

MAC_cntxt.txModState = MAC_TX_MOD_STATE_WAIT_ACK;

In the example above, the code is calling SYS_fatal( ) if it fails to start a timer. There is no reason why this timer API should fail unless there is a bug in the code. This API fails if the timer “A0” is already running or the timeout is not within the allowed range. Both conditions point to buggy code.

I could have used the C compiler pre-processor macros “__FILE__” and “__LINE__” to identify each invocation of SYS_fatal( ) instead of using a 16 bit unique identifier. The downside is that with time, as code changes, __LINE__ info from a node running an older version of the firmware may not correspond to the latest code. In addition,  __FILE__ and __LINE__ info would increase flash usage (read only data section) and also increase the size of the ASSOC_REQ message.

Addressing in the WiSense low power wireless mesh network (LPWMN)

In the WiSense LPWMN, every node has a 16 bit “short” address. Each LPWMN has one coordinator and the rest of the nodes can be  a mix of FFDs (full function devices capable of routing) and RFDs (reduced function devices which spend most of the time sleeping).

The LPWMN coordinator has a fixed address (0x0001). The broadcast address is also fixed (0xffff). The range of unicast addresses is from 0x0001 to 0x7fff. Multicast addresses range from 0x8000 to 0xfffe.

Each WiSense node has a permanent IEEE provided 64 bit globally unique extended address. This address is embedded in the AT24MAC602 I2C EEPROM on the node. This address allows the node to be uniquely identified by the coordinator irrespective of the 16 bit short address assigned to the node when it joins the network.

Note that only the 16 bit short addresses are used in the MAC header and the mesh header. Routing uses the 16 bit short addresses. The 64 bit extended address is only used to identify a node to the coordinator and the external world since the 16 bit short address allocated to a node can change during the life time of the network.

The LPWMN coordinator allocates addresses to each node which joins the network. As part of the joining/registration process, a node sends out an “ASSOC_REQUEST” command frame containing the node’s 64 bit extended address. This command is relayed to the network coordinator through one or more FFD nodes if the joining node is not a neighbor of the network coordinator.  In response, the network coordinator will allocate a short address and send an “ASSOC_RESPONSE” command frame conveying this short address to the joining node. Once the joining node receives the short address, it is ready to send/receive data traffic (in addition to network traffic).  The coordinator maintains a list of all registered/joined nodes. Each entry in this list stores the node’s 64 bit extended address and the allocated short address among other information.

The first allocated address (by the coordinator) is 0x0002, the second is 0x0003 and so on until 0x7fff (the highest unicast short address). The next address allocated is back to 0x0002 assuming 0x0002 is not currently allocated to any node. If not, the next address tested is 0x0003 and so on until an un-allocated short address is found. You can see the code in the function “NM_allocShortAddr( )” in the file “node_mgr/src/node_mgr.c”.

What happens when a node (which has already joined the network) is reset ? It will try to rejoin the network. When the coordinator gets an “ASSOC_REQUEST” message sent by the re-joining node, it will realize that this node is re-joining when it finds the node’s entry in the list of registered nodes (the search is done using the 64 bit extended address received in the ASSOC_REQUEST). The coordinator allocates a fresh short address to the node and sends this address to the joining node. The node’s entry in the list of registered nodes is updated with the newly allocated 16 bit short address.

When a reduced function device (RFD) is not able to communicate with it’s parent node, the RFD will try to rejoin the network. It will select another parent (if available) and send a ASSOC_REQUEST to the coordinator. The process is exactly similar to the one described just above.

Outdoor testing rig

I made couple of stands using 3/4 inch PVC pipes for outdoor testing. Wanted to share the pics. The sensor nodes are screwed to a metal strip at one end and the other end of this strip is clamped to the upright PVC pipe using two screws. I can loosen one screw to adjust the node’s height. I can also increase the height of the stand by attaching another PVC pipe using a coupler. The stands are cheap, light weight and can be taken apart and put together if required.  On one stand, you can see a USB cable. This will be attached to a laptop to provide serial connectivity and power to the node (configured as the network coordinator).  The other node will run on coin cell or external batteries.

1111

2

5

3

WiSense update – what are we up to ?

I am happy to report that the CC1101/MSP430 based sensor node design is working well. The firmware is pretty stable now. Mesh networking is working though it needs more testing in a large setup. The node’s range is satisfactory.

wisense_node_pic

The CC1101/MSP430 sensor node is equipped with a temperature sensor (LM75B from TI) and an ambient light sensor (TSL45315 from AMS-TAOS).  In addition, the voltage of the node’s power source can be measure by the MSP430 itself (it has an ADC channel allocated for this purpose) and the MSP430 also has an on chip temperature sensor. We are going to add two more low cost sensors (listed below).

  • LIS2DH12  – Three axis accelerometer (SPI interface) from ST
  • LIS3MDL –  three axis magnetic sensor (I2C interface) from ST

The LM75B and TSL45315 are both accessed over the I2C interface.

Other hardware changes –

  • Protection against reverse polarity power supply. The node has a coin cell retainer. In addition, you can apply external power supply (< 3.6 Volts) to the Vcc/Gnd pins which are part of the 4 pin right angled JTAG port or the Vcc/Gnd pins on the 2×6 connectors. The reverse protection mechanism will be added to all these supply points.
  • Allow total current consumption to be measured when node is powered by the coin cell (inserted in the on board coin cell retainer). We will expose a two pin right angled header which will (by default) be shorted by a jumper. To measure current, remove the jumper and put a multi-meter in series.

We are soon going to machine assemble around 100 CC1101 based sensor nodes (our first stab at machine assembly). This should help in reducing assembly time and node cost.

In addition, we are in the initial stages of designing a solar power module for the sensor nodes. Our first design will utilize a super capacitor instead of a battery. Clearly, this will only be suitable for sensor nodes configured to operate as a reduced function device (RFD).

Stay tuned for more updates.

Understanding RSSI and LQI values reported by the CC1101

RSSI stands for received signal strength (power) indication (in dBm). A higher value indicates higher power.

LQI stands for link quality indicator. From the CC1101 spec – “The Link Quality Indicator is a metric of the current quality of the received signal. The LQI gives an estimate of how easily a received signal can be demodulated by accumulating the magnitude of the error between ideal constellations and the received signal over the 64 symbols immediately following the sync word. LQI is best used as a relative measurement of the link quality (a low value indicates a better link than what a high value does), since the value is dependent on the modulation format”.

WiSense node firmware configures the CC1101 to append the RSSI and LQI of the received packet at the end of the packet’s payload in the 64 byte receive FIFO. The MAC layer thus knows the RSSI and LQI associated with each received packet. The RSSI value reported by the CC1101 is a 8 bit signed number with an effective range from -138 dBm to -10.5 dBm when the CC1101 is operating around 868 MHz. The LQI value reported by the CC1101 is a 7 bit unsigned number with a range from 0 to 127. Note that a lower value indicates a better link.

The sniffer trace below will help in understanding the difference between RSSI and LQI. The setup (from which trace was captured) had four nodes (one coordinator, one FFD , one RFD and one sniffer).  The coordinator and the RFD were far apart with the FFD in the middle (closer to the coordinator). The RFD was only able to connect through the FFD (the coordintor and the RFD could not hear each other). The sniffer is adjacent to the FFD. The short addresses of the nodes are listed below.

  • Coordinator    –   0x0001
  • FFD                  –   0x0006
  • RFD                 –    0x0007

The sniffer trace shows a data packet sent by the RFD to the FFD.  The sniffer’s CC1101 sniffed this packet and the corresponding RSSI is -81 dBm and the LQI is 43.  The next packet is an acknowledgment sent by the FFD to the RFD. Since the FFD and the sniffer are adjacent, the sniffer received the ack packet with a RSSI of -29 dBm and an LQI of 44.  You can see that the RSSI of the first packet is almost (-29 – (-81)) -> 52 dB below the second packet. 52 dB means the second packet had a power level almost 158490 times greater than the power level of the first packet. Even though the power levels are so far apart, the LQI (signal quality) levels are almost the same. This means that the CC1101 was able to demodulate both packets easily since the packet quality was similar.

———————————————————————————————————–
#<17410> <Thu Dec 18 13:26:54 2014> rssi<-81 dBm> lqi<43> len<61>
rxPyldSize left<0x39>
Type<DATA> Sec<n> FP<n> AR<y> PIC<n> Seq-Nr<180>
Dest LPWMN-Id<0x7455> / Dest Short<0x0006>
Src LPWMN-Id<0x7455> / Src Short<0x0007>
———————————————————————————————————–
#<17411> <Thu Dec 18 13:26:54 2014> rssi<-29 dBm> lqi<44> len<16>
rxPyldSize left<0xc>
Type<ACK> Sec<n> FP<n> AR<n> PIC<y> Seq-Nr<180>
Dest LPWMN-Id<0x7455> / Dest Short<0x0007>
Src LPWMN-Id<0x7455> / Src Short<0x0006>
rssi<-93> lqi<47>
———————————————————————————————————–
#<17412> <Thu Dec 18 13:26:54 2014> rssi<-29 dBm> lqi<43> len<61>
rxPyldSize left<0x39>
Type<DATA> Sec<n> FP<n> AR<y> PIC<n> Seq-Nr<437>
Dest LPWMN-Id<0x7455> / Dest Short<0x0001>
Src LPWMN-Id<0x7455> / Src Short<0x0006>
———————————————————————————————————–
#<17413> <Thu Dec 18 13:26:54 2014> rssi<-41 dBm> lqi<42> len<16>
rxPyldSize left<0xc>
Type<ACK> Sec<n> FP<n> AR<n> PIC<y> Seq-Nr<437>
Dest LPWMN-Id<0x7455> / Dest Short<0x0006>
Src LPWMN-Id<0x7455> / Src Short<0x0001>
———————————————————————————————————–

The LQI of a received packet will be bad (higher number) when there is lot of interference.  Let us take two signals. One is a perfect sine waves with an amplitude of 100 volts and the other is a perfect sine wave with an amplitude of say 10 milli-volts. The first signal is almost 10^4 times bigger in amplitude but their quality is almost the same. If a noise with average amplitude of say 50 volts is mixed with the first signal, you will agree that its quality has now dropped if you saw the mixed signal on a scope. So, even though the second signal has a far smaller amplitude, it has a higher quality compared to the the first signal (now mixed with noise).

Why do we care about RSSI and LQI ?

RSSI and LQI can be used for link selection by routing algorithms. Suppose node A wants to second a packet to node F and there is no route on A for F. WiSense network layer on A will initiate route discovery to node F. WiSense network layer currently uses AODV-L (L is for light) as the routing algorithm. The routing algorithm depends on a route cost metric when evaluating the best route between A and F. The route cost metric can be as simple as the number of hops between A and F. So if multiple routes are discovered (during the route discovery process) between A and F, the routing algorithm will choose the route with the least number of hops. The routing cost metric can be more sophisticated if it takes into account the RSSI or LQI or some combination of both to assign each link a cost. The algorithm can then choose the route whose route cost (calculated (for example) by a simple summation of link costs) is the least. Researchers have come up with many different link/route cost metrics. Let us come back to RSSI and LQI. Suppose the routing algorithm ignored the LQI values and solely depended on RSSI values. It is likely that the routing algorithm will end up selecting routes with bad links (too many packet drops) with good RSSI but bad LQI.  Why not depend on LQI alone ? This means throwing away useful RSSI information. Why not use both. For links with similar LQIs, choose the link with better RSSI. This sounds like a good idea.

Link cost metric is also used when an RFD tries to select a parent node at the time of joining the network. If the parent selection process throws up multiple parents (RFD receives beacons from multiple FFDs) , an algorithm is needed to select the best one. This algorithm can simply choose the parent from which the strongest (best RSSI) beacon is received. It can use LQI only or a combination of LQI and RSSI (described above). The algorithm can also include the parent’s distance from the coordinator as a factor in deciding the parent.

Note that RSSI and LQI can vary widely over the lifetime of a link. Human movement and varying EMI (radio frequency interference) for instance can have considerable effect on RSSI and LQI even for links between stationary nodes. How does one route if links keep changing ? This is one of the big challenges in low power wireless sensor networks. If the (RF) links in a network are fickle, you need a agile routing algorithm which can adapt to the changing conditions but this might increase the network overhead (ratio of data to control traffic). As with most everything else in wireless sensor networks, this is far easier said than done.

References:

  1. http://www.ti.com/lit/ds/symlink/cc1101.pdf
  2. https://sing.stanford.edu/pubs/rssi-emnets06.pdf
  3. http://e2e.ti.com/support/wireless_connectivity/w/design_notes/calculation-and-usage-of-lqi-and-rssi

Using a Sniffer to capture traffic in a WiSense network

A WiSense node needs to be flashed with a WiSense sniffer image so that it can act as a traffic sniffer. The “sniffer” node does not send out any traffic. It only receives all the traffic in the channel it has been configured to operate in. A sniffer is a really useful tool in troubleshooting a network. You can also use it to understand the flow of control and data traffic. If you have a widely dispersed network, you may need more than one sniffer nodes to look at all the traffic in the network. In a “star” network, you just need one sniffer near the coordinator node to look at all traffic in the network.

 

Let us look at actual network traffic captured by a WiSense node operating as a sniffer. The network has a coordinator, one FFD (full function device) and two RFDs (reduced function devices). The FFD is the parent node of both the RFDs. The RFDs are sending data to the outside world via the FFD and the COORD.

Short addresses of the nodes involved –

  • Coord – 0x0001
  • FFD –  0x0006
  • RFD_1  – 0x0007
  • RFD_2 – 0x0009

sniffer

 

sniffer_pkt_explaind
————————————————————————————————————
#<17408>    <Thu Dec 18 13:26:53 2014>    rssi<-29 dBm>    lqi<44>    len<55>
rxPyldSize left<0x33>
Type<DATA>    Sec<n>    FP<n>    AR<y>    PIC<n>    Seq-Nr<436>
Dest LPWMN-Id<0x7455>    /    Dest Short<0x0001>             
Src LPWMN-Id<0x7455>    /    Src Short<0x0006>                 
————————————————————————————————————
#<17409>    <Thu Dec 18 13:26:53 2014>    rssi<-42 dBm>    lqi<45>    len<16>
rxPyldSize left<0xc>
Type<ACK>    Sec<n>    FP<n>    AR<n>    PIC<y>    Seq-Nr<436>
Dest LPWMN-Id<0x7455>    /    Dest Short<0x0006>       
Src LPWMN-Id<0x7455>     /    Src Short<0x0001>
———————————————————————————————————–

The two frames sniffed above show sensor data sent by the FFD (0x0006) to the coordinator (0x0001) and the corresponding acknowledgment.  The “AR<y>” field in the first packet indicates that this packet needs to be acknowledged by the receiver (0x0001).  The second packet above is an acknowledgement packet sent by 0x0001 to 0x0006.

 

———————————————————————————————————–
#<17410> <Thu Dec 18 13:26:54 2014> rssi<-81 dBm> lqi<43> len<61>
rxPyldSize left<0x39>
Type<DATA> Sec<n> FP<n> AR<y> PIC<n> Seq-Nr<180>
Dest LPWMN-Id<0x7455> / Dest Short<0x0006>
Src LPWMN-Id<0x7455> / Src Short<0x0007>
———————————————————————————————————–
#<17411> <Thu Dec 18 13:26:54 2014> rssi<-29 dBm> lqi<44> len<16>
rxPyldSize left<0xc>
Type<ACK> Sec<n> FP<n> AR<n> PIC<y> Seq-Nr<180>
Dest LPWMN-Id<0x7455> / Dest Short<0x0007>
Src LPWMN-Id<0x7455> / Src Short<0x0006>
rssi<-93> lqi<47>
———————————————————————————————————–
#<17412> <Thu Dec 18 13:26:54 2014> rssi<-29 dBm> lqi<43> len<61>
rxPyldSize left<0x39>
Type<DATA> Sec<n> FP<n> AR<y> PIC<n> Seq-Nr<437>
Dest LPWMN-Id<0x7455> / Dest Short<0x0001>
Src LPWMN-Id<0x7455> / Src Short<0x0006>
———————————————————————————————————–
#<17413> <Thu Dec 18 13:26:54 2014> rssi<-41 dBm> lqi<42> len<16>
rxPyldSize left<0xc>
Type<ACK> Sec<n> FP<n> AR<n> PIC<y> Seq-Nr<437>
Dest LPWMN-Id<0x7455> / Dest Short<0x0006>
Src LPWMN-Id<0x7455> / Src Short<0x0001>
———————————————————————————————————–

The four frames sniffed  above show data send by an RFD (0x0007) to the outside world via the parent node (0x0006) and the network coordinator (0x0001).

Description –

  • 17410 – Data frame sent by RFD (0x0007) to parent node (FFD – 0x0006) with ACK required bit set
  • 17411 – Acknowledgment frame from 0x0006 to 0x0007
  • 17412 – Data frame forwarded by 0x0006  to  0x0001 with ACK required bit set
  • 17413 – Acknowledgment frame from 0x0001 to 0x0006

 

The WiSense sniffer has the following components –

  • WiSense node
  • USB cable to connect the WiSense node to a PC USB port. There is a “mini-B” USB receptacle on the WiSense node.
  • Firmware – Sniffer firmware which needs to be loaded on the node’s MSP430
  • UI – Textual interface which can be run on any Linux system (including the Raspberry PI) or under Cygwin/windows.  This has a couple of files which can be compiled using “gcc”.

$ ./sniffer.exe  ?
Usage: ./sniffer.exe <serial-device> <chann-nr (1 to 9)>
On Cywgin, if the COM port is COMa, the corresponding serial port device is /dev/ttySb where b=a-1
Example: ./gw.exe /dev/ttyS20 5

$ ./sniffer.exe   /dev/ttyS2   5

 

You just need to tell the sniffer firmware the channel number to operate on.  In the example above, the serial port connected to the WiSense node is /dev/ttyS2 and the channel to operate in is 5.

Why we don’t support TinyOS/Contiki/6LowPAN/RPL/REST etc on WiSense nodes

I receive lot of queries for sensor nodes with support for the above mentioned technologies. There is a reason why we are not supporting any of these fine technologies. There is nothing wrong with any of them. It is just that they can be overwhelming for the vast majority of WSN/IOT enthusiasts. wisense_mesh_nwk

Most literature on sensor/actuator networks mentions networks with millions of nodes and the need for IPv6 to address this large address space. On the other hand, in real life most applications (such as home automation) have far fewer nodes. Even 16 bit addressing is more than enough for most practical applications. Another issue is the prevalence of IPv4 (not IPv6). Most home routers/WAN gateways (at least in India) do not support IPv6 . What is the point in having IPv6 just inside the mesh network ? You will have to translate between IPv4 and IPv6.

The WiSense network architecture is pretty simple. You have a bunch of wireless sensor nodes and a network coordinator node. The sensors node can be powered by a 3V coin cell (CR-2032). The network coordinator serves as the interface between the external world and the wireless sensor network (WSN).  Connect the coordinator to a laptop using a USB cable. This cable will provide power and serial connectivity to the coordinator node. Run a simple C program on the laptop to get all kinds of information about the network from the coordinator as well as collect data sent out by the sensor nodes in the WSN. Switch on all the sensor nodes. All the nodes will join the network and in the process get a unique 16 bit short address. Once a node join the network, it will start sending sensor data to the external world (via the coordinator node) as dictated by the application running on the node. On the laptop, you will be able to see all the data sent out by each of the sensor nodes. Currently we have two kinds of sensor nodes (RFDs and FFDs). RFDs are reduced function devices which spend most of their time sleeping, waking up now and then to read on board sensors and communicate with the outside world (via the coordinator) if required. These nodes have a limited energy source and therefore have to be very frugal in their power consumption so that their energy source (usually a coin cell or AA batteries) can last as long as possible. RFDs do not take part in routing. FFDs on the other hand are usually AC powered or have some unlimited energy source so that they are “on” all the time. They participate in routing and serve as parents to RFDs. The network coordinator is classified as an FFD. RFDs communicate via their parent node only. RFDs select a parent node at the time of joining the network. The coordinator and the FFDs participate in creating a mesh network so that any node can talk to any other node. Since RFDs are usually asleep, they use a polling mechanism (when they wake up) to query their parent for any frames buffered (on the parent) for them. WiSense nodes use a simple mesh routing protocol which is a simplified/lighter version of AODV (AODV-L). Addressing is on the basis of 16 bit short addresses allocated at the time of joining.  This is it. There is nothing more to the WiSense architecture. Pretty basic (like the Tata Nano).  We believe this is simpler to understand for the vast majority of people interested in WSNs. This can be a first step before moving on to more complicated concepts such as 6LowPAN/RPL/COAP/REST etc.

IPv6/6LowPAN is not an easy concept to grasp, especially given the common application scenarios for WSN/IOT. Suppose you have a bunch of sensor nodes in different rooms in your house. You have a network coordinator node connected to a raspberry PI. The raspberry PI is connected to your wireless router. The WSN interface code is (the C program mentioned above) running on the PI. You have a web server running on the PI. You use a web browser on your laptop to connect to the PI. You have a simple web page showing all the nodes. The page shows you data from the nodes and allows you to control the nodes. Your browser talks to the PI using IPv4. The browser talks to the WSN through the interface/glue code. Do you need IPv6/6LoWPAN in this scenario ? Do you really need to assign an IPv4 / IPv6 address to each node ? Let us say you do need an IPv4 or IPv6 address for each node. In this case you can do the translation from IPv4/IPv6 and the nodes’s short address on the Raspberry PI. The WiSense stack does not have to modified if the translation is done on the PI. How about the operating system ? WiSense nodes use the MSP430G2955 micro from TI. They have 4 KB RAM (data space) and 56 KB flash (code/data space). Obviously we can’t have a full fledged OS here. Why not use Contiki? Because Contiki is another new concept to grasp. TinyOS is even more complicated compared to Contiki. WiSense node software architecture is very simple (nothing new). There is a single central loop which checks event flags and invokes functions in different layers when the corresponding bit is set. There are no threads and therefore no blocking. Suppose the network layer wants to forward a packet to a neighbor node. Once it has the packet ready (with all the network layer headers updated), it will set a flag in the common 48 bit flag group indicating that it wants to send a packet out and return control to the central loop. The central loop is always checking for flags set in the common 48 bit flag group . When it sees the flag set by the network layer, it will check if the MAC layer is free. If the MAC layer is free, it will call a network layer function to do the handover from the network to the MAC layer. If the MAC layer is not free (it is sending a frame or an ACK), the central loop will  move on to check other flags. Eventually when the MAC layer becomes free, the central loop will call the network layer function to do the handover after clearing the flag.

I want to emphasis that I am not against TinyOS/Contiki/RPL/6LoWPAN etc. I am just not sure if this is the way for most beginners to start on the WSN/IOT journey. Having said that, one  can always upgrade WiSense nodes to use these technologies. Some of these technologies can be incorporated into the current WiSense architecture. For example, COAP/REST (at the application layer) etc. You can replace AODV-L with RPL (use 16 bit addresses instead of IPv6 addresses).

WiSense node antenna orientation

In this post, I am going to talk about how antenna orientation has an effect on a node’s range.

The WiSense CC1101 base nodes utilize a whip antenna. See the pic below.  This is a quarter wave, reduced height, omni-directional helical whip antenna. It connects to the RF board through an SMA connector which allows the antenna to be removed.

As mentioned above, this antenna has an omni-directional radiation pattern. The radiation pattern of an antenna determines it’s coverage.  Let me quote Wikipedia’s description –

“In radio communication, an omni-directional antenna is a class of antenna which radiates radio wave power uniformly in all directions in one plane, with the radiated power decreasing with elevation angle above or below the plane, dropping to zero on the antenna’s axis. This radiation pattern is often described as “doughnut” shaped.”

omni_pattern

.

.

.

.

.

.

.

.

.

.

Imagine this doughnut (in the pic above) placed on a table with the hole pointing towards the ceiling. As you can see, the radiation pattern is uniform in all directions in the horizontal plane (parallel to the ground).  An antenna with this radiation pattern will have the same range in all directions parallel to ground but it’s range in the vertical direction (perpendicular to ground) won’t be as much. Let us compare it with the isotropic radiation pattern shown in the figure below.

Isotropic 1

.

.

.

.

.

.

.

.

.

.

.

.

.

You can see that the isotropic radiation pattern is symmetric in all directions which means any antenna with this radiation pattern will have the same range in all directions. Unfortunately, such an antenna exists only in theory but it serves as a good reference for our discussion.

node_pattern1

.

.

.

.

.

.

.

.

.

.

.

.

The Linx antenna used by WiSense nodes have an omni-directional pattern. Imagine the antenna at the center of the doughnut hole pointing towards the ceiling.  These antennas are what you need if you need good coverage in the horizontal plane (parallel to the ground). For example, you have a bunch of WiSense nodes (all antennas pointing skywards) spread out over a soccer field.  and the nodes are more or less at the same height above ground.  In this scenario all the nodes should be able to talk to each other. Now, suppose you place one of the nodes at some height above the ground (say 10 meters),  this node may go out of coverage of the other nodes.

Suppose you have two WiSense nodes at either ends of the soccer field. Assume they are sending packets to each other. Note down the RSSI (received signal strength) in dBm of frames received by each node. If the nodes (and therefore the antennas) are pointing up, then they will be able to talk to each other. Now suppose you tilt one node (and therefore the antenna) parallel to the ground, you will note a significant drop in signal strength of received packets. You might loose connectivity altogether. Now suppose you tilt the other node so that it is also parallel to the ground. You will loose connectivity completely since the radiation patterns of the two nodes are now vertical to the ground and parallel to each other.

How about two WiSense nodes close to each other (say a meter apart) with one node pointing towards the ceiling and another node pointing sideways (parallel to the ground).  The RSSI will still be less (compared to the case where both are pointing towards the ceiling) even though both are pretty close (relative to the maximum range of WiSense nodes (> 300 m in the open). This has to do with antenna polarization. Electromagnetic waves radiated by an antenna constitute an E field (electric field) and an H field (magnetic field) perpendicular to each other as well to the direction of propagation of the wave. The electric field or “E” plane determines the polarization (orientation) of the electromagnetic wave. An antenna is vertically polarized (linear) when its E field is perpendicular to the Earth’s surface. The Linx whip antenna on a WiSense node is a vertically polarized antenna when the node is pointing towards the ceiling.  It is important that two wireless devices (which want to communicate) with each other should be identically polarized. That is, the E-plane of the radio waves produced by the two antennas should be parallel to each other. In a linearly polarized system, a misalignment of polarization by 45 degrees will degrade the signal up to 3 dB and if mis-aligned by 90 degrees the attenuation can be 20 dB or more*.

You can easily see the effect of polarization using two WiSense nodes. Take one RFD/FFD and let it connect to a coordinator node. Keep the nodes a meter or two apart. Configure the RFD/FFD to send data periodically to the coordinator and monitor the data on a laptop (to which the coordinator is connected).  The sample UI app (from WiSense) prints out the signal strength (RSSI) of each packet received from a remote node (in addition to sensor data). Start off with the RFD and coordinator pointing to the ceiling. Note down the RSSI of say 10 packets sent by the RFD. Now tilt the RFD so that it’s antenna is parallel to ground. Now note the drop in received RSSI.

References:

WiSense MAC – Duplicate packet detection

In this post, I am going to explain how WiSense MAC  (Medium access control) layer handles duplicate packets.

Assume you have two WiSense nodes, node A and node B. Suppose node A sends a packet (say Px) to node B and the “ack_required” bit in the packet’s MAC header is set to 1. When “B” receives this packet ‘Px’ , it will send an acknowledgment frame to A. If A receives this acknowledgment frame, A will be satisfied that the packet ‘Px’ has made it to B. If A does not receive this acknowledgment frame from B, A will retransmit ‘Px’ to B. Note that when B receives ‘Px’, it will send the corresponding ACK frame (to A) immediately without performing CSMA/CA (carrier sense multiple access with collision avoidance).  A will retransmit  ‘Px’ at most 3 times. If A still does not receive acknowledgment from ‘B’, ‘A’ will give up and delete the packet ‘A’.

If ‘A’ does not get acknowledgment from ‘B’, there are two possibilities –

  • B did not receive ‘Px’ sent by A

or

  • B received ‘Px’ from A but A did not receive the acknowledgment sent by B.

In the second case, A will resend ‘Px’ to B. If this re-transmission also makes it to B, B will receive ‘Px’ again (a duplicate). In the worst case, B will receive 4 copies of the same frame ‘Px’. It is very important that B drop the duplicates.

The MAC layer includes a mechanism to detect (and drop) duplicate frames received over a link. The MAC header has a 2 byte frame sequence number. Each WiSense node maintains a 16 bit frame sequence number (FSN) in the MAC layer.

  • 1 <= FSN <= 65535.
  • 0 is not a valid FSN.
  • When FSN reaches 65535, it will start back again from 1.

Whenever a node transmits a MAC frame (other than an ACK frame),  it will copy the current value of the FSN into the MAC header. It will then increment this FSN.  This means every frame sent out will have a different frame sequence number. Note that re-transmissions of a frame have the same sequence number. Let us take the two node example above. Suppose A sends sequence number 389 in the frame ‘Px’ sent to B. When B receives ‘Px’, B will make a note that it has received a frame with sequence number 389 from node A. Suppose A does not receive the acknowledgment sent by B and A resends ‘Px’ (containing the same sequence number 389). B will receive ‘Px’ again but it will drop this duplicate frame since the duplicate frame has the same sequence number (389) which B has already noted down from the first ‘Px’ frame received from A.

Note that a node may have multiple (N) neighbors which are sending packets to it. It has to do duplicate detection on packets received from all of these ‘N’ nodes. Each node maintains its FSN independent of other nodes which means a node can receive frames (from different nodes) with the same sequence number. So it is not enough to just store the frame sequence number from the last received frame. The MAC needs to store both the source address and the last sequence number received from that source address.

WiSense MAC maintains a table (on each non RFD) of received frames. Each entry in this table has three fields.

  • Field 1 – The 16 bit MAC address of the node which sent the frame
  • Field 2 – The 16 bit frame sequence number from the frame’s MAC header
  • Field 3 – Time to expiry (in seconds) of this entry (8 bit value).

Currently this table can have max 32 entries.

Whenever a node receives a (non acknowledgment) frame, it will look up this table to check if the received frame is a duplicate or not. If the frame is a duplicate, it will be dropped but an acknowledgment will still be sent to the source if the received frame has the acknowledgment required bit set in the MAC header. If the received frame is not a duplicate, the corresponding entry (16 bit MAC address of the sender) in the table is updated with the new frame sequence number from the received frame. Every time an entry is updated or created, it’s time-to-expiry field is set to 8 seconds. This field is decremented every second. When this field becomes zero, the corresponding entry is deleted.

Another point which is relevant to this discussion is the short address allocated to nodes. If a node rejoins the network it will get a new short address.

Finally let us look at duplicate frame detection on RFDs (reduced function devices). A WiSense RFD only communicates with/via its parent. This means it only has to worry about duplicate packets received from its parent node. RFDs, therefore, do not need to maintain a table. They just need to maintain the frame sequence number in the last frame received from the parent. RFD MAC resets this sequence number to 0 (the invalid sequence number) every time the RFD wakes up from deep sleep.