EECS 373 Lab 8: Low-Power Wireless Communication

Copyright © 2010 - Thomas Schmid, Matt Smith, Ye-Sheng Kuo, and Prabal Dutta.

Schedule

See posted lab schedule for due dates, in-lab, and post-lab due dates.

Objectives

The purpose of this lab is to...

  1. Familiarize yourself more with wireless radios
  2. Investigate Low-Power MAC protocol design

Background

Additional Material

Following are some paper references on Wireless Communication

  1. Prabal Dutta, Stephen Dawson-Haggerty, Yin Chen, Chieh-Jan Mike Liang, and Andreas Terzis, "Design and Evaluation of a Versatile and Efficient Receiver-Initiated Link Layer for Low-Power Wireless," ACM Sensys 2010 (http://www.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/p101-dutta.pdf)
  2. Joseph Polastre, Jonathan Hui, Philip Levis, Jerry Zhao, David Culler, Scott Shenker, and Ion Stoica, "A Unifying Link Abstraction for Wireless Sensor Networks," Sensys 2005
  3. Gahng-Seop Ahn, Emiliano Miluzzo, Andrew T. Campbell, Se Gi Hong, Francesca Cuomo, "Funneling-MAC: A Localized, Sink-Oriented MAC for Boosting Fidelity in Sensor Networks," ACM Sensys 2006.
  4. Kevin Klues, Gregor y Hackmann, Octav Chipara, Chenyang Lu, "A Component-Based Architecture for Power-Efficient Media Access Control in Wireless Sensor Networks," ACM SenSys 2007.
  5. Nicolas Burri, Pascal von Rickenbach, and Roger Wattenhofer, "Dozer: Ultra-Low Power Data Gathering in Sensor Networks," ACM/IEEE IPSN 2007.
  6. Wei Ye, Fabio Silva, and John Heidemann, "Ultra-Low Duty Cycle MAC with Scheduled Channel Polling," ACM Sensys 2006.
  7. M. Buettner, G. Yee, E. Anderson, R. Han, "X-MAC: A Short Preamble MAC Protocol for Duty-Cycled Wireless Sensor Networks," ACM Sensys 2006.
  8. Amre El-Hoiydi and Jean-Dominique Decotignie, "WiseMAC: An Ultra Low Power MAC Protocol for Multi-hop Wireless Sensor Networks," First International Workshop on Algorithmic Aspects of Wireless Sensor Networks (Algosensors 2004), July 2004.
  9. S. Ganeriwal, I. Tsigkogiannis, H. Sim, V. Tsiatsis, M. B. Srivastava, and D. Ganesan, "Estimating Clock Uncertainty for Efficient Duty-Cycling in Sensor Networks," IEEE/ACM Transactions on Networking, 2008.
  10. J. Polastre, J. Hill, D. Culler, "Versatile Low Power Media Access for Wireless Sensor Networks," ACM Sensys 2004

There are also many good books on fundamentals of wireless communication. A very good one from David Tse and Pramod Viswanath is even available as PDFs online Fundamentals of Wireless Communication

Overview

Pre-Lab Assignment

  1. Read through the lab 8 notes.
  2. Read through lecture 12 slides again and familiarize yourself with the material.
  3. Read through one or two papers mentioned above, so you get a good idea of what this lab is all about.

Lab Assignment

This lab is different from the other labs. You have so far explored the fundamentals of embedded systems and understand memory, buses, peripherals, and analog to digital conversion (and back). In this lab you will have to explore and think yourself as we give you only few instructions. See this as a good preparation for the project ahead of you.

For that purpose, there is no in-lab or post-lab component. Just an assignment. The rest of this text will state the assignment and give you some more general hints and tools you can use to solve it.

The Goal of this Lab

Write a low-power wireless MAC protocol as described during lecture 12. We don't ask you to write one specific MAC protocol. You have to come up with your own, or implement ideas from other Low-Power MAC protocols. Your assignment will be graded by how much power you can save from the baseline, plus the ability to communicate with a second radio that runs the same MAC protocol. We will measure the power drawn of both boards and average over them. Therefore, don't just let one of the radios on all the time!

Your nodes should communicate at least once every second. In addition, you need to add visual feedback indicating when a message gets sent, or received.

The Baseline MAC

You can use the following code as the baseline. It implements a simple sender/receiver application and the radios are on all the time. The SPI driver is implemented for you. However, feel free to change the design and hardware components as you wish. You can use new timer units, SPI controllers, etc, as long as the radio still works at the end.

You can use the following code to start with. It is essentially the code from Lab 6 plus the SPI driver. If your SPI driver worked well for Lab 6, then you can also use that one instead of this project.

FPGA Code: cc2520Fpga.zip

SoftConsole Workspace: cc2520Workspace.zip

Radio Interface

You can use the following functions from cc2520driver.h to control the radio. Feel also free to tweak parameters in cc2520.h or the driver code in cc2520.c if you think it is necessary.

/*
 * cc2520driver.h
 *
 *  Created on: Sep 18, 2010
 *      Author: Thomas Schmid
 */

#ifndef CC2520DRIVER_H_
#define CC2520DRIVER_H_

#include "config.h"

/**
 * Initialize the radio. This function has to be called only once
 * after powerup of the whole system. It initializes all the I/O
 * lines and puts the radio into LPM1 (everything initialized, but
 * oscillators are still turned off).
 */
void Radio_init();

/**
 * Turn on the radio receiver. The CC2520 now draws about 20 mA.
 *
 * return SUCCESS if the command succeeded.
 */
error_t RadioState_turnOn();

/**
 * Put the radio into Active mode, i.e., turn off the receiver
 * while keeping the oscillators running. This draws about 1 mA.
 * The advantage is that we can quickly switch back into receive
 * mode within about 192 us.
 *
 * return SUCCESS if the command succeeded.
 */
error_t RadioState_standby();

/**
 * Put the radio back into Low Power mode 1. In this mode, the radio
 * draws about 200 uA while retaining state. The oscillators are turned
 * off, but the voltage regulator is kept on. It takes at least 0.2 ms to
 * get back into receive mode.
 *
 * return SUCCESS if the command succeeded.
 */
error_t RadioState_turnOff();

/**
 * Shutdown the radio. This turns off the voltage regulator of the radio
 * and is the lowest power possible at 0.1 uA. It takes at least 0.3 ms
 * to get back into a receive mode (not including SPI initialization).
 *
 * Currently not implemented
 *
 * return SUCCESS if the command succeeded.
 */
error_t RadioState_shutdown();

/**
 * Change the radio channel. Valid channels are 11 to 26, corresponding
 * to the 16 IEEE 802.15.4-2006 compliant channels.
 *
 * param c The radio channel to which we should switch
 * return SUCCESS if the command succeeded.
 */
error_t Radio_setRadioChannel(uint8_t c);

/**
 * Send a radio message.
 *
 * param seqn The sequence number of the message. The application developer
 *            has to assure that it is incrementing.
 * param panid The IEEE802.15.4 Personal Area Network ID. Can be used to
 *             filter messages belonging to a different network.
 * param saddr The source address of the message.
 * param daddr The destination address of the message.
 * param payload The data payload of the message.
 * param length Size in bytes of the payload.
 *
 * return SUCCESS if the command succeeded.
 */
error_t Radio_send(uint8_t seqn, uint16_t panid, uint16_t saddr, uint16_t daddr, uint8_t* payload, uint8_t length);

/**
 * This function has to be defined in your own code. It gets called when the
 * radio is done sending the message, and a new message can be sent. It is
 * kind of a callback function.
 *
 * param error SUCCESS if the message was successfully sent.
 */
void Radio_sendDone(error_t error);

/**
 * This function has to be defined in your own code. It indicates the reception
 * of a message by the radio.
 *
 * param seqn The sequence number of the message. The application developer
 *            has to assure that it is incrementing.
 * param panid The IEEE802.15.4 Personal Area Network ID. Can be used to
 *             filter messages belonging to a different network.
 * param saddr The source address of the message.
 * param daddr The destination address of the message.
 * param payload The data payload of the message.
 * param length Size in bytes of the payload.
 * param rssi The received signal strength measured during radio reception.
 */
void Radio_receive(uint8_t seqn, uint16_t panid, uint16_t saddr, uint16_t daddr, uint8_t* payload, uint8_t length, int8_t rssi);

/**
 * This function requests a clear channel assessment from the radio. The
 * return value indicates if the radio channel (or radio itself) is currently
 * busy.
 *
 * return SUCCESS if channel is free, EBUSY otherwise
 */
error_t Radio_requestCCA();

#endif /* CC2520DRIVER_H_ */

Tips & Tricks for Successful Wireless Communication

Common Message Structures

You might have wondered how your application can differentiate different types of messages. For example, how do you know that a message is an acknowledgment, and not another radio message from a different node? In general, radio's don't care about such details. They just send out whatever bytes you give them. Thus, it is the application's job to specify a message structure.

Look at the provided application in main.c. You will fine a typedef struct at the top of the file. This newly defined type constitutes the messages that get send over the radio for this simple counter application. Similar to memory mapped I/O, where you can use structs to make memory access easier and more comprehensible, here, we use structs to define the byte sequence of a message. This particular blinkmsg_t struct, for example, defines the first byte to be named group, the second amtype and the third and fourth will be a counter.

An application could now use the amtype field to differentiate between the meaning of the counter value, or between the meaning of the message. For example, an amtype equal to 0 could mean a regular message, while an amtype of 1 could be an acknowledgment.

CRC

CRC stands for Cyclic Redundancy Check. It is an integrity check that indicates to a receiving radio if the message got corrupted or not. The CRC is automatically calculated by the radio. All the radio driver has to do is download it (it is attached to the end of every message), and check if it is OK or not. Thus, your application does not have to worry about message integrity. The radio and radio driver are taking care of it. However, if your are interested in receiving corrupted messages, then you will have to modify the radio driver. The CRC check is done on line 1029 in cc2520.c. We only signal a received message if the CRC turns out good. You would want to change this to always signal a received message. However, I strongly suggest to also change the receive interface and add the CRC field in it. Else, your application will have difficulty to differentiate between corrupted and non-corrupted messages.

Message Acknowledging and Frame Filtering

While the radio supports automatic hardware acknowledgments, it is not currently implemented. If you need fast turn-around times for ACKs, then you will have to enable them. This is done by changing the radio configuration using the writeRegister function. Find out from the TI CC2520 Manual which register you will have to change in order to enable hardware acknowledgments. Once enabled, the radio will send an automatic ACK message after each successfully received message. However, you will also have to enable Frame Filtering as you only want a radio to acknowledge messages that are destined to its address. The CC2520 radio can automatically filter messages that are not addressed to it, or that are not sent to the broadcast address (0xFFFF). For this to work, you will have to change some radio registers and let the radio know its address. Again, read through the TI CC2520 Manual to find out how to do this.

Programming your Application into the Non-Volatile Memory

By now you probably noticed that when you unplug your evaluation board from the USB cables, and plug it back in, your application is gone. This is because we used the volatile SRAM as build target. The eval board also has non-volatile memory. In fact, we have a total of 256 kB of Flash memory, while we "only" have 64 kB of SRAM. This means that you can write much larger and complex code if you program it into Flash. Additionally, your application will also run after you unplug it from the USB cables. This will be useful in case you want to be mobile for you project.

The disadvantage of using Flash are higher execution cost (reading/writing to flash costs more energy), limited amount of write cycles (~100k), and slower programming. Thus, you really want to first test your code using the SRAM target, where you can have a quick development cycle. Once you are sure it works, program it into the Flash for further testing.

The easy way of using the Flash is to use the predefined Debug eNVM build target provided in the lab 8 design files. This will create a binary targeted for the eNVM (i.e. Flash). The modifications I performed were the following:

Use the Debug eNVM build target to create a new binary. Once it succeeds, create a new debug configuration as follows:

After a while, Softconsole will complain that it couldn't insert a hard breakpoint. We are still trying to find out why we can't debug code in the eNVM. It should be possible, and if you find out how to do it, let us know!

In any case, your application should run now. Unplug the board from the USB cables and plug it back it. This will reset the board, and start your application.

Caveates

Static variables, like predefined strings, are not located in memory anymore. Thus, writing into them will most likely throw an exception. Therefore, you will have to manually allocate memory for them using malloc in order to properly use them.

As debugging currently doesn't work, you will have to rely more on printf to find out what's going on in your application, and why things are not working anymore. You might consider to rewrite the HardFaultHandler to output a character on the UART. This will help you to show that you crashed your application.

Measuring Power Draw

To evaluate the effectiveness of your application in conserving energy, you will have to measure the boards power draw. You can use the same setup as used in Lab 1. If you don't remember how it was done, then you can following this direct link: DMM

We measured the power of the code provided for lab 8 in order to give you a sense of how much power your board should draw.

If we don't turn off anything, use the OLED to show the result, and keep the Radio constantly on: 185 mA @ 5 V

If we put the radio into permanent standby, but busy-loop with the CPU: 166.8 mA @ 5 V

If we put the radio into permanent shutdown, but busy-loop with the CPU: 164.2 mA @ 5 V

If we keep the radio permanently ON, but use the WFI instruction between RX or TX (i.e., we wait for a received message, or a timer expires to tell us that we have to transmit): 151 mA @ 5 V

Following is a current trace of the radio receiving a message. Before the message arrives, the CPU is waiting and thus we draw just short of 150 mA. Once the radio starts receiving the message, the CPU starts downloading the message from it and thus the current jumps to 165 mA:

Some Suggestions on Where to Start

From the above measurements, you can see that duty-cycling the radio can conserve another ~20 mA. Thus, with a simple low-power listening scheme as described during class, we expect the power draw to be somewhere around 130 to 140 mA. You should be able to achieve this by using hardware timers to schedule your wakeup and listening periods. A good start would be to read reference 10 of the Additional Material section ("Versatile Low Power Media Access for Wireless Sensor Networks"). Note that you have to be on the University network in order to download the PDF provided on the link. This paper describes a simple low-power listening MAC protocol called B-MAC.

To save even more energy, you can start to shutdown more and more components. Following is a list of things coming to my mind.

Deliverables

Your application should successfully transmit and receive a message between two nodes at least once a second. On average, each node should draw less than the baseline implementation's 151 mA @ 5V.

Write a report explaining the details of your implementation. Mention why you chose your particular approach, and how effective it is. Base your reasoning on numbers measured from your board. For example: If we duty-cycle the radio at 10%, then the average power draw drops to XY mA. Switching from OLED display to LEDs reduces the current draw by XY mA, while reducing visibility, etc. Indicate what you would change or how you could improve your implementation if you had more time.

Submit a compressed file for your SoftConsole workbenches (name it cc2520Workbench_uniquename1_uniquename2.{rar,zip,7z,bz}). In case you modify your FPGA code, add a second compressed file containing the Libero project (name it cc2520Fpga_uniquename1_uniquename2.{rar,zip,7z,bz}) The workbench should be fully configured with build targets and your code should compile. Send all compressed files to eecs373@gmail.com with the subject f10-lab8:uniquename1,uniquename2. Hand in your report during the lab.

Before handing in your report, show your application to a lab staff and get a signature on your title page. We should see the power draw of your application on the DMM. Make sure the staff member puts down the current measurement next to his signature.

We will also have a small competition to see who can get the lowest power number out of their smart fusion boards, while still providing visual feedback and receiving and transmitting. The group with the lowest average power will get +25%, second lowest +10%, and third lowest +5% bonus of their grade for this lab. We will select the three lowest groups based on the numbers measured during your presentation to the staff. We will verify this number during class using precision instruments that record the power draw of the system at 1000 kHz.