Вы находитесь на странице: 1из 87

EmberNet Application Development Guide

Final

120-0065-000A 08 December 2004

Copyright 2002-2004 by Ember Corporation All rights reserved. The information in this document is subject to change without notice. The statements, configurations, technical data, and recommendations in this document are believed to be accurate and reliable but are presented without express or implied warranty. Users must take full responsibility for their applications of any products specified in this document. The information in this document is the property of Ember Corporation. Title, ownership, and all rights in copyrights, patents, trademarks, trade secrets and other intellectual property rights in the Ember Proprietary Products and any copy, portion, or modification thereof, shall not transfer to Purchaser or its customers and shall remain in Ember and its licensors. No source code rights are granted to Purchaser or its customers with respect to all Ember Application Software. Purchaser agrees not to copy, modify, alter, translate, decompile, disassemble, or reverse engineer the Ember Hardware (including without limitation any embedded software) or attempt to disable any security devices or codes incorporated in the Ember Hardware. Purchaser shall not alter, remove, or obscure any printed or displayed legal notices contained on or in the Ember Hardware. EmberNet, Ember Enabled, Ember, and the Ember logo are trademarks of Ember Corporation. All other trademarks are the property of their respective holders.

Contents

About This Document...............................................................................................7


Purpose .........................................................................................................................................7 Audience .......................................................................................................................................7 Getting Help .................................................................................................................................7 Documentation Conventions .......................................................................................................8 .......................................................................................................................................................8

Chapter 1

Introduction to Embedded Networking ..........................................9


Overview ......................................................................................................................................9 How Radios Work .................................................................................................................... 10 Electromagnetic Waves ..................................................................................................... 10 Radio Systems: Transmission, Reception, and Propagation ........................................... 10 Medium Access Control .................................................................................................... 11 How Embedded Mesh Networks Work ................................................................................. 11 Network Location and Association .................................................................................. 11 Route Discovery ................................................................................................................. 11 Message Delivery .............................................................................................................. 12 Types of Embedded Mesh Networking Topologies .............................................................. 12 Further Reading ......................................................................................................................... 13

Chapter 2

Introduction to Embedded Networking ....................................... 14


EmberNet Components ............................................................................................................ 14 Understanding the EmberNet Stack ................................................................................. 14 Understanding the HAL ..................................................................................................... 16 Understanding the Tools ................................................................................................... 16 Further Reading About the EmberNet Stack ................................................................... 17 Network Association, Discovery, and Routing ....................................................................... 17 Network Formation ............................................................................................................ 17 Discovery and Routing ...................................................................................................... 17 Data Addressing and Delivery in Full-Function Devices ........................................................ 22 Addressing .......................................................................................................................... 22

EmberNet Application Development Guide

120-0065-000A Final

Page 3

Binding ................................................................................................................................ 22 Message Delivery .............................................................................................................. 23 Transmitting, Receiving, and Tracking Beacons .............................................................. 24 Data Addressing and Delivery in Leaf Nodes ........................................................................ 25 Addressing .......................................................................................................................... 25 Binding ................................................................................................................................ 25 Delivery of Broadcast, Unicast Messages ....................................................................... 25 Receiving and Tracking Beacons ..................................................................................... 25

Chapter 3

Designing an EmberNet Application............................................ 26


Capturing Application Requirements ...................................................................................... 26 Environmental Requirements ............................................................................................. 26 Device Requirements ......................................................................................................... 27 Traffic Requirements ........................................................................................................... 27 Taking Data off the Network ............................................................................................ 28 Designing an EmberNet Application ...................................................................................... 29 General Design Recommendations .................................................................................. 29 Identify Full-Function and Leaf Node Devices ................................................................. 29 Define Messages ............................................................................................................... 30 Determine Device Binding Requirements ......................................................................... 30 Choose a Network Discovery Method ............................................................................ 31 Determine Endpoints and Interfaces ................................................................................ 31 Define Binding Table Interactions ..................................................................................... 32 Create the Means to Relay Messages to and from Leaf Nodes ................................... 32 Evaluate the Design Against the Requirements ............................................................... 32 Integrate Your Solution with EmberNet ................................................................................... 32 Hardware ........................................................................................................................... 32

Chapter 4

Implementing the Project............................................................... 33


Overview ................................................................................................................................... 33 Basic Template: Full-Function and Leaf Node Devices .......................................................... 34 Header Files ....................................................................................................................... 34 Variables ............................................................................................................................. 35 Initialization Function Calls ............................................................................................... 35 Running the Stack ............................................................................................................... 37 Sending Messages .................................................................................................................... 38 Create Bindings .................................................................................................................. 38 Open a Connection ........................................................................................................... 39 Creating the Message ....................................................................................................... 39 Creating Message Data .................................................................................................... 40 Submit Message to the EmberNet Stack ......................................................................... 42

EmberNet Application Development Guide

120-0065-000A Final

Page 4

Wait for Callback .............................................................................................................. 42 Receiving Messages ................................................................................................................. 42 Create Binding ................................................................................................................... 42 Incoming Message Handler ............................................................................................. 42 Sending and Receiving Beacons ............................................................................................. 45 Sending Beacons ............................................................................................................... 45 Receiving Beacons ............................................................................................................. 46 Tracking Beacons ............................................................................................................... 46 Sleeping and Waking .............................................................................................................. 46 Going to Sleep ................................................................................................................... 46 Waking Up ......................................................................................................................... 46 Callbacks ................................................................................................................................... 47

Chapter 5

Sample Sensor Applications ......................................................... 49


Overview ................................................................................................................................... 50 How the Sample Sensor Application Works .......................................................................... 50 Writing the Main Application Loop ......................................................................................... 51 Initializing the Application ................................................................................................ 51 Associating to the Network ............................................................................................... 52 Initializing Application Functions ...................................................................................... 53 Writing the Event Loop ...................................................................................................... 53 Establishing Interfaces and Endpoints ..................................................................................... 53 Declaring Interfaces ........................................................................................................... 53 Declaring Endpoints ........................................................................................................... 54 Binding Devices Together ......................................................................................................... 55 Commissioning the Network .................................................................................................... 56 Sending and Receiving Messages .......................................................................................... 56 Sending Multicasts ............................................................................................................. 56 Receiving Messages .......................................................................................................... 57 Setting the Binding ............................................................................................................. 58 Sending Datagrams ........................................................................................................... 59 Leaf Node Sample Sensor Application .................................................................................. 62 Design of the Leaf Node Sensor Sample Application .................................................... 62 Leaf Node Development ................................................................................................... 64 Leaf Node Initialization and Startup ................................................................................ 64 Leaf Node Network Acquisition ....................................................................................... 65 Routing from a Leaf Node Device .................................................................................... 69 Routing to a Leaf Node Device ........................................................................................ 72 Beacons .............................................................................................................................. 73 Battery Life .......................................................................................................................... 73

EmberNet Application Development Guide

120-0065-000A Final

Page 5

Chapter 6

Developing Applications ............................................................... 74


Development Overview ............................................................................................................ 74 Developing Full-Function Device Applications ................................................................ 74 Developing Leaf Node Applications ................................................................................ 75 Building Applications ................................................................................................................ 75 About IAR Embedded Workbench .................................................................................. 75 Creating an IAR Workspace File from the Application Template File .......................... 75 Familiarizing Yourself with the IAR Embedded Workbench .......................................... 76 Building with the Debug Version of the EmberNet Stack ............................................... 76 Building with the Release Version of the EmberNet Stack ............................................. 77 Building for the Atmega64 ................................................................................................ 77 Building with the EmberNet Leaf Stack ............................................................................ 77 Debugging Applications ........................................................................................................... 77 Adding Debug Features to an Application ...................................................................... 78 Viewing Application Debug Messages ........................................................................... 78 Viewing Debug Messages Via the Serial Port ................................................................ 80 Using the Ember Studio Backchannel Debug Tools ....................................................... 80 Uploading Applications ........................................................................................................... 81 Choosing the Correct Upload Method for an Application ............................................ 81 Uploading Via Ember Studio ............................................................................................ 81 Uploading Via the Ember Development Board Serial Line Connection ....................... 81

Appendix A Creating a .ebin File....................................................................... 86

EmberNet Application Development Guide

120-0065-000A Final

Page 6

About This Document

Purpose. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Getting Help. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Documentation Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Purpose
This document describes how to design and implement a project using Ember software. In addition, it also contains introductory information on radio propagation and embedded mesh networking topologies and details on networking that are important for understanding how the system functions and making the correct design decisions. We recommend that you read this document from beginning to end, because later chapters rely on the information in previous chapters. You can then refer to specific chapters as necessary during your development process.

Audience
This document is intended for project managers and for embedded software engineers who are responsible for building a successful embedded mesh networking solution using Ember's radio, networking stack, and tools. This document assumes that the reader has a solid understanding of embedded systems design and programming in the C language. Experience with networking and radio frequency systems is useful but not expected.

Getting Help
If you have any questions about how to developing Ember applications, please contact your Ember account representative: United States 343 Congress Street Boston, MA 02210 Telephone: +1 617-951-0200 Fax:+1 617-951-0999 Email: support@ember.com

EmberNet Application Development Guide

120-0065-000A Final

Page 7

Documentation Conventions Europe Unit 29 Science Park, Milton Road Cambridge CB4 0DW, UK Telephone: +44 (0) 1223 423322 Fax: +44 (0) 1223 423390 Email: support@ember.com The Ember website contains information about the full range of Ember products and services and allows you to sign up for the support section of the site: http://www.ember.com

Documentation Conventions
Notation
Italics UPPERCASE Right-angle bracket (>) Courier

Meaning
Identifies on-screen software menu options. Identifies a keyboard key. Delimits a series of software menu options to be clicked. Identifies software code and, in body text, variables.

Example
Refresh Screen ENTER Open > Save void Main(String[] argv) the buffer variable

EmberNet Application Development Guide

120-0065-000A Final

Page 8

CHAPTER 1

Introduction to Embedded Networking

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 How Radios Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Electromagnetic Waves. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Radio Systems: Transmission, Reception, and Propagation . . . . . . . . . 10 Medium Access Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 How Embedded Mesh Networks Work . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Network Location and Association . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Route Discovery. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Message Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Types of Embedded Mesh Networking Topologies . . . . . . . . . . . . . . . . . . 12 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Overview
Embedded networking is the solution for low-cost, low-power devices that need to communicate among themselves and with the outside world. The successful embedded networking solution must be easy to install, provide robust communication, be capable of supporting battery-operated nodes for more than a year, and have a low enough cost to be added to an already low-cost manufactured device, such as a thermostat. Meeting all of these requirements in one solution is not easy, and many past attempts have fallen short of the mark. The simplest and least-expensive approach is point-to-point wireless, but successful deployment often requires a time-consuming and expensive radio site-survey. More expensive radios can mitigate this problem, but this limits the market to higher cost, AC-powered applications. Embedded mesh networking allows inexpensive radios to relay information through each other, providing a robust communications channel and allowing deployment without a site-survey. Battery-operated nodes in such networks can last up to several years, depending on the application design. As the radio, networking software, and application framework become more and more integrated, these solutions will become even more power-efficient and even lower in cost. To meet these needs, Ember offers an industrial-strength embedded mesh networking algorithm combined with high-performance radios. Our whole-system approach allows us to offer customers a single point of contact for their embedded networking system design, implementation,

EmberNet Application Development Guide

120-0065-000A Final

Page 9

Chapter 1: Introduction to Embedded Networking

How Radios Work

and deployment needs, and also allows us to continue to develop the state of the art in all areas, to offer the best solution possible into the future.

How Radios Work


This introduction provides a basic understanding of how radio frequency systems work. Only the concepts most relevant to working with Embers technology are discussed. Readers already familiar with these topics are encouraged to review more comprehensive treatments of the topic (see Further Reading on page 13).

Electromagnetic Waves
A radio wave is an electromagnetic (EM) wave that travels at the speed of light from its source in all directions simultaneously. The wave has both an electrical wave component (E) and a magnetic wave component (M) that are perpendicular both to each other and the direction of travel. For our purposes, EM waves can be described by two main properties: the frequency of the wave and its intensity, or power. The frequency of a wave is measured in hertz (cycles per second) and indicates the amount of time required for the wave to return to its starting position. The frequency of a wave is inversely proportional to its wavelength, a feature that is important for understanding antenna design and placement. The power of a wave is measured in milliwatts (mW) or decibels per milliwatt (dBm) and indicates how much energy it contains. An EM wave that you are familiar with is visible light. Different frequencies of visible light produce different colors, and different powers of visible light are clearly perceived as differences in intensity or brightness. Radio waves function in much the same way, although they use a much lower frequency that is not perceived by the human eye. The power of a wave diminishes as its distance from the source increases, but it is safe to assume that in most embedded networking situations, the waves frequency will remain the same.

Radio Systems: Transmission, Reception, and Propagation


A radio system generates a radio frequency (RF) signal with some information encoded into it at the transmitter and expects to receive the RF signal and decode the same information at the receiver. The receiver must be listening at the same frequency (that is, channel) as the generated RF signal in order to hear it. The effectiveness of this simple system is related to how often the signal reliably travels from transmitter to receiver. Two factors principally determine system effectiveness: How loudly the signal is heard at the receiver. Whether the receiver can decipher the signal it has heard. The human sense of hearing is a good model for how this works. If a man speaks very softly from a long distance, you may hear his voice but be unable to decipher his words. The same man speaking loudly or from a shorter distance will be heard more easily. Similarly, if the man is speaking from the other side of a glass window, his words may be harder to understand. In like manner, RF signals are affected by increased distance, decreased transmission power, and items blocking the path of transmission. Some factors affect RF signals more than others. Metal, for example, always absorbs some signal. At 2.4GHz, water absorbs some of the signal. In general, higher frequency RF signals are subject to more reflection, refraction, and absorption in the environment than lower frequency RF signals. Other factors that affect successful reception of a radio signal, including modulation method, interference, multipath, and noise floor, are beyond the scope of the document.

EmberNet Application Development Guide

120-0065-000A Final

Page 10

Chapter 1: Introduction to Embedded Networking

How Embedded Mesh Networks Work

Medium Access Control


Generally, the Medium Access Control (MAC) layer allows multiple devices to use the transmission medium. For this reason, it is also sometimes referred to as Multiple Access Control. This can be achieved in a variety of ways, descriptions of which are beyond the scope of this document. The IEEE 802.15.4 standard specifies the use of a CSMA/CA (carrier-sense multiple access / collision avoidance) mechanism to allow multiple radios to access the same channel. This mechanism may be simply described as follows: Listen first to see if someone else is talking. If yes, then wait a little bit and try again. If no, send your message. This mechanism avoids many collisions but not all of them. It also cannot detect when a collision has occurred. For both of these reasons, Ember uses additional collision-coping mechanisms on individual link communications as well as end-to-end acknowledgements to ensure that a sending device receives indication that a message was received at the final destination.

How Embedded Mesh Networks Work


Embedded mesh networks make radio systems more reliable by allowing radios to relay messages for other radios. If a transmission from A to B cannot be heard, the embedded mesh network can relay the message to B through an available intermediate node C. To truly address the low-cost, high-volume markets, an embedded mesh network must be self-configuring. That is, a human installer or maintenance crew must not be required to inform the network about available paths. The network must determine this information for itself and continue to update this information as conditions change.

Network Location and Association


If a node wishes to communicate, it must first locate a network. All nodes participating in the same network must speak and listen on the same frequency (that is, channel). This means that to find a network, a node must search on the possible channels for that network. Several different ways to search are explored in more detail in Chapter 4, Implementing the Project. EmberNet also makes use of the concept of a personal area network identifier, or PAN ID. The PAN ID provides a way for two networks to exist on the same channel while still maintaining separate traffic flow. Although the packets from one network will not present themselves to the application on another network, be aware that two networks operating in the same channel with different PAN IDs must share the local radio bandwidth. A node may also decide to start its own network. The procedure for doing this varies depending on the implementation of the networking software. Once a node has found the appropriate channel, it must join the network. It uses a simple association mechanism for joining: Simply sending and receiving on the same channel and with the same PAN ID as an existing network is sufficient to constitute joining the network. However, this can be controlled at the application level to only allow known devices to join the network.

Route Discovery
The network is responsible for discovering and maintaining available routes so that the application does not need to know anything about the underlying routes to deliver a message to a destination node. The way this is handled varies among networks and routing mechanisms. The two main approaches are on-demand route discovery and active route discovery. Active route discovery attempts to keep certain routes up to date at all times. This consumes additional network overhead but means that the

EmberNet Application Development Guide

120-0065-000A Final

Page 11

Chapter 1: Introduction to Embedded Networking

Types of Embedded Mesh Networking Topologies

routes are available immediately when a node wishes to send data. On-demand route discovery creates less overhead network traffic but may incur a delay when a route has changed because of shifting RF conditions or network rearrangements.

Message Delivery
Once one or more viable routes have been discovered, the network must deliver the message using one or more of these routes. The information about the routes can be next-hop, where either the message or the node knows what the next hop should be, or it can be distributed, where the nexthop is decided dynamically depending on which nodes hear the message. Next-hop delivery can be made very bandwidth efficient, since only the node elected to be the next hop will re-transmit the message. Distributed delivery, however, will recover from intermittent failures much more quickly, since the next hop is chosen dynamically. AODV (ad hoc, on-demand, distance-vector routing) is one common type of a next-hop routing system, whereas Ember's GRAdient routing is a distributed delivery system. More information about distributed delivery can be found in Chapter 2, Introduction to Embedded Networking.

Types of Embedded Mesh Networking Topologies


Four topologies can be formed with mesh networking: star, tree, full mesh, and hybrid mesh (Figure 1-1). Star network: One hub is the central point of all communications. The hub can become bottlenecked with network/processing bandwidth, but behavior is fairly deterministic. This topology is not very mesh-like, and transmission is limited by the communication radius of the hub. Outlying nodes are commonly battery powered. Tree topology: A rigid hierarchical structure is formed from a central root node. A tree topology provides for controlled network growth but may not provide the most direct routing path for messages. It also scales poorly.

Figure 1-1: Four network topologies Tree Topology Star Topology

Full Mesh Topology

Hybrid Mesh Topology

EmberNet Application Development Guide

120-0065-000A Final

Page 12

Chapter 1: Introduction to Embedded Networking

Further Reading

Full mesh network: All nodes relay messages and can be in communication with one another. Traffic is distributed between several senders and receivers. Nodes can share information with one another, allowing an application designer to create a system of distributed intelligence. This topology is not very deterministic. There are no obvious bottlenecks and information is easy to share, but it is harder to troubleshoot and predict. Hybrid network: This topology combines the star and mesh strategies. Several star networks exist, but their hubs can communicate as a mesh network. A hybrid network allows for longer distance communication than a star topology and more capability for hierarchical design that a mesh topology. The choice of a topology should be based on the network design and individual devices and the expected data flow within the system. Leaf or reduced function nodes (that is, non-routing nodes) are used in many of these topologies to reduce cost and power requirements.

Further Reading
For in-depth information on the topics covered in this chapter, we recommend the following resources: IEEE 802.15.4 specification http://electronics.howstuffworks.com/radio.htm

EmberNet Application Development Guide

120-0065-000A Final

Page 13

CHAPTER 2

Introduction to Embedded Networking

EmberNet Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Understanding the EmberNet Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Understanding the HAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Understanding the Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Further Reading About the EmberNet Stack. . . . . . . . . . . . . . . . . . . . . 17 Network Association, Discovery, and Routing. . . . . . . . . . . . . . . . . . . . . . . 17 Network Formation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Discovery and Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Data Addressing and Delivery in Full-Function Devices. . . . . . . . . . . . . . . . 22 Addressing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Message Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Transmitting, Receiving, and Tracking Beacons . . . . . . . . . . . . . . . . . . 24 Data Addressing and Delivery in Leaf Nodes . . . . . . . . . . . . . . . . . . . . . . . 25 Addressing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Delivery of Broadcast, Unicast Messages . . . . . . . . . . . . . . . . . . . . . . 25 Receiving and Tracking Beacons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

EmberNet Components
EmberNet's software consists of three main components: the stack, the HAL, and tools, both embedded and PC-based (Figure 2-1).

Understanding the EmberNet Stack


The EmberNet stack provides the API and compiled library code for the EmberNet mesh networking solution. The stack is available in two configurations: a full-functionality stack and a reduced-functionality stack. The developer must choose the one that is appropriate for each device in the application.

EmberNet Application Development Guide

120-0065-000A Final

Page 14

Chapter 2: Introduction to Embedded Networking

EmberNet Components

Figure 2-1: Schematic of the EmberNet stack

The full-functionality stack provides complete mesh networking behavior, using Embers GRAdient routing algorithm. The application interacts with a comprehensive message transport layer that provides targeted broadcast messages (which Ember calls multicast messages) and end-to-end acknowledged unicast messages. The stack controls and automates route discovery and message delivery. For a detailed description of the EmberNet messaging API, see the EmberNet Stack Interface Guide. The full-functionality stack can also be configured to send one-hop beacons, either periodically at regular intervals or as unrelated messages. Beacons can be used to coordinate network activity and to announce network resource availability to other full-function devices and to leaf node devices. The full-functionality stack also provides a simple memory management system via data structures called message buffers, which the stack uses as temporary storage for incoming messages, outgoing messages, and messages being routed for other nodes. The application can also use these message buffers for its own dynamic information, if that is useful. Full-function devices form the routing backbone of an embedded mesh network. To do this, they perform some additional under-the-hood network maintenance, such as keeping track of nearby neighbors and the relative radio link quality heard from those neighbors. This imposes two restrictions on the use of full-function devices (which are not imposed on leaf nodes): They must be on at all times when the network is functioning, and they should not move quickly relative to one another. In general, a full-function device is not a suitable choice for a battery-powered node. It cannot always sleep immediately because its routing responsibilities are not deterministic, and it cannot wake instantaneously because it requires time (a small but significant amount when battery life is a concern) to gather local network information before it can send and receive messages. The reduced-functionality stack (that is, the leaf node stack) provides a significantly reduced feature set that enables the entire program to fit on a much smaller (16k flash) processor. The reduced feature set provides only point-to-point and point-to-multipoint data transmission within a single hop, and it does not route messages for other nodes. Using reduced-function nodes creates a EmberNet Application Development Guide 120-0065-000A Final Page 15

Chapter 2: Introduction to Embedded Networking

EmberNet Components

hybrid mesh topology (Figure 1-1). It also removes features (such as message buffers) that add to the RAM and FLASH overhead but are not strictly necessary for a smaller device. For a complete API description, see the Leaf Node Stack Interface Guide. Because leaf nodes have no relaying or routing responsibilities, they can be put to sleep quickly for long periods of time and woken up quickly, which makes them an effective choice for batterypowered nodes. Their transient nature in the network also makes them suitable for mobile applications.

Understanding the HAL


The HAL provides a thin layer between the EmberNet stack and the microprocessor and boardlevel peripherals that the stack and higher-level applications rely on. It is provided in source code format to allow you to modify it to suit your projects needs and available resources. The HAL provides both board-level and microprocessor-level functionality. The board-level functionality is contained in the hal/board directory and is designed to be modified by customers using the Ember reference design but with slightly different board configurations (for example, different pinouts). The microprocessor level functionality can be modified by developers who need need to alter how the Ember stack uses the microprocessor peripherals (for example, to use different timers or interrupts).

Understanding the Tools


Ember provides tools to help with development, manufacturing, and deployment.

Ember Studio
Ember Studio provides basic network monitoring and debug information to assist in the development of embedded applications. Ember Studio can be used with Ember development boards to provide an easy-to-use network for development and testing of an embedded application prior to deployment on customer specific hardware. For a full description of Ember Studios functionality and use, see the Ember Studio Users Guide.

Serial and ADC Drivers


Embedded source code such as the serial drivers and analog-to-digital converter drivers are provided in C. These drivers allow you to quickly incorporate standard functionality into a custom application. For more information on these drivers, see the Hardware Abstraction Layer Interface Guide.

Bootloader
The Ember over-the-air bootloader allows the system to upgrade its own software, either via an RS-232 serial link or over a single-hop radio connection. This can be used to speed the development process and also to make units field-upgradeable, which is often an important concern when deploying long-term installations. Because of the small flash size and limited microprocessor supported bootload area, bootloader support is not available for nodes implemented using the Leaf Node stack.

Rangetest
Embers rangetest application provides low-level control of the radio and can be used to verify proper functionality after manufacturing, characterize radio performance, set manufacturing parameters (that is, tokens), and control the radio properly for the certification process required by

EmberNet Application Development Guide

120-0065-000A Final

Page 16

Chapter 2: Introduction to Embedded Networking

Network Association, Discovery, and Routing

many countries. For information on using the rangetest application, see Application Note 5001, Bringing Up Custom Nodes.

Remote Network Access Protocol II (RNAP II)


RNAP II is a software program and a serial protocol for use between an EmberNet node and a larger host processor. It allows the host processor to perform memory-related services for a gateway node, such as storing routes and destinations. RNAP II is intended for aggregation applications (large sensor networks where most data is flowing to a centrally defined aggregator) in which the gateway node periodically receives data from a large number of network nodes and must occasionally send data back to them. For a complete description of the RNAP II software, see the RNAP II Interface Guide.

Further Reading About the EmberNet Stack


For in-depth information about the EmberNet stack, we recommend the following resources: The following EmberNet stack files: The files in the board/dev directory (specifics of the board interface) micro.c / micro.h (specifics on the microprocessor interface and pin definitions) serial.h (serial port information) adc.h (ADC interface information) The header files in the stack/include directory (general API information) The RNAP II Interface Guide

Network Association, Discovery, and Routing


Network Formation
In EmberNet stack versions earlier than the 3.3 version, nodes could associate with a particular network simply by changing their channel to be on the channel of the network. In version 3.3 and later of the EmberNet stack, the emberAssociate() function call handles the association process, using the appropriate PAN ID and radio channel. In both cases, there is no authorization procedure for joining a network. All new full-function nodes join as peers of the existing nodes. An authorization process can be established using a coordinator at the application level if desired for system operation, but this is not required for EmberNet operations.

Discovery and Routing


For a device to send a message to another device within the network, it must know the cost of sending the message to this device. This cost is established during a discovery process. The cost determined in this discovery is then used to route the message to be sent. The following series of figures illustrates a device sending a broadcast to find another node. All nodes forward this broadcast, and the cost of the route is recorded until it reaches the destination node. The destination node then sends a response that also records the route costs back to the source. Once this is completed, the source and destination can exchange messages.

EmberNet Application Development Guide

120-0065-000A Final

Page 17

Chapter 2: Introduction to Embedded Networking

Network Association, Discovery, and Routing

Figure 2-2: Node 2 has a message for node 6, but before it can send the message, it must discover node 6 in the network.

Figure 2-3: Node 2 broadcasts a discovery message, looking for node 6.

EmberNet Application Development Guide

120-0065-000A Final

Page 18

Chapter 2: Introduction to Embedded Networking

Network Association, Discovery, and Routing

Figure 2-4: Nodes 4 and 5 forward the broadcast.

Figure 2-5: All nodes now all have the cost for sending to node 2.

EmberNet Application Development Guide

120-0065-000A Final

Page 19

Chapter 2: Introduction to Embedded Networking

Network Association, Discovery, and Routing

Figure 2-6: Node 6 acknowledges node 2's request.

Figure 2-7: Nodes now update with the cost to send to node 6.

EmberNet Application Development Guide

120-0065-000A Final

Page 20

Chapter 2: Introduction to Embedded Networking

Network Association, Discovery, and Routing

Figure 2-8: Node 2 can now send a message to node 6 with node 5 acting as a relay.

Figure 2-9: Node 5 relays the message to node 6.

EmberNet Application Development Guide

120-0065-000A Final

Page 21

Chapter 2: Introduction to Embedded Networking

Data Addressing and Delivery in Full-Function Devices

Data Addressing and Delivery in Full-Function Devices


Full-function devices are all full participants in the mesh network As such, they can send and receive multicast messages to multicast groups they have subscribed to, and they can send and receive unicast messages to any other full-function device in the network. Additionally, the default behavior of full-function devices is to relay messages for other nodes in the network when necessary.

Addressing
Every Ember node has a 64-bit IEEE address that is assigned at manufacturing time and never changes. Because these addresses are allocated by the IEEE, no two devices should ever have the same 64-bit address. This allows the networking system to uniquely address a particular device. Ember supplies IEEE 64-bit addresses with each chip to developers who need them. Companies may also choose to acquire their own block of addresses from IEEE. To avoid sending 64-bit addresses around the network with every message, which would consume significant bandwidth, the network negotiates a 16-bit address that is unique within the network. In EmberNet this 16-bit address is dynamically allocated, and conflicts are resolved internally to the networking software. Because the 16-bit address may change during device operation in the network, this address is not exposed to the application layer. All application-level addressing uses the 64-bit IEEE address or a multicast group address. EmberNet devices can also subscribe to any number of multicast groups. A multicast group has a 16-bit identifier and allows messages to be sent to multiple devices simultaneously (see Message Delivery on page 23). In addition to the main address (either a 64-bit IEEE address or a multicast group), messages are sent to a specific endpoint and interface pair. The endpoint/interface combination specifies an additional destination within the targeted device and is delivered as a parameter to the device's incoming message handler. Readers familiar with UDP or TCP can think of this as analogous to a UDP or TCP port. Endpoints and interfaces are configured at compile-time and are explained in more detail in the implementation section.

Binding
Each device maintains a binding table with a configurable number of entries. Each entry is either a multicast binding or a unicast binding. A multicast binding allows the device to hear multicast messages sent to the specified multicast identifier. It also allows the device to send messages to other nodes that also provide a binding to that multicast identifier. A unicast binding allows the device to send messages to the IEEE address specified in the binding.

Note: A device will receive unicast messages to its address even if no binding is present.
As of version 3.3 of the EmberNet stack, a special binding is supported to send messages to a local leaf node. Except for the binding type, these bindings are identical to unicast bindings. A binding table is used to identify required information about a device in the network with which the existing device will exchange messages. Each EmberNet binding is bidirectional in that messages can be sent and received. The binding table provides the mechanism for virtually joining discrete elements such as a wall switch and three overhead lights, so that any message created for a change of state at the switch is then sent to the appropriate lights.

EmberNet Application Development Guide

120-0065-000A Final

Page 22

Chapter 2: Introduction to Embedded Networking

Data Addressing and Delivery in Full-Function Devices

Message Delivery
For this discussion, the word message will refer to a single packet that is sent over the radio. Different transmission types have different maximum sizes. For example, a multicast message can be larger than a unicast message. When more data needs to be sent, it will need to be sent in multiple messages. All messages must be put into a message buffer, which is requested by the application from the stack. Once the message is constructed in or copied into a message buffer, it can be sent. Messages are always sent to a particular binding table entry. Messages sent to a unicast binding table entry must be sent using emberSendDatagram() or emberSendSequenced(), and messages sent to a multicast binding must be sent using emberSendMulticast() or emberSendLimitedMulticast(). The appropriate function will return EMBER_SUCCESS to indicate that no errors were detected in the form of the message or the destination binding and that the message has been accepted for delivery by the stack. It does not necessarily indicate that the message has reached its destination, or even that it has been sent.

Sending a Datagram
A datagram is a sent without any coordination between the sender and the recipient. For each message that receives an EMBER_SUCCESS result code from emberSendDatagram(), the callback emberMessageSent() will be called to indicate success or failure of the transmission. An EMBER_SUCCESS call to emberMessageSent() indicates that the message was received by the destination node and that the destination node was able to send an acknowledgement to the sender.

Note: A call to emberMessageSent() with an unsuccessful result code does not guarantee
that the recipient did not receive the message. It only guarantees that the acknowledgement did not reach the sender before the timeout period. If the acknowledgement is not received within 1.2 seconds, the datagram will be retried. Each datagram will be retried three times before a failure is indicated. Note that due to this retry mechanism, duplicate messages may occasionally be received by the destination node, and messages that are sent simultaneously (without first waiting for emberMessageSent() to be called back) may arrive in an order different from the one in which they were sent. Applications must accommodate this behavior or use sequenced messages.

Sending a Sequenced Message


Sequenced messages are very similar to datagrams, except that the sender and recipient exchange messages during the emberOpenConnection() process that allows them to guarantee in-order delivery and eliminate duplicates. Each sequenced message is still sent with an end-to-end acknowledgement, but a unique number is added to each message that indicates its place in the sequence, allowing the stack to automatically discard duplicate messages and buffer and resequence out-of-order messages. Note that the application must still be responsible for not sending duplicate messages itself. This mechanism only works with messages that are submitted for delivery once. Further, communication failures may still result in a message being heard at the destination but the sender being informed of a failed delivery. Applications that are extremely sensitive to duplicate messages must take additional measures to prevent them.

EmberNet Application Development Guide

120-0065-000A Final

Page 23

Chapter 2: Introduction to Embedded Networking

Data Addressing and Delivery in Full-Function Devices

Sequenced messages may be sent after the emberConnectionStatusHandler() is called, indicating that the requested connection has been opened. A connection is always bidirectional, meaning that only one side needs to request that it be opened. As with datagrams, emberMessageSent() is always called back after each successful submission. If a message fails after the transport level retries, the connection is considered closed, and the emberConnectionStatusHandler() is called to indicate this new state.

Sending a Multicast Message


When a multicast message is sent, it is broadcast to the entire network, although the number of hops that a message propagates can be limited by using emberSendLimitedMulticast(). Only nodes that have subscribed to the same multicast identifier will receive the message. Multicast messages are not acknowledged, and emberMessageSent() will not be called to indicate a successful transmission. Multicast messages are still extremely robust. Each multicast message is sent three times by each node along the relay path. This uses a large amount of network bandwidth and should therefore be used sparingly. See the section on designing your solution for ideas that will reduce the need for multicasts.

Sending a Reply to a Message (Unicast Messages Only)


By using emberSendReply(), applications can piggy-back their own message on the acknowledgement that the transport layer sends to indicate that it has successfully received a message. To avoid the pathological situation of acknowledging and acknowledgement, messages sent using emberSendReply() are not acknowledged by the recipient and do not generate an emberMessageSent() callback.

Sending a Message to a Leaf Node


As of version 3.3 of the EmberNet stack, full-function nodes can send messages to leaf nodes. Messages are sent to leaf nodes using emberSendDatagram(), and accepted messages will result in a call to emberMessageSent() in the same way expected with normal messages. Specifically, if the destination node is no longer in range or if its radio is asleep, emberMessageSent() will not return success. These link-level messages will not be relayed by any surrounding nodes.

Transmitting, Receiving, and Tracking Beacons


Full-function devices can choose to transmit beacons, either at regular intervals or in a one-at-atime mode. Beacons are sent without using the CSMA/CA MAC mechanism (see Medium Access Control on page 11). This means that they require extra care to avoid upsetting the rest of the networking. Specifically, when operating in a beaconed network, all devices that are not transmitting a beacon must track any periodic beacons that are in-range. When the beacon is tracked, the stack will know how to avoid transmitting messages that will collide with the beacon. A practical limitation that this imposes is that only one node in a local vicinity can be beaconing. Two nodes that are beaconing have no mechanism for avoiding each other, and any node that can hear both beacons has no way to track them both at once. Beacons can be sent with a very high frequency, but application developers should be aware that this will consume a large amount of local bandwidth and that the size of the beacon data will affect the bandwidth usage.

EmberNet Application Development Guide

120-0065-000A Final

Page 24

Chapter 2: Introduction to Embedded Networking

Data Addressing and Delivery in Leaf Nodes

Data Addressing and Delivery in Leaf Nodes


Addressing
Leaf nodes are not full participants in the mesh network; therefore, they have no 16-bit network address. Leaf nodes are addressed using their unique 64-bit IEEE address, and they send to fullfunction devices using the 64-bit IEEE address of the destination.

Binding
To save memory and code size, the leaf node does not have a binding table. Instead, it specifies the recipients 64-bit IEEE address directly when requesting message transmission.

Delivery of Broadcast, Unicast Messages


When the leaf sends a unicast message, it will receive a callback to emberMessageSent() that indicates proper delivery. The leaf stack will retry delivery of a failed message, but these retries are done at the MAC level and not with the longer backoffs associated with the transport layer on fullfunction devices.

Receiving and Tracking Beacons


Leaf nodes can receive beacons from full-function devices. In many cases, this is used by a mobile leaf node to learn which network (or which area of a network) is nearby, and then to detect when it has left the network.

Note: If the leaf nodes in a system are configured to transmit messages in response to receiving a
beacon, this can result in an unintended synchronization of messages when all leaf nodes in the range of a single beacon attempt to respond simultaneously. This may result in an undesirably high number of collisions unless the application provides a random backoff from the beacon prior to transmitting a message.

EmberNet Application Development Guide

120-0065-000A Final

Page 25

CHAPTER 3

Designing an EmberNet Application

Capturing Application Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Environmental Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Device Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Traffic Requirements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Taking Data off the Network. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Designing an EmberNet Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 General Design Recommendations. . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Identify Full-Function and Leaf Node Devices. . . . . . . . . . . . . . . . . . . . 29 Define Messages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Determine Device Binding Requirements . . . . . . . . . . . . . . . . . . . . . . . 30 Choose a Network Discovery Method . . . . . . . . . . . . . . . . . . . . . . . . . 31 Determine Endpoints and Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Define Binding Table Interactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Create the Means to Relay Messages to and from Leaf Nodes . . . . . 32 Evaluate the Design Against the Requirements . . . . . . . . . . . . . . . . . . . 32 Integrate Your Solution with EmberNet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

Capturing Application Requirements


Application requirements can be broken into four categories: environmental requirements, traffic requirements, device requirements, and taking data off the network.

Environmental Requirements
The easiest requirements to articulate are the following environmental ones: Location: Are the nodes primarily indoors or outdoors? Physical environment: What are the likely physical obstacles? Pay specific attention to metal items and, when using 2.4GHz, items containing much water. Dont forget the device packaging and any mounting hardware. The occasional small metal or water-bearing object is

EmberNet Application Development Guide

120-0065-000A Final

Page 26

Chapter 3: Designing an EmberNet Application

Capturing Application Requirements

not likely to pose a problem, but clusters of such objects or large instances of them may. Dont forget the device packaging and any mounting hardware. Expected range: For the expected location and physical environment, what range between devices is necessary? Can relay nodes be added if needed? The device layout needs to support enough nodes in proximity to each other to create a mesh (each node should have at least two neighbors). Node access once installed: Does the design incorporate field-upgrading of nodes? What upgrading method will be used (for example, over the air or via Ethernet)? Are any of the nodes inaccessible for the chosen upgrading method?

Device Requirements
Device requirements should be familiar to designers accustomed to standard embedded design. Because the stack and the application will be deeply integrated, it is important to pay attention to both what the application needs and what the application leaves available for the stack. Interrupt latencies: What are the minimum interrupt latencies required by your program, and what is the maximum duration of critical sections (that is, sections where interrupts are disabled) in your application? MCU utilization: Other than interrupts, what is the anticipated percentage of MCU time required by your application? A rough estimate is fine, because the amount of MCU time required by the stack is dependent on the traffic requirements. Primarily, this is a checkbox item to help guarantee that there is some processor time available for the network. MCU memory utilization: What is the estimated FLASH and RAM usage of your application? This is likely to be of most concern for complicated applications and for applications that are using the leaf node stack with a smaller, less expensive microprocessor such as the ATmega16L. Also worth considering are EEPROM requirements. Although the stack uses very little, it does consume some. MCU peripherals: What internal peripherals will your application make use of? Pay special attention to timers, as the stack does make use of timers in various ways. What MCU pins will need to be used to control external peripherals? The timers, pins, and most other peripherals used by the stack can be modified within the HAL. A few, like the SPI port, are used exclusively by the stack. Consider the UART and other peripherals that are likely to generate a large number of interrupts; these will affect the interrupt latencies above. Mobility: Are any of the nodes mobile? How quickly will they be moving? How quickly must they repair routes that have been changed by their movement? How quickly must they discover a new network upon entering its coverage area? Battery operation: Do any of the nodes need to be battery operated? What is the capacity (mA*H or equivalent) and peak current of the batteries under consideration? How long must they last before requiring recharging or replacement of batteries? Packaging: What is the anticipated packaging of the device, and what external access is available for debug? Although these factors primarily affect RF design (especially antenna design and placement), the embedded software developer should keep them in mind because they may affect the available choices for MCU peripherals. In addition, building devices without at least test points for providing debug output makes application troubleshooting difficult.

Traffic Requirements
Each deployment of an application will be slightly different, making it impossible to predict exact layouts, traffic patterns, and reliability requirements. Nevertheless, because the assumptions made in this stage will influence many later design decisions, it is important to get the best understanding

EmberNet Application Development Guide

120-0065-000A Final

Page 27

Chapter 3: Designing an EmberNet Application

Capturing Application Requirements

possible. Usually this means making assumptions about standard operating environments, device placement, and usage patterns. We recommend that you document these assumptions so that you can later assess their consistency with real-world field trials and deployment. The primary result of analyzing the traffic requirements is a map of the traffic flow. Layout: What are the anticipated physical layouts of the devices in the network? This may be impossible to fully capture, but choose the likely configurations (and perhaps one or two boundary cases) and use them for the design. Does the layout provide for formation of a mesh network, or are there many single paths for failure? What can be done to eliminate single-path connections? Traffic patterns: What devices are sending data to which other devices? Try to recognize general patterns. For example, is most data flowing to one or more central collection points, or is it locally concentrated? Or a combination of the two? Range: Within the anticipated traffic patterns, what is the maximum range required (without a repeater node) between any two devices? Bandwidth: How much data is being sent, and at what rate? Pay attention to how bandwidth requirements increase as multiple nodes send along the same pathway. Put this information together with traffic patterns to determine the likely high-bandwidth pathways. For a first pass, it is sufficient to concentrate on high-bandwidth paths. Latency: What are the required latency times for messages? As with bandwidth, assess this against the traffic patterns. For a first pass, it is sufficient to concentrate on the messages that require the swiftest transmission (that is, those with the lowest latency requirements). Reliability: A realistic embedded design accounts for anticipated failure modes, their acceptable rate of occurrence, and acceptable recovery mechanisms. When designing an embedded mesh network design, the case of the failure of one or more crucial routes must be considered. Such failures persist long enough to result in the stacks informing the application that delivery is not possible. By contrast, failure of a single route is much less serious because the mesh network automatically detects and corrects for the failure. A crucial route may fail because of the failure of critical nodes in the delivery path, obstacles, or persistent interference. Appropriate recovery mechanisms are application-specific. In some applications (for example, long-term, low-data-rate sensor networks) transmission latency is not important, and messages can be cached for a very long time. In other applications, a fast higher-level failure notice or alert is important. Reliability requirements can be effectively captured by accounting for two component requirements: What is the maximum number of acceptable missed messages per relevant unit of time, and how long can messages be cached by the sending application for later delivery before they are considered lost?

Taking Data off the Network


Depending on the application, data either flows within the network, enabling decision making between embedded devices, or flows off the network. Normally, data flows off a network at a gateway-type device. This gateway provides a bridge between the small embedded processors and a larger processor or a PC. In general, on the embedded processor of the gateway device, all data is sent via a UART to some other processor. The gateway device requires special consideration because it can become the largest traffic point in the network, and it shares time between handling radio interrupts for EmberNet traffic and serial/UART interrupts for moving data on and off the network. For large networks that aggregate data, Ember provides the Remote Network Access Protocol II (RNAP II) for use in abstracting some of the memory-intensive operations off the small embedded processor and up to a host processor. This allows a network to scale larger, without being limited EmberNet Application Development Guide 120-0065-000A Final Page 28

Chapter 3: Designing an EmberNet Application

Designing an EmberNet Application

by the gateway node memory requirements. This approach is recommended for any networks larger than thirty-two nodes.

Designing an EmberNet Application


The following section discusses each of the steps of designing an EmberNet application. Some steps are not needed for certain types of applications: 1. 2. 3. 4. 5. 6. 7. 8. Identify full-function and leaf node devices. Define messages. Determine device binding requirements. Choose a network discovery method. Determine endpoints and interfaces. Define binding table interactions. Create a mechanism for relaying messages to and from leaf nodes. Evaluate the design against the requirements.

Even if you are familiar with designing network applications, we recommend you read this section because certain aspects of the design process are unique to EmberNet.

General Design Recommendations


The following design practices are recommended for use with embedded mesh networks of any sort: Use push-based message flow whenever possible. Specifically, avoid polling nodes for data, because doing so uses twice the bandwidth that would be required by a node configured to send data at an appropriate rate. Rely on intelligence at the node to reduce the amount of traffic. Expect devices to enter and exit the network periodically. Plan for network bring-up both during installation and in the case of a power outage.

Identify Full-Function and Leaf Node Devices


To begin, develop a list of the different types of application-level devices that your network requires. For example, your network may have two types of light switches, three types of lights, and one type of gateway device. In addition to mapping these devices to your traffic pattern requirement, you should also determine whether they are best represented as leaf nodes or fullfunction nodes. Battery life and cost requirements usually dictate the choice. Nodes that must be battery operated must run the leaf node stack. Nodes that are cost sensitive are candidates for a smaller processor, which requires the leaf node stack. If you have leaf node devices, then you have a hybrid-mesh topology in which full-function devices provide the routing backbone for the network. Verify that your chosen sample deployments will still function even if some nodes will not route. This is a good time to consider modifying the deployment strategy or device types if full mesh coverage is not available in all situations. Changing leaf nodes to full-function nodes will increase the mesh, but at some cost in installation since full-function devices may be more expensive and may consume more power.

EmberNet Application Development Guide

120-0065-000A Final

Page 29

Chapter 3: Designing an EmberNet Application

Designing an EmberNet Application

Define Messages
For each type of node identified, determine the types of messages that it will send and receive. Then, for each type of message, specify maximum payload size, latency requirements, the type of node that will receive the message, and whether it is a unicast or a multicast message. Try to eliminate unnecessary multicast messages because they use a lot of network bandwidth. But in some cases, such as discovery of services, they are unavoidable. Make sure that no message payloads are larger than the maximum acceptable size for that type of message. Unicast messages must be 93 bytes or fewer, multicast messages must be 100 bytes or fewer, and aggregation messages must be 77 bytes or fewer. Larger messages must be broken into fragments by the application. To calculate approximate latencies, add 10ms per hop in a lightly loaded network and up to 100ms per hop in a heavily loaded network. Compare against your required minimum latencies.

Determine Device Binding Requirements


After device types and messages have been defined, the next step is to provide a mechanism that allows each device to know what device is the destination for a particular message. For example, a traditional light switch controls only the lights to which it is physically wired. In the case of a wireless light switch, there is no such physical mechanism. This is known as the virtual plug problem. The virtual plug problem can be solved in a variety of ways. The ease of use of a particular solution often depends on how well it matches the abilities of the target user. Here are some common approaches: Devices can be preprogrammed at manufacture time to know the other devices that they will speak to. This solution is easy for users to understand but necessitates installed networks that may not be reconfigurable. Most networks will be unable to make do with this solution alone. Sometimes a default package can be created by beginning with this solution and using one of the following solutions to add other devices later. The application can provide a binding device that displays the local network in graphical format and allows the user to configure associations among deployed devices to achieve the desired functionality. Owing to the added cost of such a binding device, this industrial-strength solution is only appropriate for applications that expect to have a technician deploy or modify most networks. The devices can provide a physical input mechanism that allows the user to select a particular device when the device is deployed. For example, a light switch and a set of lights may each have a button. When the user presses the light switch button and then one of the light buttons, the light switch associates to the selected light. This is an attractive solution for many consumer products because it is relatively simple, can have a variety of implementations depending on the device functions, and adds little or no cost to the project. The devices can employ dynamic binding. For example, devices may be instructed to listen for broadcasts from a gateway device and, when heard, store the gateway device for later use as a destination for certain types of messages. In this setup, the gateways can be changed without problem, because devices will simply store the next gateway that they hear. This solution is flexible, but care must be taken to make sure an appropriate gateway is chosen. This approach lends itself to in-field diagnostic or reconfiguration equipment. To assess device binding requirements, determine how each type of device will be informed of the appropriate destination for its messages. Add message types to accommodate the association process. Remember that leaf nodes do not have a binding table and communicate only with their parent device. Therefore, parent devices must know where to send leaf node messages.

EmberNet Application Development Guide

120-0065-000A Final

Page 30

Chapter 3: Designing an EmberNet Application

Designing an EmberNet Application

Note that unicast bindings require the 64-bit IEEE address, which, to save bandwidth, is not included by default in messages. Update payload lengths for messages that must contain the 64-bit address of the sender. Consider how the application will perform out of the box, and make sure that any required startup tasks are understood and documented.

Choose a Network Discovery Method


This step is only necessary for designs that need a way to guarantee that certain nodes can discover an appropriate network and alert its members to their presence. Mainly, these designs involve mobile nodes that must determine when they have entered a network or (for leaf nodes) whether their local relay point has changed. In some networks, it is not desirable to allow a new device to join unless the node has been identified and accepted. This can be done by using a PAN ID obtained from a central gateway or coordination device, or via a binding device (discussed in the preceding section). Decide whether mobile devices will periodically search for a local network periodically or wait to hear an advertisement beacon or broadcast message. Developers using leaf nodes must pay particular attention to how the leaf nodes track the network and how the network tracks them, especially if the leaf node may switch local relay points during a transaction. Add message types for the advertising exchange if they were not included in the messaging model defined above. Add a message type for providing the PAN ID to new nodes joining the network. Make sure that network acquisition time (that is, the length of time before a mobile node discovers a new network, and vice/versa) is acceptable. If using a beaconing or broadcast scheme, be aware of the network bandwidth consumed by sending out periodic beacons, even if nobody is using them. Battery-powered devices are subject to a direct tradeoff between bandwidth and acquisition time: Frequent beacons consume more bandwidth but allow a faster acquisition time.

Determine Endpoints and Interfaces


The EmberNet stack uses endpoints and interfaces to provide a local destination at the destination device. Each device can support up to 31 different endpoints, and each endpoint can contain up to 8 different interfaces. The destination endpoint and interface are provided in the emberIncomingMessageHandler() callback so that the application can determine the appropriate handler function. Every full-function device must have at least one endpoint and interface. Endpoints and interfaces support the binding device discussed above. If the application is consistent in its use of particular endpoints and interfaces, the external device can easily determine appropriate bindings by comparing the available endpoints and interfaces on each device. (Note that this is the only purpose of the SERVER and CLIENT endpoint types. Except for informing a binding device about the connections that can be made, these endpoint types are identical to the SYMMETRIC endpoint type.) Endpoint 0 is a special type of endpoint that can be used to query other local devices and set bindings remotely. It is described more fully in the endpoint 0 sample application (app\sample\enpoint0-app.c) that is provided with the Developer Kit. List each endpoint and interface in your application and which types of devices will have which. For each endpoint and interface combination, assign a type of message. EmberNet Application Development Guide 120-0065-000A Final Page 31

Chapter 3: Designing an EmberNet Application

Integrate Your Solution with EmberNet

Is there a method for establishing the appropriate endpoint and interface for all message types within the network? After initial installation, can the method of endpoints and interfaces chosen be used for as new devices are added or devices removed.

Define Binding Table Interactions


Each full-function device has room for only a limited number of bindings, because of RAM constraints. (Leaf node devices do not use bindings.) The application must determine how to use the binding table entries available to it so that it can send the unicast messages it needs to send and receive and send multicast messages from and to the appropriate multicast groups. Decide how the binding table will be used and the maximum size binding table expected for each device. Provide a means to reset the binding table if the network is modified. If the binding table will be saved over power cycles, it can be stored in EEPROM by correctly configuring binding table entries.

Create the Means to Relay Messages to and from Leaf Nodes


This step is necessary only for applications that include leaf nodes. Local beaconing nodes, a single-hop broadcast message, or a combination of the two may be employed to achieve the desired functionality.

Evaluate the Design Against the Requirements


When the design is completed, compare its capabilities and limitations to the project requirements, to make sure that the application meets all the identified needs. If it does not, either the design or the requirements should be adjusted.

Integrate Your Solution with EmberNet


Hardware
For development and debug of particularly difficult areas of your application, this can be done using individual devices with the debug tools normally used. Initial development and debug of your overall network level application should be done using the Ember development boards. This provided network level debug capabilities as well as methods for rapidly reloading software on all devices that are useful during software development and initial testing. Once the basic application is operational, it can then be moved to your custom hardware. This custom hardware can be developed with an internal hardware team, or Ember can recommend hardware design partners that have been used by other customers.

EmberNet Application Development Guide

120-0065-000A Final

Page 32

CHAPTER 4

Implementing the Project

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Basic Template: Full-Function and Leaf Node Devices . . . . . . . . . . . . . . . . 34 Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Initialization Function Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Running the Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Sending Messages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Create Bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Open a Connection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Creating the Message. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Creating Message Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Submit Message to the EmberNet Stack . . . . . . . . . . . . . . . . . . . . . . . 42 Wait for Callback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Receiving Messages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Create Binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Incoming Message Handler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Sending and Receiving Beacons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Sending Beacons. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Receiving Beacons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Tracking Beacons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Sleeping and Waking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Going to Sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Waking Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Overview
This chapter explains the steps required to implement a simple project and shows proper use of the building blocks required to make more complicated projects. Users interested in more detailed examples should see Chapter 5, Sample Sensor Applications and browse the sample code available in the stack distribution and on the Ember support web site (http://support.ember.com). EmberNet Application Development Guide 120-0065-000A Final Page 33

Chapter 4: Implementing the Project

Basic Template: Full-Function and Leaf Node Devices

For more information on configuring and using the IAR compiler, see Chapter 6, Developing Applications.

Basic Template: Full-Function and Leaf Node Devices


The app/simple/main.c file provides a simple template of a full-function device that does nothing but repeat for its neighbors. This application has only a few components.

Header Files
Ember uses several standard header files to define the types, data structures, and static variables used by the stack. Detailed descriptions of these files can be found in the EmberNet Stack Interface Guide. For EmberNet functionality, the following header files are required: PLATFORM_HEADER: A constant defined by compiler flags, this header file provides low-level compiler- and microprocessor-specific directives. It must be included in all source files that use the EmberNet API. stack/include/ember.h (or stack/include/ember-leaf.h for leaf nodes): Defines the EmberNet API. stack/include/error.h: Defines return values for EmberNet APIs. stack/include/ember-static-configuration.h: Must be included by exactly one source file per application. Source files that are involved in controlling the MCU-level and board level hardware should include the following header files: stack/include/hal.h: Defines high-level HAL APIs. hal/board/board.h: Defines board-specific control APIs and configurations. hal/micro/micro.h: Defines microprocessor-specific control APIs and configurations. Other header files commonly used are: stack/include/packet-buffer.h: Packet buffers are used only by the full-functionality stack and are explored in Sending Messages on page 38 and Receiving Messages on page 42. app/util/serial/serial.h: APIs for control of the UART driver. Sample of Header Files from app\simple\main #include PLATFORM_HEADER // Micro- and compiler-specific //typedefs and macros // Public Ember Stack APIs

#include "stack/include/ember.h"

#include "stack/include/packet-buffer.h" // Stack/Linked buffer //access APIs #include "stack/include/error.h" #include "stack/include/hal.h" #include "hal/board/board.h" #include "hal/micro/micro.h" // EmberNet stack status codes // Common HAL APIs that the stack // also uses // Board-specific HAL APIs // Micro- specific HAL APIs // Serial utility APIs

#include "app/util/serial/serial.h"

EmberNet Application Development Guide

120-0065-000A Final

Page 34

Chapter 4: Implementing the Project

Basic Template: Full-Function and Leaf Node Devices

Variables
Including stack/include/ember-static-configuration.h includes the default values of many variables. Changes to the default variable value must be done using macros defined in ember-static-config.h. In addition, full-function devices must include the following application-specific static variables: int8u emberEndpointCount: Defines the number of endpoints used by the application. This is used by the EmberNet stack to access the emberEndpoints variable. If it is not set correctly, stack behavior is undefined. This variable must be between 0 and 31, inclusive. EmberEndpoint emberEndpoints[]: This variable allows the stack to access userdefined endpoints. This array must be at least one element long (even if no endpoints are defined). Sample of Variables in app\simple\main // Declare adjustable memory allocations required by the stack // See the header for macros which can be used to adjust the size // of the allocations for specific applications // Ex: // #define EMBER_PACKET_BUFFER_COUNT 12 #include "stack/include/ember-static-configuration.h" // A variable to track the current status of the stack EmberStatus stackStatus = EMBER_NETWORK_DOWN; // Endpoints used by this application, and referenced by the stack int8u emberEndpointCount = 0; EmberEndpoint emberEndpoints[1];

Initialization Function Calls


Hardware-Level Initialization
The main function must initialize the microprocessor and board-level hardware before initializing the EmberNet stack. The initialization functions for the hardware components, microBoot() and boardBoot(), are provided in source code format in the HAL directory so that custom boards and custom microprocessor configurations can be supported.

Utility Initialization
Certain Ember-provided utilities, such as the ADC library, the UART/serial library, and the stack debugging output, must be initialized separately. Consult the EmberNet Stack Interface Guide for information on these utilities.

Stack-Level Initialization
The EmberNet stack has a two-step initialization process. First, emberInit() must be called to set up the right variables and prepare the stack for operation. Then, emberAssociate() must be called to configure the radio channel, PAN ID, and other network parameters. Once this is complete, the stack is ready to run.

EmberNet Application Development Guide

120-0065-000A Final

Page 35

Chapter 4: Implementing the Project

Basic Template: Full-Function and Leaf Node Devices

Sample of Initialization and Main Event Loop from app\simple\main int main(void){ EmberResetType reset; EmberStatus status; EmberNetworkParameters networkParams; // Determine the cause of the reset (powerup, etc.). reset = microGetResetInfo(); microBoot(); boardBoot(); // Initialize the micro and its peripherals //(timers, watchdog, ...) // Initialize the board and its peripherals //(LEDs, buttons, ...) // Safe to enable interrupts at this point // Use serial port 0 for debug output

INTERRUPTS_ON(); emberDebugInit(0);

// Initialize the Ember Stack. status = emberInit(reset); if (status != EMBER_SUCCESS) { // Report status here, if possible. if (status == EMBER_UNINITIALIZED_EUI64 || status == EMBER_INVALID_EUI64) { // Run to allow over-the-air configuration. while (TRUE) { __watchdog_reset(); emberTick(); } } else { assert(FALSE); } } // Bring the network up. networkParams.panId = 0; networkParams.enableRelay = TRUE; networkParams.radioTxPower = -1; networkParams.radioChannel = 0; status = emberAssociate(&networkParams); EmberNet Application Development Guide 120-0065-000A Final Page 36

Chapter 4: Implementing the Project

Basic Template: Full-Function and Leaf Node Devices

if (status != EMBER_SUCCESS) { // Report status here, if possible. assert(FALSE); } // Main event loop of the application while(TRUE) { __watchdog_reset(); emberTick(); // Periodically reset the watchdog // Allow the stack to run

if(stackStatus == EMBER_NETWORK_UP) { // OK to use the stack to send messages, etc. } heartBeat(); // Visually indicate normal operation // Needed for buffered serial, //which debug uses #ifdef DEBUG_ON emberSerialBufferTick(); #endif } }

Running the Stack


emberTick()
emberTick() can be considered the heartbeat of the networking functionality. It is responsible for processing all incoming radio packets and determining if they should be passed up to the application, relayed (in the case of a full-function device), or discarded. It is also responsible for other bookkeeping tasks that update the stack routing information and manage the memory usage of the stack. The frequency with which emberTick() must be called varies depending on the amount of traffic the individual node is generating and the amount of local network traffic. Most applications do not place high processing demands on the processor, so calling emberTick() frequently is not a problem. If your application is experiencing otherwise unexplained delivery failures or routing problems, increasing the frequency at which emberTick() is called may help. The return value of emberTick() represents the time until the next scheduled event. Interrupts may require processing sooner than this, in which case emberTick() should be called as soon as possible.

Stack Status Handler


The full-function stack requires some time after being initialized before it is ready to send and receive messages. The emberStackStatusHandler() will be called to indicate that the status of the stack has changed. When it returns EMBER_NETWORK_UP, messages can be sent and received.

Note: Do not call any EmberNet stack APIs if the stack is not up.

EmberNet Application Development Guide

120-0065-000A Final

Page 37

Chapter 4: Implementing the Project

Sending Messages

Sending Messages
Once the hardware and stack are initialized, messages can be sent and received. A message can be created at any time (see Allocating a Message Buffer on page 39), but it cannot be sent until the destination is known. The destination is identified by use of the binding table. A binding must be created (see Create Bindings on page 38) for the message to be sent. If a series of messages is to be sent and the sequence is to be maintained, then a connection between the source and destination is opened (see Open a Connection on page 39). Once a binding and message have been created, the message can be submitted to the Ember stack for delivery (see Submit Message to the EmberNet Stack on page 42) and status can be checked using the callback (see Wait for Callback on page 42).

Create Bindings
Note: This section applies to full-function devices only.
To send a message, a node must first create the proper binding table entry. The binding table entry can target a single destination node (for a unicast) or multiple destination nodes (for a multicast). The stack uses the binding table, but the table entries are managed entirely by the application. The number of bindings available is limited by the amount of RAM and EEPROM on the processor and can be adjusted in ember-static-configuration.h. Very large network applications should considering using RNAP to offload some of the memory requirements onto a larger host processor. The application must create bindings when it needs them and, if more bindings are required than there is space in the table, it must delete old bindings and reclaim the space they occupied. The application can also check to see if a binding is currently involved in sending or receiving a message by using emberBindingIsActive(). Bindings cannot be deleted while they are active. For the exact structure of binding table entries and function calls for managing binding table entries, see the EmberNet Stack Interface Guide. Sample Binding Table Entry Creation from app\sensor\sensor-ffd // setup multicast binding void setMulticastBinding(void) { EmberBindingTableEntry entry; EmberStatus status; entry.type = EMBER_MULTICAST_BINDING; entry.local = emberMakeTerminal(ENDPOINT, 1); entry.remote = emberMakeTerminal(ENDPOINT, 1); entry.identifier[0] = HIGH_BYTE(MULTICAST_ID); entry.identifier[1] = LOW_BYTE(MULTICAST_ID); status = emberSetBinding(MULTICAST_BINDING_INDEX, &entry);

EmberNet Application Development Guide

120-0065-000A Final

Page 38

Chapter 4: Implementing the Project

Sending Messages

emberSerialPrintf(APP_SERIAL, "EVENT: setting multicast binding, status is 0x%x\r\n", status); }

Open a Connection
Note: This section applies one to full-function devices and the sending of sequenced unicast
messages. If you are using sequenced messages, you must first use emberOpenConnection() to open a connection to the correct binding. Then you must wait for the handler function, emberConnectionStatusHandler(), to inform you that the connection is ready for use.

Creating the Message


The method used to create the message varies depending on the type of device: Full-function devices: Allocate a message buffer. Leaf node devices: Place the message in an array.

Allocating a Message Buffer


Note: This section applies to full-function devices only.
The full-functionality stack uses message buffers to send and receive messages. A message buffer is one or more 32-byte buffers that are linked together at runtime to provide enough space for a single message. These buffers are not guaranteed to be contiguous, so to avoid running off the end of a linked buffer, we recommend that you use the functions in packet-buffer.h to access and modify buffers. Messages shorter than 32 bytes can safely manipulate a direct pointer to the data. The simplest way to allocate a buffer is by using emberFillLinkedBuffers(), which can be passed a standard array and a length that will be copied into a newly allocated message buffer. The function returns a handle to the new message buffer, or EMBER_NULL_MESSAGE_BUFFER if no buffer is available. Always check the return value of this and any message buffer function that returns a value, to ensure that the memory you are requesting is available. Any buffers allocated by the application must be freed by the application. Any buffers not allocated by the application must not be freed by the application. Other methods for accessing the message buffers can be found in packet-buffer.h. Sample for Creating and Sending a Message from app\sensor\sensor-ffd // The sensor fabricates data and sends it out to the sink void sendData(void) { int16u data; EmberStatus status; EmberMessageBuffer buffer = 0; int8u i;

EmberNet Application Development Guide

120-0065-000A Final

Page 39

Chapter 4: Implementing the Project

Sending Messages

// get a random piece of data data = firmGetRandom(); emberDebugPrintf("sensor has data ready: 0x%2x \r\n", data); // the data - msg type, my address and data globalBuffer[0] = MSG_DATA; MEMCOPY(&(globalBuffer[1]), emberGetEui64(), 8); for (i=0; i<(SEND_DATA_SIZE/2); i++) { globalBuffer[9+(i*2)] = HIGH_BYTE(data); globalBuffer[10+(i*2)] = LOW_BYTE(data); } // copy the data into a packet buffer buffer = emberFillLinkedBuffers(globalBuffer, 9 + SEND_DATA_SIZE); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [data], OUT OF BUFFERS\r\n"); return; } // send the message status = emberSendDatagram(SINK_BINDING_INDEX, buffer); // done with the packet buffer emberReleaseMessageBuffer(buffer); // print a status message emberSerialPrintf(APP_SERIAL, "TX [DATA] status: 0x%x data: 0x%2x\r\n", status, data); }

Creating Message Data


Note: This section applies to leaf node devices only.
Leaf node devices do not have message buffers, so they store data in a contiguous array of memory that is managed by the application. The leaf node stack allocates its own memory for processing incoming messages. When filling in a message buffer, the application must set the first byte of the data to the total number of bytes that follow.

EmberNet Application Development Guide

120-0065-000A Final

Page 40

Chapter 4: Implementing the Project

Sending Messages

When this message is received by a full-function device, the first byte in the received message buffer is the first byte of data, not the number of bytes. The length of the message is determined via the message buffer APIs. Sample of Creating and Sending a Message from app\sensor\sensor-leaf // The sensor-leaf fabricates data and sends it out to the sink void sendLeafData(void) { int16u data; EmberStatus status; int8u localTerminal = 9; int8u remoteTerminal = 9; // length is msg type (1 byte), eui (8 bytes), and data // (length byte does not count in length) int8u length = SEND_DATA_SIZE + 9; int8u i; // get a random piece of data data = firmGetRandom(); //emberDebugPrintf("sensor-leaf has data ready: 0x%2x \r\n", data); // the data - length, msg type, my address and data globalBuffer[0] = length; globalBuffer[1] = MSG_LEAF_DATA; MEMCOPY(&(globalBuffer[2]), emberGetEui64(), 8); for (i=0; i<(SEND_DATA_SIZE/2); i++) { globalBuffer[10+(i*2)] = HIGH_BYTE(data); globalBuffer[11+(i*2)] = LOW_BYTE(data); } // send the message status = emberSendDatagram(sinkEui64, localTerminal, remoteTerminal, globalBuffer); // print a status message emberSerialWaitSend(APP_SERIAL); emberSerialPrintf(APP_SERIAL, "TX [leaf DATA] status: 0x%x data: 0x%2x\r\n", status, data); emberSerialWaitSend(APP_SERIAL); }

EmberNet Application Development Guide

120-0065-000A Final

Page 41

Chapter 4: Implementing the Project

Receiving Messages

Submit Message to the EmberNet Stack


To ask the stack to send the message, use one of the following calls: For full-function devices: emberSendSequenced() or emberSendMulticast() For leaf node devices: emberSendLinkBroadcast() For both full-function and leaf node devices: emberSendDatagram() Full-function devices must pass the message buffer handle to the function. Leaf node devices must pass a pointer to the message data. If the function returns EMBER_SUCCESS, then the stack has accepted your message for delivery. If a non-success value is returned, examine it to determine the source of the error. In most cases it will be a configuration problem and not a dynamic resource problem (for example, trying to send a unicast message on a multicast binding). If you are sending a unicast message (either sequenced or datagram), the stack will always call emberMessageSent() to indicate the result of the delivery attempt. Multicast messages are assumed sent when they are accepted for delivery. Once a unicast message is submitted for delivery, the message buffer should not be modified until the emberMessageSent() callback has occurred for the unicast message.

Wait for Callback


Note: This section applies to unicast messages only.
The emberMessageSent() callback will be called for all accepted unicast messages. It will indicate whether the message was successfully received. Ember uses a full end-to-end acknowledgement for each message. A status value of EMBER_SUCCESS guarantees that the message was received by the destination node and that the acknowledgement was received back at the sending node. Other return values indicate only that the sending node did not receive the acknowledgement, not that the destination node did not receive the message.

Receiving Messages
A device receives any messages that are sent using its address as the destination. The message is handed up to the application with a status of EMBER_NULL_BINDING in the following cases: When a binding table entry does not exist for the source of the message. When the binding table only has the 64-bit address and the message is sent using the 16-bit address.

Create Binding
Note: This section applies to full-function devices and multicast messages only.
For full-function devices to receive a multicast message, they must create a binding to the appropriate multicast group. This is done in the same way as creating and binding to send to the multicast group. There is no need to create a separate binding. However, the same binding can be used for sending and receiving.

Incoming Message Handler


When an incoming message is received for this node, the Ember stack calls emberIncomingMessageHandler() with the appropriate status values filled in.

EmberNet Application Development Guide

120-0065-000A Final

Page 42

Chapter 4: Implementing the Project

Receiving Messages

Leaf node devices will receive the incoming message as an array with the first byte indicating the number of bytes to follow. Full-function devices will receive a callback for each matching binding in the binding table. The function parameters will be populated as per the API documentation. The message buffer may be modified, but will stay modified for any subsequent calls to emberIncomingMessageHandler() on other matching bindings. The message buffer must not be freed by the application. The binding index will contain either the binding match or EMBER_NULL_BINDING if no binding matched an incoming unicast message. Note that if no binding matches, it does necessarily follow that no binding to the sending node is present in the table. Bindings are associated with the 64-bit address. Messages are sent using a 16-bit short address. By calling emberNoteSendersBinding() on a received message, the binding table will be updated with the short address. The short address can sometimes change during network operation. In this event, the binding table entry may not match, and the old binding should be deleted and a new binding created. Sample Code for Incoming Message Handler from app\simple\sensor-ffd void emberIncomingMessageHandler(EmberIncomingMessageType type, int8u localTerminal, int8u bindingTableIndex, EmberMessageBuffer message){ // Called with an incoming message int8u* data; int8u length; data = emberMessageBufferContents(message); length = emberMessageBufferLength(message); // make sure this is a valid packet of sensor/sink app // it must have a type, then 64 bit address (9 bytes minimum) if (length < 9) { emberSerialPrintf(APP_SERIAL, "RX [bad packet] of length %x\r\n", length); return; } // handle the incoming message switch (data[0]) { case MSG_SINK_ADVERTISE: emberSerialPrintf(APP_SERIAL, "RX [sink advertise] from: "); printEUI64(APP_SERIAL, &data[1]); if ((mainSinkFound == FALSE) && (waitingForSinkReadyMessage == FALSE) && (waitingToRespond == FALSE)) { waitingToRespond = TRUE;

EmberNet Application Development Guide

120-0065-000A Final

Page 43

Chapter 4: Implementing the Project

Receiving Messages

emberSerialPrintf(APP_SERIAL, "; processing message\r\n"); MEMCOPY(&(dataBuffer[0]), data, 9); // wait for 1 - 5 seconds before responding respondTimer = ((firmGetRandom()) % 20) + 5; timeToWaitForSinkReadyMessage = TIME_TO_WAIT_FOR_SINK_READY; emberSerialPrintf(APP_SERIAL, "EVENT waiting %x ticks before reponding\r\n", respondTimer); } else { emberSerialPrintf(APP_SERIAL, "; ignoring\r\n"); } break; case MSG_SENSOR_SELECT_SINK: emberSerialPrintf(APP_SERIAL, "RX [sensor select sink] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; this is an ERROR]\r\n"); break; case MSG_SINK_READY: emberSerialPrintf(APP_SERIAL, "RX [sink ready] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; will start sending data\r\n"); waitingForSinkReadyMessage = FALSE; mainSinkFound = TRUE; sendDataCountdown = SEND_DATA_RATE; startSensorBeacons(); break; case MSG_DATA: emberSerialPrintf(APP_SERIAL, "RX [DATA] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; this is an ERROR\r\n"); break; case MSG_MULTICAST_HELLO: emberSerialPrintf(APP_SERIAL, "RX [multicast hello] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "\r\n"); break; case MSG_LEAF_JOIN:

EmberNet Application Development Guide

120-0065-000A Final

Page 44

Chapter 4: Implementing the Project

Sending and Receiving Beacons

emberSerialPrintf(APP_SERIAL, "RX [leaf join] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; processing message\r\n"); emberSerialWaitSend(APP_SERIAL); handleLeafJoin(data); break; case MSG_LEAF_DATA: // we just heard from this binding table index ticksSinceLastHeard[bindingTableIndex] = 0; emberSerialPrintf(APP_SERIAL, "RX [leaf DATA] from: "); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; len 0x%x / data 0x%x%x\r\n", length, data[9], data[10]); forwardLeafDataToSink(message); break; default: emberSerialPrintf(APP_SERIAL, "RX [unknown (%x)] from: ", data[0]); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "; ignoring\r\n"); } }

Sending and Receiving Beacons


Sending Beacons
Note: This section applies to full-function devices only.
Periodic beacons are transmitted by calling emberTransmitBeacons(). The beacons are transmitted on the specified beacon interval until another call is made to emberTransmitBeacons() to change the beacon interval or to turn off the beacons. For details on the parameters that control the beacon interval and value used to turn off the beacons, see the EmberNet Stack Interface Guide. The beacon payload is passed to the stack in a message buffer. The beacon payload can be modified by calling emberTransmitBeacons() with a new message buffer and either the same beacon interval timing values or new timing values if desired. The maximum beacon payload size is 100 bytes. The beacon payload can also be NULL. Nodes that receive beacons with a NULL payload will only receive the EUI64 of the beacon sender. Nodes that are transmitting beacons cannot also receive and track beacons from other nodes. Note that bindings are not used for sending beacons.

EmberNet Application Development Guide

120-0065-000A Final

Page 45

Chapter 4: Implementing the Project

Sleeping and Waking

Receiving Beacons
Beacons are received in the incomingBeaconHandler() callback. Two parameters are passed to the application in the callback: An application-specific beacon payload and the EUI64 address of the node transmitting the beacon. On the leaf node, if the payload is not NULL, the first byte is the length of the payload. Bindings are not used for receiving beacons.

Tracking Beacons
Beacon tracking is used to notify the application when the stack has stopped receiving beacons from a beaconing node. The emberBeaconTrack() API call enables or disables beacon tracking. When beacon tracking is enabled and the stack has not heard a beacon in four consecutive beacon periods, the EMBER_MAC_BEACON_LOSS status is passed to the application in the emberStackStatusHandler() callback. Beacon tracking is automatically disabled when the beacon loss status is passed up to the application. See the EmberNet Stack Interface Guide documentation on emberBeaconTrack()for details on how to enable or disable beacon tracking. The EMBER_MAC_BEACON_LOSS status is a one-time event and has no effect on the EMBER_NETWORK_UP status.

Sleeping and Waking


Nodes that need to conserve power need to sleep as often as possible. Because of the routing responsibilities of full-function devices, Ember does not recommend that they be put to sleep while the network is functioning. However, functionality is available to do this, on both full-function and leaf node devices.

Going to Sleep
To put the EmberNet stack to sleep, call emberSleep(). When emberSleep() returns TRUE, the network stack is no longer operating and the radio has been put into idle mode. Because it takes time for the stack to complete processing, the microprocessor should not be put to sleep until emberSleep() returns TRUE. Once the radio is asleep, the microprocessor must be put to sleep. Ember provides utility functions in the appropriate HAL micro.c file to do this, but the application must ensure that the microprocessor has some mechanism configured to wake up again. Be sure to disable the watchdog timer before sleeping, to avoid a watchdog reset immediately upon wakeup.

Waking Up
Once the microprocessor has waked up, it should reinitialize any peripherals it was using and then call emberWakeUp() to reinitialize the stack and wake up the radio. The emberWakeUp() call should only be used once. Sample of Sleep and Wake Code from app\sensor\sensor-leaf // manage the sleeping and waking up of the leaf if (isAwake == TRUE) { // *** leaf is awake *** EmberNet Application Development Guide 120-0065-000A Final Page 46

Chapter 4: Implementing the Project

Callbacks

awakeTimer = awakeTimer - 1; if (awakeTimer < 1) { // delay going to sleep if in the middle of a protocol exchange if ((waitingToRespond == TRUE) || (waitingForSinkAllowJoin == TRUE)) { awakeTimer = 1; } else { // put the node to sleep status = emberSleep(); emberSerialPrintf(APP_SERIAL, "EVENT: leaf node going to sleep, status 0x%x\r\n", status); isAwake = FALSE; sleepTimer = LEAF_SLEEP_TIME; } } } else { // *** leaf is asleep *** sleepTimer = sleepTimer - 1; if (sleepTimer < 1) { emberWakeUp(); emberSerialPrintf(APP_SERIAL, "EVENT: leaf node waking up\r\n"); isAwake = TRUE; awakeTimer = LEAF_AWAKE_TIME; } } } }

Callbacks
EmberNet requires a number of callbacks to be implemented so that the stack can inform the application of events and status changes. The current list of callbacks for full-function devices (as of version 3.3 of the EmberNet stack) is: emberEndpointFoundHandler() emberMessageSent() emberIncomingMessageHandler() emberConnectionStatusHandler() emberApplicationBufferWasFreed() emberRemoteSetBindingHandler()

EmberNet Application Development Guide

120-0065-000A Final

Page 47

Chapter 4: Implementing the Project

Callbacks

emberStackStatusHandler() emberIncomingBeaconHandler() (optional) Details on these callbacks can be found in the EmberNet Stack Interface Guide.

EmberNet Application Development Guide

120-0065-000A Final

Page 48

CHAPTER 5

Sample Sensor Applications

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 How the Sample Sensor Application Works . . . . . . . . . . . . . . . . . . . . . . . . 50 Writing the Main Application Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Initializing the Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Associating to the Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Initializing Application Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Writing the Event Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Establishing Interfaces and Endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Declaring Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Declaring Endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Binding Devices Together. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Commissioning the Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Sending and Receiving Messages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Sending Multicasts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Receiving Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Setting the Binding. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Sending Datagrams. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Leaf Node Sample Sensor Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Design of the Leaf Node Sensor Sample Application . . . . . . . . . . . . . 62 Leaf Node Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Leaf Node Initialization and Startup. . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Leaf Node Network Acquisition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Routing from a Leaf Node Device. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Routing to a Leaf Node Device. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Beacons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Battery Life . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

EmberNet Application Development Guide

120-0065-000A Final

Page 49

Chapter 5: Sample Sensor Applications

Overview

Overview
This chapter draws on the general design and implementation topics covered earlier to demonstrate the subset of EmberNet stack calls needed for a basic sensor data collection application, using the Developer Kit sample sensor applications to illustrate the discussion. This type of application involves many key stack API abstractions and calls, and thereby the topics covered in this chapter will be of use to developers working on all types of applications. Following discussion of the general sensor network, the chapter covers modification of the sensor application to support leaf node devices. The sample sensor application is a simplified version of typical industrial control or monitoring applications in which multiple sensors periodically report data to one or more data collection points, called data sinks. The application follows the usual practice of requiring that data sinks periodically announce their presence and that sensors respond to the announcements. (This is preferred to having the sensors announce their presence, because there are many more sensors than sinks.) The discussion of the sample application assumes a single sink, but it can easily be generalized to more sinks. The code examples used in this chapter are from the Developer Kit sensor sample application. This application is contained in three files: common.h, sensor.c, and sink.c. The leaf node sensor application can be found in sensor-ffd.c and sensor-leaf.c. See the source code for additional comments and code features not discussed here. The following discussion frequently references Ember HAL functions, structures, and data types. For information about these constructs, see the Hardware Abstraction Layer Interface Guide.

How the Sample Sensor Application Works


Figure 5-1 illustrates the basic program flow in sensor.c and the message types sent. The application begins by having the sink broadcast a message to the sensors (termed a multicast in the EmberNet stack API). The sinks use the multicast to advertise that they are looking for sensors. Later, sensor nodes will need to send data reports back to the controller. The simplest messages sent to a single recipient in EmberNet are called datagrams. To send and receive datagrams, the stack requires a binding. Bindings are discussed in more detail in Chapter 4, Implementing the Project.

Figure 5-1: Program flow and message types in the sample sensor application Sink Node Sink advertise Multicast Unicast Set binding to sink Sensor Node

Set binding to sensor

Unicast Sensor Data Unicast

EmberNet Application Development Guide

120-0065-000A Final

Page 50

Chapter 5: Sample Sensor Applications

Writing the Main Application Loop

Writing the Main Application Loop


As described in Chapter 4, Implementing the Project, applications must first initialize the hardware and associate to the network, then perform application initializations, then loop through a cycle that alternately calls application functions and the EmberNet stack functions that drive the stack.

Initializing the Application


To initialize an application, call microBoot() and boardBoot() and, optionally, two serial port initializations, one to enable printouts and the other to talk to the Ember Studio Debug Reader. (For information about the Debug Reader, see Chapter 5 of the Ember Studio Users Guide.) emberInit() is called to initialize the EmberNet stack and perform error checks. It configures the radio and prepares the networking stack variables. As always, pay attention to the EmberStatus values returned from all stack functions and take appropriate action. // Begin main application loop int main(void) { ResetType reset; EmberStatus status; EmberNetworkParameters networkParams; int16u pc; // radio configuration and Ember bringup reset = microGetResetInfo(); microBoot(); // initialize the LEDs and such boardBoot(); // allow interrupts INTERRUPTS_ON(); // initialize the serial port emberSerialInit(APP_SERIAL, BAUD_19200, PARITY_NONE, 1); // emberInit() must be called before other stack functions emberDebugInit(DEBUG_SERIAL); // Initialize the Ember Stack. status = emberInit(reset); if (status != EMBER_SUCCESS) { emberSerialGuaranteedPrintf(APP_SERIAL, "error returned from emberInit: 0x%x\r\n",status); assert(FALSE); } }

EmberNet Application Development Guide

120-0065-000A Final

Page 51

Chapter 5: Sample Sensor Applications

Writing the Main Application Loop

Associating to the Network


After initializing the radio, you need to set network parameters and associate to the network. emberAssociate() is used to set all of the parameters that affect routing and to associate with a network in the area. The EmberNetworkParameters structure contains all the parameters that emberAssociate() requires. The structure has four members: panId: Sets the PAN ID for the application. The PAN ID is the 802.15.4 personal area network identifier. This two-byte number acts as a filter, allowing the application to create a private personal area network (PAN) and disregard traffic occurring in other PANs. 0xFFFF is the broadcast PAN. enableRelay: Sets whether this node can act as a repeater for other traffic. radioTxPower: Sets the radio transmission power level. radioChannel: Sets the radio channel on which you wish to send and receive data. The sensor sample application calls emberAssociate() with a pointer to an EmberNetworkParameters structure. To change the EmberNetworkParameters settings for a node, you must call emberDisassociate(), which causes the node to dissociate from the network and then call emberAssociate() with the new parameters. Be careful when changing settings. An error in a node's setting may prevent other network nodes from communicating with the node after it reassociates with the network. For example, if the channel setting is changed for a node, it will not be able to find the network on the new channel, because all the other nodes are using a different channel. Use emberAssociate() to associate to a new network. If you have previously connected to a network and wish to reconnect to it, use emberReassociate(). The main difference between these two functions is that certain network parameters are established in an emberAssociate() call and are kept static in an emberReassociate() call. For example, if you are programming sensor nodes that can be redeployed at any location and talk to any sink, you should call emberAssociate() on restart every time (as the sensor sample application does). If you are creating a lighting application, in which the nodes generally won't move around, you should use emberAssociate() only through a commissioning agent function call, and use emberReassociate() on every other reset that occurs. // Bring the network up. networkParams.panId = 0; networkParams.enableRelay = TRUE; networkParams.radioTxPower = -1; networkParams.radioChannel = 0x0F; status = emberAssociate(&networkParams); if (status != EMBER_SUCCESS) { emberSerialGuaranteedPrintf(APP_SERIAL, "error returned from emberAssociate: 0x%x\r\n",status); assert(FALSE); } sensorInit(); // main() is finished in code extract below

EmberNet Application Development Guide

120-0065-000A Final

Page 52

Chapter 5: Sample Sensor Applications

Establishing Interfaces and Endpoints

Initializing Application Functions


After associating, you can initialize anything needed for the application, and you are free to use the network to do so. The initialization routine for the application is sensorInit(), as you can see in the actual sensor.c source code. In the sink application (sink.c), this is replaced by sinkInit().

Writing the Event Loop


After writing the code that initializes the network and application functions, you must write the event loop. This loop executes application functions and calls emberTick(), which performs the maintenance functions required to operate the EmberNet stack. // continued from above // event loop while(TRUE) { __watchdog_reset(); emberTick(); processSerialInput(); heartBeat(); // flash the LEDs, watch timeouts // end main application loop

Establishing Interfaces and Endpoints


Declaring Interfaces
A terminal consists of interfaces and endpoints. Interfaces are declared with the EmberInterfaceID structure. In this example, sensor advertisement messages follow a fixed structure, or protocol. We define an interface for these advertisements as follows: static EmberInterfaceId PGM commonInterfaceId = { AD_HOC_INTERFACE, SYMMETRIC_ENDPOINT, 1, COMMON_SPEC}; // interface domain // endpoint type // # of bytes in specification ID // specification identifier {AD_HOC_INTERFACE, SYMMETRIC_ENDPOINT, 1, SENSOR_SPEC}; static EmberInterfaceId PGM sinkInterfaceId = {AD_HOC_INTERFACE, SYMMETRIC_ENDPOINT, 1, SINK_SPEC}; These structures tell the stack that there will be three types of advertisement messages and that they will have the following characteristics: They will all implement an ad hoc interfacethat is, an interface whose identifier is arbitrary and does not conform to specifications for any standards body. EmberNet Application Development Guide 120-0065-000A Final Page 53

static EmberInterfaceId PGM sensorInterfaceId =

Chapter 5: Sample Sensor Applications

Establishing Interfaces and Endpoints

They will all have an ad hoc interface, which will be used on a symmetric endpoint. This means that the protocol will be the same for every node that implements the interface. Protocols sometimes involve different client and server messages; these are designated by selecting the corresponding endpoints. Applications in which many data sources report to a data aggregator should specify that the interface resides on an aggregation endpoint. Each message implements a different protocol, as declared by the specification field in each structure. Because the interface is of the ad hoc type, the value for this field is arbitrary and uncoordinated. Note that there is a risk of a potential ID conflict with other ad hoc interfaces. Note that the structures are declared PGM, which means that they are stored in program memory and so cannot be changed at runtime.

Declaring Endpoints
Endpoints are declared with the EmberEndpointDescription structure. An endpoint abstractly represents an embedded device connected to the Ember radio. For example, one radio could have an on/off switch attached. This would be one device, represented by one endpoint. If we also added a dimmer switch, it would be a good idea to represent it as a different endpoint. The following excerpt represents the distributed sensor node in the sensor data collection example. // interface IDs #define COMMON_IFACE 1 #define SENSOR_IFACE 2 static EmberEndpointDescription PGM sensorEndpoint = { {COMMON_IFACE, &commonInterfaceId}, {SENSOR_IFACE, &sensorInterfaceId} }; This structure tells the stack that there is a sensor connected to the radio. Devices sometimes accept messages in multiple protocols, so the endpoint definition lists the interfaces the device supports. Because devices do not usually change their communication characteristics, the endpoint definition is not something that changes on the fly, and thus the structure can be stored in flash to preserve RAM. The stack needs a list of the endpoints that this radio will support: // emberEndpointCount and emberEndpoints MUST be defined by // the application. This is how EmberNet stack accesses the // application-defined endpoints and interfaces. int8u emberEndpointCount = 1; EmberEndpoint emberEndpoints[] = { {ENDPOINT, &sensorEndpoint} }; // Interface IDs #define COMMON_IFACE 1 #define SENSOR_IFACE 2 EmberNet Application Development Guide 120-0065-000A Final Page 54

Chapter 5: Sample Sensor Applications

Binding Devices Together

#define SINK_IFACE

// define the actual endpoint (stored in PGM memory) static EmberEndpointDescription PGM sensorEndpoint = { {COMMON_IFACE, &commonInterfaceId}, {SENSOR_IFACE, &sensorInterfaceId} }; static EmberEndpointDescription PGM sinkEndpoint = { {COMMON_IFACE, &commonInterfaceId}, {SINK_IFACE, &sinkInterfaceId} } An endpoint can support multiple interfaces. The combination of endpoint and interface is called a terminal. This combination can be thought of as a service provided or subscribed to. In the preceding lighting example, one of the interfaces we may establish in the on/off switch is the actual on/off toggle itself. We might also want to add a control interface to this endpoint, so that we can tell the switch how often to report a given datum for a node (for example, battery life). The stack can support different node configurations, and the application can detect endpoint configuration dynamically. For example, suppose your product is available to the end consumer in three configurations. The first configuration contains devices A and B, the second contains devices A and C, and the third contains only device A. If you want to use the same application image in all versions, include endpoint descriptions for devices A, B, and C in flash. At power-up, the application detects which devices are connected to the radio, sets emberEndpointCount to either 2 or 1, and populates the emberEndpoints[] array only with the endpoints found. The variables emberEndpointCount and emberEndpoints[] must be declared in every application, because the stack uses them. They are left to the application because the amount of RAM is usually limited and the size of emberEndpoints[] depends on the application.

Note: While most of the index and ID values are arbitrary in their valid ranges, endpoint 0 is
reserved. emberEndpointCount is the number of endpoints defined by the user application. It does not include endpoint 0 in its count.

Binding Devices Together


In this example, the sink advertises itself using a multicast message. We declare this to the stack by setting the following binding: #define MULTICAST_BINDING_INDEX (EMBER_BINDING_TABLE_SIZE - 1) #define SINK_BINDING_INDEX (0) // This is the unique identifier for the multicast group that // this application uses. #define MULTICAST_ID 0x1111 // set up multicast binding void setMulticastBinding(void) { EmberBindingTableEntry entry; EmberStatus status;

EmberNet Application Development Guide

120-0065-000A Final

Page 55

Chapter 5: Sample Sensor Applications

Commissioning the Network

entry.type = EMBER_MULTICAST_BINDING; entry.local = emberMakeTerminal(ENDPOINT, 1); entry.remote = emberMakeTerminal(ENDPOINT, 1); entry.identifier[0] = HIGH_BYTE(MULTICAST_ID); entry.identifier[1] = LOW_BYTE(MULTICAST_ID); status = emberSetBinding(MULTICAST_BINDING_INDEX, &entry); emberSerialPrintf(APP_SERIAL, "EVENT: setting multicast binding, status is 0x%x\r\n", status); } As the name indicates, the EmberBindingTableEntry type field indicates when the entry: Is not used. Is used to exchange messages with a single recipient (unicasts). Is used to exchange multicasts. The identifier field allows two bytes for multicasts and eight bytes for unicasts, to distinguish the association corresponding to this binding from any others. In the case of a multicast, the stack uses the identifier field to filter messages, so both the sender and receiver must use the same values. The local terminal identifies which interface on what endpoint is set up for these messages when they are inbound, and we set the field here in case we want to check for multiple controllers in the network. Unlike the datagrams discussed below, multicast messages do not get sent to a specific remote terminal, so the remote field is not used.

Commissioning the Network


Commissioning is the process of determining the interactions among devices. It is a key step in the deployment of many systems. For example, in lighting control, a contractor installs switches, light level sensors, occupancy sensors, and lamp ballasts as required for a particular building layout. Because there is no way for manufacturers of these components to anticipate the precise combination of devices used or their configuration at the jobsite, they must provide some means to specify how devices interact after installation. Commisioning can happen completely at run-time, with a sink service advertising itself and the sensor nodes subscribing to the service, and this is the method used in the sensor/sink application. It can also happen entirely at program time, with the network connections being preprogrammed and not changing during runtime. Finally, commisioning can also happen at set-up time, through a third-party agent. The nodes need to populate the emberRemoteSetBindingHandler() with appropriate application code and program the third-party agent to implement an appropriate interface for the types of bindings your installers will need to create.

Sending and Receiving Messages


Sending Multicasts
Using the binding created above, we can send multicast messages advertising the sink: // sinkAdvertise void sinkAdvertise(void) { EmberStatus status; EmberMessageBuffer buffer = 0; EmberNet Application Development Guide 120-0065-000A Final Page 56

Chapter 5: Sample Sensor Applications

Sending and Receiving Messages

// the data - msg type, and sink address globalBuffer[0] = MSG_SINK_ADVERTISE; MEMCOPY(&(globalBuffer[1]), emberGetEui64(), 8); // copy the data into a stack buffer buffer = emberFillLinkedBuffers((int8u*) globalBuffer, 9); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [sink advertise], OUT OF BUFFERS\r\n"); return; } // send the message status = emberSendMulticast(MULTICAST_BINDING_INDEX, buffer); // done with the stack buffer emberReleaseMessageBuffer(buffer); } This creates a message containing the 64-bit identifier. Sensor nodes that set a binding table entry with the same multicast identifier field will be able to receive this message. As you will see later in this chapter, these sensors use the controller EUI to create a binding. Because the sending node does not keep a list of the recipients of multicast messages, there is no acknowledgement mechanism for multicasts. Consequently, the user application does not receive any indication of whether they were delivered. Note that emberFillStackBuffer() allocates a message buffer from the stack buffer pool. This function is responsible for releasing buffers it allocates.

Receiving Messages
Once the sensor hears the sink advertisement, it sets a binding and sends a unicast message to the sink, which then sets a corresponding binding entry. The user application receives messages via the emberIncomingMessageHandler() callback, which the stack requires in every application. The following code handles all incoming messages because the same code is running both the sensor nodes and the sink nodes. void emberIncomingMessageHandler(EmberIncomingMessageType type, int8u localTerminal, int8u bindingTableIndex, EmberMessageBuffer message){ // called with an incoming message int8u* data; int8u length; data = emberMessageBufferContents(message); length = emberMessageBufferLength(message); // make sure this is a valid packet of sensor/sink app EmberNet Application Development Guide 120-0065-000A Final Page 57

Chapter 5: Sample Sensor Applications

Sending and Receiving Messages

// it must have a type, then 64-bit address (9 bytes minimum) if (length < 9) { emberSerialPrintf(APP_SERIAL, "RX [bad packet] of length %x\r\n", length); return; } emberSerialPrintf(APP_SERIAL, "RX from: ["); printEUI64(APP_SERIAL, &data[1]); emberSerialPrintf(APP_SERIAL, "] "); // handle the incoming message switch (data[0]) { case MSG_SINK_ADVERTISE: if (mainSinkFound == FALSE) { emberSerialPrintf(APP_SERIAL, "[sink advertise]\r\n"); handleSinkAdvertise(data); } else { emberSerialPrintf(APP_SERIAL, "[sink advertise], ignoring\r\n"); } break; The handler above is the callback for incoming messages. In the full sample code this handler contains more message types, as they have been defined by the application. The code sorts messages based on these types. In more complex systems, nodes may receive datagrams in multiple protocols for the various devices they support. In these cases, messages should be sorted further by localTerminal.

Setting the Binding


When a sensor receives a sink advertisement, it adds a binding to the binding index and responds with a SENSOR_SELECT_SINK message. // This handles the sink advertisement message on the // sensor. The sensor responds with a SENSOR_SELECT_SINK // message if it is not yet bound to a sink. void handleSinkAdvertise(int8u* data) { EmberBindingTableEntry entry; EmberStatus status; EmberMessageBuffer buffer = 0; // add a binding to SINK_BINDING_INDEX entry.type = EMBER_UNICAST_BINDING; entry.local = emberMakeTerminal(ENDPOINT, 1); entry.remote = emberMakeTerminal(ENDPOINT, 1); EmberNet Application Development Guide 120-0065-000A Final Page 58

Chapter 5: Sample Sensor Applications

Sending and Receiving Messages

MEMCOPY(entry.identifier, &(data[1]), 8); status = emberSetReplyBinding(SINK_BINDING_INDEX, &entry); if (status == EMBER_SUCCESS) { emberSerialPrintf(APP_SERIAL, "EVENT: sink set binding to sensor ["); printEUI64(APP_SERIAL, &(data[1])); emberSerialPrintf(APP_SERIAL, "]\r\n"); // send a message picking this sink // the data globalBuffer[0] = MSG_SENSOR_SELECT_SINK; MEMCOPY(&(globalBuffer[1]), emberGetEui64(), 8); // copy the data into a stack buffer buffer = emberFillLinkedBuffers((int8u*)globalBuffer, 9); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR can't send [sensor select sink], OUT OF BUFFERS\r\n"); return; } } // send the message status = emberSendDatagram(SINK_BINDING_INDEX, buffer); // done with the stack buffer emberReleaseMessageBuffer(buffer); }

Sending Datagrams
To send and receive datagrams, the stack requires an appropriate binding. The code example sets such a binding based on the EUI ID sent in the sink advertisement. We first verify that we do not already have binding for exchanging unicasts with the sink. To check for this, call emberGetBinding() and check the type field to ensure that it is an EMBER_UNUSED_BINDING. Because emberGetBinding() provides a copy of the binding rather than returning a pointer, this code provides storage for an EmberBindingTableEntry structure. The stack operates this way so that it can store some bindings in nonvolatile memory and others in RAM, depending upon the binding index used. The microprocessor on the Developer Kit RF communication module handles references to these memory types differently, so returning a pointer is inconvenient for the user application. Do not use emberBindingIsActive() to check the validity of a binding. This function checks something different: It determines whether the binding can safely be changed by checking for in-flight messages and active connections. If neither exist for the binding in question, a perfectly valid binding entry will return FALSE when the active check is made.

EmberNet Application Development Guide

120-0065-000A Final

Page 59

Chapter 5: Sample Sensor Applications

Sending and Receiving Messages

// The sensor fabricates data and sends it out to the sink. void sendData(void) { int16u data; EmberStatus status; EmberMessageBuffer buffer = 0; int8u i; // get a random piece of data data = firmGetRandom(); emberDebugPrintf("sensor has data ready: 0x%2x \r\n", data); // if we have a bind index for a sink node then // send it our data if (mainSinkFound == TRUE) { // the data - msg type, my address, and data globalBuffer[0] = MSG_DATA; MEMCOPY(&(globalBuffer[1]), emberGetEui64(), 8); for (i=0; i<(SEND_DATA_SIZE/2); i++) { globalBuffer[9+(i*2)] = HIGH_BYTE(data); globalBuffer[10+(i*2)] = LOW_BYTE(data); } // copy the data into a stack buffer buffer = emberFillLinkedBuffers(globalBuffer, 9 + SEND_DATA_SIZE); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [data], OUT OF BUFFERS\r\n"); return; } // send the message status = emberSendDatagram(SINK_BINDING_INDEX, buffer); // done with the stack buffer emberReleaseMessageBuffer(buffer); // print a status message printEUI64(APP_SERIAL, emberGetEui64()); emberSerialPrintf(APP_SERIAL, "TX [DATA] status: 0x%x data: 0x%2x\r\n", status, data); } }

EmberNet Application Development Guide

120-0065-000A Final

Page 60

Chapter 5: Sample Sensor Applications

Sending and Receiving Messages

The code runs on the sensor and sends the datagram, beginning by checking the binding to ensure that it has been set. Note again that we retrieve the binding table entry and check the type field rather than use emberBindingEntryIsActive(). The call to emberFillLinkedBuffers() allocates a buffer and fills it with the sensor data. After sending the datagram, it is the applications responsibility to release the buffer. In most applications it is important to verify that the datagram was delivered successfully. In this example, the sensor can reuse memory once a report is successfully delivered. To determine the fate of a sent message, we need to fill in the callback function emberMessageSent(). // Called when a message has completed transmission -// status indicates whether or not the message was // successfully transmitted. void emberMessageSent(int8u bindingTableIndex, EmberMessageBuffer message, EmberStatus status){ // print an error if a message can't be sent int8u* data; int8u length; data = emberMessageBufferContents(message); length = emberMessageBufferLength(message); if (status != EMBER_SUCCESS) { emberSerialPrintf(APP_SERIAL, "Error 0x%x: can't send message ", status); if (length > 0) { emberSerialPrintf(APP_SERIAL, "0x%x ", data[0]); if (length > 8) { emberSerialPrintf(APP_SERIAL, " to:"); printEUI64(APP_SERIAL, &(data[1])); } } } emberSerialPrintf(APP_SERIAL, "\r\n"); } This code examines the status associated with the datagram sent in the message. Acknowledged datagrams are reported as EMBER_SUCCESS. Messages not acknowledged within the timeout interval are lost. In this example, we print an error. Other applications, such as those with moving or power-cycled nodes, might deal with failed messages differently.

EmberNet Application Development Guide

120-0065-000A Final

Page 61

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

Leaf Node Sample Sensor Application


Many applications include leaf nodes, which do not participate in data packet routing. Temporary leaf nodes can be created by simply turning off routing, but permanent ones can be created with Ember's Leaf Node stack. These permanent leaf nodes must communicate with routing nodes that are running an application built with the EmberNet stack. Users familiar with 802.15.4 should note that Ember leaf nodes do not support the full feature set of the 802.15.4 leaf node device. The features that are supported, however, are fully compliant with the specification. The Leaf Node stack messaging model provides for single-hop communication from a leaf node to a parent device. The parent device then performs any routing within the network. This model allows leaf nodes to wake, send a message to a parent device, and then go back to sleep.

Note: Customers upgrading from EmberNet stack version 3.2 should be aware that although a
3.2 device can communicate with a 3.3 full-function device, the changes required to support leaf nodes mean that 3.3 leaf node devices and 3.2 devices cannot communicate with each other. Version 3.3 full-function devices are compatible with version 3.2 fullfunction devices and can communicate with them. For information about specific functions available to leaf node devices and full-function devices, see the Leaf Node Interface Guide and the EmberNet Stack Interface Guide, respectively.

Design of the Leaf Node Sensor Sample Application


The leaf node sample application establishes a network containing sleeping leaf nodes. Several models of messaging between full-function devices (FFDs) and leaf node devices can be demonstrated with the application. In the original sensor-sink application, the messaging model can be abstracted as follows:

Sink SA SSS SR D

Sensor

SA = Sink advertise (multicast), len=9 [MSG_SINK_ADV, eui(8)] SSS = Sensor select sink (datagram), len=9 [MSG_SENSOR_SELECT_SINK, eui(8)] SR = Sink ready (datagram), len=9 [MSG_SINK_READY, eui(8)] D = Data (datagram), len=variable [MSG_DATA, eui(8), data(2-84)]

EmberNet Application Development Guide

120-0065-000A Final

Page 62

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

By contrast, in the leaf node version of the sensor-sink application, the messaging model looks like this:

Sink SB LJ SAJ LD

Sensor-to-Leaf Node

SB = Sink beacon (beacon), len=3 [MSG_SINK_BEACON, BEACON_SINK_KEY(2)] LJ = Leaf join (link datagram), len=9 [MSG_SENSOR_ALLOW_JOIN, eui(8)] SAJ = Sink allow join (link datagram) LD = Leaf data In a wider network that includes FFDs other than the sink device, the following messaging model would be used. It mixes features from the original sensor-sink application and the leaf node sample application:

Sink SA SSS SR

Sensor-to-FFD

Sensor-to-leaf node device

SB LJ RAJ LD FD
SA = Sink advertise (multicast), len=9 [MSG_SINK_ADV, eui(8)] SSS = Sensor select sink (datagram), len=9 [MSG_SENSOR_SELECT_SINK, eui(8)] SR = Sink ready (datagram), len=9 [MSG_SINK_READY, eui(8)] SB = Sensor beacon, len=3 [MSG_SENSOR_BEACON, BEACON_SENSOR_KEY(2)] LJ = Leaf join (link datagram), len=9 [MSG_SENSOR_ALLOW_JOIN, eui(8)] RAJ = Sensor allow join LD = Leaf data FD = Forwarded datagram

EmberNet Application Development Guide

120-0065-000A Final

Page 63

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

Leaf Node Development


For recommended practices for developing leaf node applications, see Chapter 6, Developing Applications.

Leaf Node Initialization and Startup


Leaf node initialization and startup are similar to FFD initialization and startup. The following example of leaf node initialization and startup was taken from sensor_leaf.c. In this excerpt, emberInit() is called, and the networkParams structure is initialized with values (a PAN ID, a transmit power, and a radio channel, and relay is turned on) and passed to emberAssociate(), which establishes the network. // emberInit must be called before other EmberNet stack functions // Initialize the Ember Stack status = emberInit(reset); if (status != EMBER_SUCCESS) { emberSerialGuaranteedPrintf(APP_SERIAL,"error returned from emberInit:0x%x\r\n",status); if (status == EMBER_UNINITIALIZED_EUI64 || status == EMBER_INVALID_EUI64) { // Run to allow over-the-air configuration. while (TRUE) { __watchdog_reset(); emberTick(); } } else { assert(FALSE); } } // Bring the network up. networkParams.panId = 0; networkParams.enableRelay = TRUE; networkParams.radioTxPower = -1; networkParams.radioChannel = 0x0F; status = emberAssociate(&networkParams); if (status != EMBER_SUCCESS) { emberSerialGuaranteedPrintf(APP_SERIAL, "error returned from emberAssociate: 0x%x\r\n",status); assert(FALSE); }

EmberNet Application Development Guide

120-0065-000A Final

Page 64

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

Leaf Node Network Acquisition


To send data to the network, leaf nodes must find the EUI64 of an FFD, within one hop, that can act as a repeater. The selection of an FFD is application dependent and can be accomplished in three ways: Actively: The leaf node device broadcasts a message that generates a response from an FFD. Passively: Eligible FFDs beacon periodically, and the leaf node device waits to hear one. Statically: The leaf node device is configured at installation time to speak to only a single FFD. Beacons can be configured to generate this kind of periodic one-hop broadcast. Beacons are most often used in mobile leaf node device applications, where the beacon serves to advertise to the leaf node device that it is now within range of a network. Beacons can also be used as a method to keep wake and sleep cycles together across a larger network. Active discovery is the fastest way for a leaf node device to find an eligible FFD, but this approach may generate an undesirable amount of traffic in applications where many leaf node devices are searching at the same time. Passive discovery may be more appropriate for such applications, provided that the beacon interval is short enough to meet the latency requirements of the application. Static configuration may be appropriate for networks in which the leaf node device serves as a slave device to a particular FFD and has no useful information to send to the network if that FFD is not available. For example, in a building automation network, leaf node devices are generally statically bound upon commissioning to the particular control device (for example, a light switch to a bank of lights or a thermostat to a control valve). Changes to this type of static binding are undesirable since the network function is fixed based upon use. In the active and passive discovery scenarios, the leaf node device may hear from several eligible FFDs. In this case, the needs of the application should drive the selection mechanism. The simplest solution is to choose the first repeater heard. This option is suitable for a sensor network where all data is being gathered to a central location but is not appropriate for a building automation scenario. Once the leaf node device has chosen an FFD to act as a repeater, the application may continue to use the same FFD until it disappears, or it may employ a more complicated updating mechanism based on periodic rebroadcasts or incoming beacons. The following excerpt from sensor-ffd.c shows the sample application initiating beacons, a leaf node device sensor hearing the beacon and responding to it, and the FFD sensor then creating a binding to the leaf node device to allow messages to occur. void startSensorBeacons(void){ EmberStatus status; EmberMessageBuffer payload = 0; int8u beaconInterval = 10; int8u activeTime = 8; emberSerialPrintf(APP_SERIAL, "starting transmit of beacons\r\n"); emberSerialWaitSend(APP_SERIAL); // the payload of the beacon // msg type (1 byte), beacon key (2 bytes), globalBuffer[0] = MSG_SENSOR_BEACON;

EmberNet Application Development Guide

120-0065-000A Final

Page 65

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

globalBuffer[1] = HIGH_BYTE(BEACON_SENSOR_KEY); globalBuffer[2] = LOW_BYTE(BEACON_SENSOR_KEY); // copy the data into a packet buffer payload = emberFillLinkedBuffers((int8u*) globalBuffer, 3); // check to make sure a buffer is available if (payload == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [sensor beacon], OUT OF BUFFERS\r\n"); return; } // beacon Interval of 10 is roughly 16 seconds; status = emberTransmitBeacons(payload, beaconInterval, activeTime); // check status if (status != EMBER_SUCCESS) { emberSerialPrintf(APP_SERIAL, "TX ERROR [sensor beacon], status 0x%x\r\n", status); } else { emberSerialPrintf(APP_SERIAL, "EVENT: sensor has started sending beacons, status 0x%x\r\n", status); } emberSetOutgoingBeaconNotifyCounter(TRUE, 1); } The following excerpt from sensor_leaf.c shows the establishment of the leaf association with either a sensor or the sink. A sensor prefers to associate with the sink, but if a sink has not been found it will associate with a beaconing FFD sensor. // is this a beacon from a sink? if ((data[0] == MSG_SINK_BEACON) && (data[1] == HIGH_BYTE(BEACON_SINK_KEY)) && (data[2] == LOW_BYTE(BEACON_SINK_KEY))){ // if we don't have a sink then use this one if ((sinkFound == FALSE) && (waitingForSinkAllowJoin == FALSE) &&(waitingToRespond == FALSE)) { // if we have an ffd-sensor, ditch it ffdSensorFound = FALSE; sinkFound = TRUE; // we are acting on this beacon actingOnBeacon = TRUE; } else { emberSerialPrintf(APP_SERIAL, "; ignoring\r\n"); EmberNet Application Development Guide 120-0065-000A Final Page 66

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

return; } } // is this a beacon from a sensor? if ((data[0] == MSG_SENSOR_BEACON) && (data[1] == HIGH_BYTE(BEACON_SENSOR_KEY)) && (data[2] == LOW_BYTE(BEACON_SENSOR_KEY))){ // if we don't have a sink then use this one if ((sinkFound == FALSE) &&(waitingForSinkAllowJoin == FALSE) && (waitingToRespond == FALSE) && (ffdSensorFound == FALSE)) { // if we have an ffd-sensor, ditch it ffdSensorFound = TRUE; // we are acting on this beacon actingOnBeacon = TRUE; } else { emberSerialPrintf(APP_SERIAL, "; ignoring\r\n"); return; } } The leaf node device uses the following code to send the join message to the FFD from which it heard the beacon. This join request establishes who the leaf node device communicates with in the network. // this sends a leaf join to the selected device (either sink // or ffd-sensor) void sendLeafJoin() { EmberStatus status; int8u localTerminal = 9; int8u remoteTerminal = 9; // first byte is length: msg type(1) + eui(8) = 9 globalBuffer[0] = 9; globalBuffer[1] = MSG_LEAF_JOIN; // the data MEMCOPY(&(globalBuffer[2]), emberGetEui64(), 8); // send the message status = emberSendDatagram(sinkEui64, localTerminal, remoteTerminal, globalBuffer); }

EmberNet Application Development Guide

120-0065-000A Final

Page 67

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

The FFD uses the following code to establish a binding with a leaf node from which it has received a join request. void handleLeafJoin(int8u* data) { EmberBindingTableEntry entry; EmberStatus status; EmberMessageBuffer buffer = 0; int8u freeBindingLocation = 0; int8u duplicate = 0; // We set the binding to the leaf so that we can send a message // to the leaf indicating that it has successfully joined // the network. // No binding would be necessary for applications that // do not send messages to their leaf nodes. // Find a free binding location to put this binding freeBindingLocation = findFreeBindingLocation(); if (freeBindingLocation == EMBER_NULL_BINDING) { emberSerialPrintf(APP_SERIAL, "WARNING: no more free bindings for this sensor-ffd-node\r\n"); return; } // check for a duplicate message, if duplicate then ignore duplicate = checkForBindingDuplicates(&(data[1])); if (duplicate == TRUE) { emberSerialPrintf(APP_SERIAL, "receive duplicate message from "); printEUI64(APP_SERIAL, &(data[1])); emberSerialPrintf(APP_SERIAL, ", ignoring\r\n"); return; } // add a binding to freeBindingLocation entry.type = EMBER_LINK_BINDING; entry.local = emberMakeTerminal(ENDPOINT, 1); entry.remote = emberMakeTerminal(ENDPOINT, 1); MEMCOPY(entry.identifier, &(data[1]), 8); status = emberSetReplyBinding(freeBindingLocation, &entry); ticksSinceLastHeard[freeBindingLocation] = 0; emberSerialPrintf(APP_SERIAL, "EVENT: sensor-ffd set binding %x to node [",freeBindingLocation ); printEUI64(APP_SERIAL, &(data[1])); emberSerialPrintf(APP_SERIAL, "]\r\n");

EmberNet Application Development Guide

120-0065-000A Final

Page 68

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

if (status != EMBER_SUCCESS) { emberSerialPrintf(APP_SERIAL, "TX ERROR [sensor allow join], binding failed, status 0x%s\r\n", status); return; } // send a message indicating success globalBuffer[0] = MSG_SENSOR_ALLOW_JOIN; MEMCOPY(&(globalBuffer[1]), emberGetEui64(), 8); // copy the data into a packet buffer buffer = emberFillLinkedBuffers((int8u*)globalBuffer, 9); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [sensor allow join], OUT OF BUFFERS\r\n"); status = emberDeleteBinding(freeBindingLocation); emberSerialPrintf(APP_SERIAL, "EVENT deleting binding 0x%x, status 0x%x\r\n", freeBindingLocation, status); return; } // send the message status = emberSendDatagram(freeBindingLocation, buffer); // done with the packet buffer emberReleaseMessageBuffer(buffer); At this point, beacons have been initiated on an FFD, the leaf node device has heard the beacon and sent a join request, and the FFD has used this join to ask if can set a binding to the leaf node device.

Routing from a Leaf Node Device


As noted above, a leaf node device can only send data to an FFD that is one hop away. The FFD is responsible for routing this data within the network. The leaf node device data can be sent as one of the following: An acknowledged message to the FFD to which the leaf node device is associated. A one-hop broadcast that any FFD within range can route. In the following excerpt from sensor_leaf.c, the sensor tracks the beacon and forwards data to the FFD after a random delay. // this is common code that is executed if we act on a // beacon from either a sink or an ffd-sensor if (actingOnBeacon == TRUE) { // we are now waiting to respond - don't want all //leaf nodes to respond at the same time waitingToRespond = TRUE;

EmberNet Application Development Guide

120-0065-000A Final

Page 69

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

emberSerialPrintf(APP_SERIAL, "; processing message\r\n"); emberSerialWaitSend(APP_SERIAL); MEMCOPY(&(sinkEui64[0]), &(sender[0]), 8); // start tracking the beacon status = emberBeaconTrack(TRUE); beacon, status 0x%x\r\n", status); // wait for 0.1 - 3 seconds before responding respondTimer = ((firmGetRandom()) % 15) + 1; timeToWaitForSinkReadyMessage = TIME_TO_WAIT_FOR_SINK_READY; emberSerialPrintf(APP_SERIAL, "EVENT: waiting %x ticks before reponding\r\n", respondTimer); emberSerialWaitSend(APP_SERIAL); return; } ... if (readyToSendData == TRUE) { sendDataCountdown = sendDataCountdown - 1; if (sendDataCountdown < 1) { // delay sending data if we are asleep if (isAwake == FALSE) { sendDataCountdown = 1; } else { sendDataCountdown = SEND_DATA_RATE; sendLeafData(); } } } // The sensor-leaf fabricates data and sends it out to the sink void sendLeafData(void) { int16u data; EmberStatus status; int8u localTerminal = 9; int8u remoteTerminal = 9; // length is msg type (1 byte), eui (8 bytes), and data // (length byte does not count in length) int8u length = SEND_DATA_SIZE + 9; int8u i; ...

EmberNet Application Development Guide

120-0065-000A Final

Page 70

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

// the data - length, msg type, my address and data globalBuffer[0] = length; globalBuffer[1] = MSG_LEAF_DATA; MEMCOPY(&(globalBuffer[2]), emberGetEui64(), 8); for (i=0; i<(SEND_DATA_SIZE/2); i++) { globalBuffer[10+(i*2)] = HIGH_BYTE(data); globalBuffer[11+(i*2)] = LOW_BYTE(data); } // send the message status = emberSendDatagram(sinkEui64, localTerminal, remoteTerminal, globalBuffer); The user application on the FFD can use the EmberNet stack API to route the message to its final destination. In some applications the FFD may already know the final destination. For example, in a sensor network the FFD will already know about the gateway device and will be able to route the packet accordingly. In more complicated applications, the leaf node device may need to specify the final destination within its own packet. Then the FFD can interpret the destination and relay accordingly. For example, in networks that place a premium on reliability, leaf node devices may broadcast messages to all known eligible FFDs, specifying a unique identifier in the payload that allows the destination to avoid processing duplicates. In networks that place a premium on battery life, leaf node devices may instead first try to transmit to a known FFD and ignore several failures before spending extra processor and radio time to rediscover eligible FFDs. The following excerpt from sensor_ffd.c handles the incoming data from a leaf node device sensor and sends it to an associated sink. // forwards a datagram received from a leaf to the sink that this // sensor-ffd is currently hooked up to void forwardLeafDataToSink(EmberMessageBuffer leafMessage) { EmberStatus status; EmberMessageBuffer buffer = 0; int8u* data; int8u length; // check for the case where the sink is gone but the leaf hasn't // noticed that this sensor-ffd is no longer beaconing if (mainSinkFound == FALSE) { emberSerialPrintf(APP_SERIAL, "ERROR: can't forward leaf data; no longer have a sink!\r\n"); return; } // pull out the data from the message data = emberMessageBufferContents(leafMessage); EmberNet Application Development Guide 120-0065-000A Final Page 71

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

length = emberMessageBufferLength(leafMessage); // the data - msg type, my address and data globalBuffer[0] = MSG_PROXY_DATA; // don't copy over the msg type from the leaf MEMCOPY(&(globalBuffer[1]), &(data[1]), length); // copy the data into a packet buffer buffer = emberFillLinkedBuffers(globalBuffer, length); // check to make sure a buffer is available if (buffer == EMBER_NULL_MESSAGE_BUFFER) { emberSerialPrintf(APP_SERIAL, "TX ERROR [proxy data], OUT OF BUFFERS\r\n"); return; } // send the message status = emberSendDatagram(SINK_BINDING_INDEX, buffer); // done with the packet buffer emberReleaseMessageBuffer(buffer);

Routing to a Leaf Node Device


Routing to a leaf node device depends on network type and the sleep-wake cycle of the leaf node device. In many cases, leaf node devices are sensor inputs to the system and are rarely expected to receive any messages. For systems requiring leaf node device parameters to be updated or leaf node device configurations to be modified, the application must choose a method for routing data to leaf node devices. The choice of method is influenced by how leaf node devices are acquiring and maintaining contact with the network. Following are three typical use cases: Building automation scenario: Leaf node devices are bound to a particular FFD at startup, and changes are infrequent. Messages are routed to particular FFDs for forwarding to the leaf node devices bound to them. The FFD can only forward the message to a leaf node device when the leaf node device wakes and sends data to the FFD. This store-and-forward capability must be implemented by FFDs if the application requires data to be sent to sleeping leaf node devices. Mobile leaf node device scenario with periodic beacons: Leaf node devices associate with a network and periodically listen to the beacon for coordination. A leaf node devices ID is broadcast with a beacon, to notify the leaf node device that it has a message pending. When the identified leaf node device receives this beacon, it requests the message from the FFD. Distributed sensor network with fixed leaf node devices and FFDs: The gateway device knows which FFD has forwarded a message from a leaf node device and uses this information to route a message to the FFD for forwarding. You can employ a network broadcast to discover information about a particular leaf node device, but doing so can consume a lot of bandwidth. It is usually a better idea to search for a solution that takes advantage of the knowledge the application already has about the possible locations and movements of nodes.

EmberNet Application Development Guide

120-0065-000A Final

Page 72

Chapter 5: Sample Sensor Applications

Leaf Node Sample Sensor Application

Beacons
The design requirements of your project will decide whether you should use beacons and how to set them up. FFDs can send beacons, and both FFDs and leaf node devices can receive and track them. See Sending and Receiving Beacons on page 45 if you intend to use beacons in your application. As described above, beacons can be used to synchronize and advertise a network. When they are used for advertisement, a leaf node device can look for these to know if the network is on, or in the area.

Battery Life
The key parameters determining battery life are availability, minimum necessary on-time, and, for networks with mobile nodes, discovery time. If extending battery life is important for your application, the leaf node device should sleep as much as possible. In dynamic networks, discovery time is established by the amount of time a mobile device is within range of the network. For example, if the device will be within range for only a few minutes, the time available for discovery will be short. A requirement for fast discovery times means that leaf node device sleep-wake cycles must be short, which will reduce battery life. In fixed networks, network discovery time does not affect battery life because leaf node devices only perform discovery when they associate to a particular FFD, a process that takes only a few minutes. A leaf node devices sleep-wake cycle determines its responsiveness to a network message. Some leaf node devices do not need a sleep-wake cycle (for example, a light switch leaf node device that only wakes and sends a message when the switch is changed). A leaf node device that only wakes on actuation will have maximum battery life, but the network can never communicate with it. Typically, such a device periodically wakes and communicates with its FFD as a heartbeat, to validate that the device is present and the battery power is adequate. Alternatively, some leaf node devices are required to receive data from the network at regular intervals. For example, a leaf node device that is a thermostat may not only send data to its FFD but also display the control state of the local HVAC unit. The application for such a leaf node device should select an update rate that is suitable for the responsiveness of this display but balances with the battery life of the device. If the device is always on, any change of state will be displayed very quickly, but the battery life will be short. If the developer determines that a four-second display update rate is acceptable, the leaf node device can have a four-second wake/sleep cycle.

EmberNet Application Development Guide

120-0065-000A Final

Page 73

CHAPTER 6

Developing Applications

Development Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Developing Full-Function Device Applications . . . . . . . . . . . . . . . . . . . 74 Developing Leaf Node Applications. . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Building Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 About IAR Embedded Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Creating an IAR Workspace File from the Application Template File . 75 Familiarizing Yourself with the IAR Embedded Workbench . . . . . . . . . 76 Building with the Debug Version of the EmberNet Stack . . . . . . . . . . . 76 Building with the Release Version of the EmberNet Stack . . . . . . . . . . 77 Building for the Atmega64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Building with the EmberNet Leaf Stack. . . . . . . . . . . . . . . . . . . . . . . . . 77 Debugging Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Adding Debug Features to an Application . . . . . . . . . . . . . . . . . . . . . . 78 Viewing Application Debug Messages. . . . . . . . . . . . . . . . . . . . . . . . . 78 Viewing Debug Messages Via the Serial Port . . . . . . . . . . . . . . . . . . . 80 Using the Ember Studio Backchannel Debug Tools . . . . . . . . . . . . . . . 80 Uploading Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Choosing the Correct Upload Method for an Application . . . . . . . . . 81 Uploading Via Ember Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Uploading Via the Ember Development Board Serial Line Connection81

Development Overview
Developing Full-Function Device Applications
Ember provides several tools to make the development of full-function devices easy: the bootloader, the Development Kit hardware, and a debug version of the EmberNet stack. We recommend that you first develop your application using the Development Kit development boards and the debug version of the EmberNet stack. This will allow you to rapidly detect and understand unexpected or incorrect behavior. If your development boards are connected using the

EmberNet Application Development Guide

120-0065-000A Final

Page 74

Chapter 6: Developing Applications

Building Applications

Ethernet backchannel, you will also be able to simultaneously update all modules with new software, further reducing development time. When you have custom hardware available, you can test it using the Ember Rangetest application and then, if necessary, adapt the Ember HAL to your custom hardware. You can test your HAL by using a simple sample application, to reduce the complexity and possible errors. Once you are satisfied with the behavior and performance of your application on the development boards, you can move your software to your custom hardware by changing the HAL from the Ember development board HAL to the pre-tested HAL that your hardware uses.

Developing Leaf Node Applications


The Leaf Node stack can be run on any Atmel ATmega that can hold both the stack and the application code. In most cases the smallest processor that can be used effectively will be the Atmega16L. For information on connecting an Atmega16L to an EM2420 for use as a leaf node device, see Application Note 5015, Design of an IEEE 802.15.4-Compliant, EmberNet-Ready Leaf Node Module Using the EM2420 Radio Frequency Transceiver. The leaf node application can be developed and debugged using the normal development hardware, which is highly recommended because the physical constraints of small microprocessors make it challenging to develop applications for them: Fewer pins are available for use as debugging output, and a smaller flash size means that there is no room for a bootloader, debug cases, or printouts. Ember recommends that you first target software at the Developer Kit carrier board's ATmega128 (or your custom board with the ATmega128 or ATmega64) and migrate to the smaller ATmega16 when the software is stable. As with moving to custom hardware on the full-function device development, Ember's HAL is the only software that needs to change when moving between the ATmega128/64 and the ATmega16. If you encounter problems, you can easily move back to the ATmega128/64, debug the application, and return to the ATmega16. Note that this flexibility also allows you to use an ATmega32 or any other Atmel chip that meets your project requirements.

Building Applications
About IAR Embedded Workbench
Ember supports only the IAR Embedded Workbench for application building. The release notes for your Developer Kit will specify the version of IAR to use. Please refer to the IAR documentation for information on installing and using the program.

Creating an IAR Workspace File from the Application Template File


The Developer Kit provides an application template file that can be modified and used as the IAR workspace (.eww) file for an application. The name of the application template file specifies the radio in your Developer Kit (for example, simple-em2420-8mhz.eww). This chapter will refer to this file as simple-<yourRadio>.eww. When compiled and uploaded to an RF communication module, the application template file causes a Developer Kit carrier board LED to blink. Ember provides both debug and release builds of the application template file. The debug build adds debug features to your code and enables Ember Studio debugging. The release build does not implement the debug features, resulting in smaller and faster-running code. The sources for the application template file have been preorganized into IAR groups to speed the process of building.

EmberNet Application Development Guide

120-0065-000A Final

Page 75

Chapter 6: Developing Applications

Building Applications

Familiarizing Yourself with the IAR Embedded Workbench


If you are not familiar with the IAR Embedded Workbench, we suggest that you make a practice build of the application template file. To build the application template file: 1. Browse to the stack sample applications directory and double-click the workspace file named simple-<yourRadio>.eww. IAR displays a project window for the file. All available versions, or configurations, of the sample project file are listed in the Configurations file drop-down list. The window displays a folder tree for the groups in the first configuration that is listed in the drop-down. Select either the debug or the release version of the configuration that matches the radio in your Developer Kit. The project window displays the groups into which the source files for this configuration have been organized. You will find main.c in the App group. Select Project > Make. A progress window displays, showing build status information, including errors and warnings. If no compiler errors were made, an output file is stored at build\simple_<yourRadio>\Exe\simple-<yourRadio>.lbin (for example: build\simpleem2420\Exe\simple_em2420.lbin). Select Project > Make. A progress window displays, showing build status information, including errors and warnings. If no compiler errors were made, an output file is stored at build\simple_<your Radio>\Exe\simple-<yourRadio>.bin (for example: build\simple_em2420\Exe\simple-em2420.bin).

2.

3.

4.

Building with the Debug Version of the EmberNet Stack


To access the EmberNet stacks real-time API debugging facilities, the application must be built with the debug version of the stack. Stack debug messages can be analyzed in Ember Studio to debug network behavior in real time. For information on how to set up and use the debug backchannel, see Chapter 6 of the Ember Studio Users Guide. To build with the debug version of the stack: 1. Open the sample workspace file by double-clicking the file or selecting File > Open. IAR displays a project window for the file. All available versions of the sample file are listed in the Configurations drop-down list. The window displays a folder tree for the projects in the first configuration listed in the drop-down. Select Project > Edit Configurations. The Configuration window displays. Click New. The New Configuration window displays. Enter a name. In the Based On Configuration list, select simple-<yourRadio>-Debug, which is the debug stack target for the project file. Select Debug from the Factory Settings portion of the window, to indicate that this will be a debug configuration. Click OK. The New Configuration window closes, returning you to the Configurations window. The new configuration that you made will now become the active configuration for building, as indicated by the current selection of the Configuration drop-down list. Select the App group from the project view and press the DELETE key, or right-click the group name and select Remove. Click Yes when prompted to confirm the deletion. Enter a group name. This group will contain the files specific to your application. Click OK. The Add Group window closes. In the workspace window, select the new configuration from the Configurations drop-down list (at the top of the window), and then select the group to which you want to add files. 120-0065-000A Final Page 76

2. 3.

4. 5.

6. 7. 8. 9.

EmberNet Application Development Guide

Chapter 6: Developing Applications

Debugging Applications

10. Select Project > Add Files. Select the file or files you wish to include in the group and click Open. 11. Select the top level of the tree, and then right-click this item and select Options, or select Project > Options from the menu. The Project Options dialog opens. 12. Select the XLINK category from the list at the left of the window. A tabbed window displays. 13. In the Output tab, in the Output File box, make sure that Override default is checked, and type a name for the output file. The output filename must have the .lbin postfix. 14. Click OK. The Project Options dialog closes. 15. Select Project > Make. The IAR Embedded Workbench will try to build your application. If the build is successful, the output file that you specified is generated (with the .lbin extension). If the build fails, the Messages window displays error messages. 16. When the output file is built, add this file to the file group you created for your application files (similarly to how you added the group in step 9). Including this file as part of a group ensures that the post-processing tool that converts the .lbin file into a .bin file (etrim.exe) runs whenever your .lbin file is rebuilt. Only .bin files can be uploaded to Developer Kit hardware.

Building with the Release Version of the EmberNet Stack


Building an application with the release version of the EmberNet stack is just like building with the debug version, with one exception: In step 3, select simple-<yourRadio>, which is the release target for the project file (for example, simple-em2420).

Note: Be careful not to select the similarly named simple-<yourRadio>-Debug.

Building for the Atmega64


Debug and release versions of the EmberNet stack are also available for the Atmega64. For a detailed description of how to build your application for the Atmega64 target, please see Application Note 5010, Compiling Ember Applications for the ATmega64 Microprocessor.

Building with the EmberNet Leaf Stack


Applications using the Ember leaf node stack are compiled in much the same way as applications using the full-function stack. To build a leaf node application, you must select the Leaf Node stack instead of the EmberNet stack, and you must include ember-leaf.h and not ember.h.

Debugging Applications
Debugging applications in a live network environment is challenging. Traditional debugging methods such as setting breakpoints and examining variables are of little use, because the act of applying them itself changes network behavior. In effect, you end up debugging a network that is different from the network that the application sets up. The Developer Kit provides a flexible and powerful set of debugging tools that sidestep these difficulties: A debug build of the EmberNet stack that supports an Ethernet debugging backchannel as well as providing debugging data. A set of debug functions in the EmberNet stack. A real-time debugger inside Ember Studio that displays debug messages (the Debug Reader). The ability to debug via serial connection to a single node. The Ember Studio backchannel debugging tools. EmberNet Application Development Guide 120-0065-000A Final Page 77

Chapter 6: Developing Applications

Debugging Applications

When debugging is complete, you can build the final application with the release build of the EmberNet stack, which lacks debug features and thus produces smaller, faster code. Ember provides only a release build of the Leaf Node stack.

Adding Debug Features to an Application


The debug build of the EmberNet stack implements the following features: Support for the Developer Kit carrier board debug backchannel, which allows you to debug applications using the Ember Studio Debug Reader. Information about the timing and parameters for important stack API calls. Information about the timing and payload data of packets sent and received by the application. Support for debugging messages using printf. Improved parameter checking for stack API calls. To use the debug build of the EmberNet stack: To enable stack debug features for an application, link the application against the debug build and define and initialize the emulator/debug module port via emberDebugInit(). This causes the application to send binary debug messages to the debug port of the emulator/debug module (by default, serial port 0, or port 4900 on the emulator/debug module). For more information about the emulator/debug module ports, see Chapter 5 of the Ember Developer Kit Users Guide. To use the debug API functions in a application, you must: Call emberDebugInit() in your application before emberInit(). Its only parameter is the serial port that you will be using for the debug backchannel. For information on determining a serial port to use for the debug backchannel, see Chapter 5 of the Ember Developer Kit Users Guide. Call emberSerialBufferTick() in the main loop of your application. The debug system utilizes the serial code in buffered mode, which requires this call.

Viewing Application Debug Messages


You can view application debug messages via the Ember Studio Debug Reader or a serial line.

Viewing Debug Messages Via the Ember Studio Debug Reader


For nodes that are connected to Developer Kit carrier boards, the Ember Studio Debug Reader provides an easy-to-use debugging interface. The Debug Reader displays the following types of debug messages: Resets Printf output API traces (see Table 6-2) Asserts Core dumps API packet traces for reception API packet traces for transmission For information about using the Debug Reader, including the data provided for each type of debug message, see Chapter 6 of the Ember Studio Users Guide.

EmberNet Application Development Guide

120-0065-000A Final

Page 78

Chapter 6: Developing Applications To use the Debug Reader:

Debugging Applications

To use the Debug Reader, nodes must be set up in a backchannel network. In this type of network the emulator/debug module is configured to intercept application debug messages from a nodes serial port and route them to the Ethernet. Ember Studio aggregates the Ethernet messages and displays them in the Debug Reader. For information on setting up a backchannel network, see Chapter 4 of the Ember Developer Kit Users Guide.

Table 6-1: EmberNet Stack APIs Traced in the Debug Reader


emberEnableRouting() emberSetRadioChannel() emberSetRadioPower() emberSleep() emberWakeUp() emberSetBinding() emberDeleteBinding() emberStartEndpointSearch() emberStopEndpointSearch() emberEndpointFoundHandler() emberOpenConnection() emberCloseConnection() emberSendDatagram() emberSendLimitedMulticast() emberSendSequenced() emberSendDatagramFromTerminal() emberSendMulticastFromTerminal() emberSendSequencedFromTerminal() emberCancelMessage() emberSendReply() emberSetReplyBinding() emberConnectionStatusHandler() emberMessageSent() emberIncomingMessageHandler() emberStackStatusHandler()

EmberNet Application Development Guide

120-0065-000A Final

Page 79

Chapter 6: Developing Applications

Debugging Applications

Viewing Debug Messages Via the Serial Port


Debug messages may be sent to either of the two carrier board serial ports or to the TTL header by properly configuring the carrier boards serial configuration array headers. To change the carrier board serial port settings, connect to the carrier board backchannel administrative socket (4902) and issue the port command. For information on configuring the serial configuration array headers, see the Ember Developer Kit Carrier Board Technical Specification. For information on connecting to the backchannel socket and issuing commands, see Chapter 5 of the Ember Developer Kit Users Guide. Note that Ember does not supply a TTL cable. Debugging via a serial port has the advantage of not altering over-the-air transmission, but it can be cumbersome. Several debug functions provide information by the serial route, for example, emberSerialInit() and emberSerialPrintf(). The downsides of serial port debugging are that you can debug only one node at a time and it is difficult to map the timing of messages because they are in different terminal windows.

Using the Ember Studio Backchannel Debug Tools


In addition to the Debug Reader, Ember Studio provides the following debugging tools, all of which are available via the backchannel: Reset nodes: Allows you to restart nodes that are not responding or not behaving properly. Power cycle nodes: Allows you to reboot an application that fails or locks up, and allows you to generate a node reboot message for testing or application development purposes. View node configuration data: Allows you to view the following parameters: Hostname Version of emulator/debug module Software version of emulator/debug module Build timestamp of emulator/debug module software Configuration (DHCP or static) Netmask IP address Gateway Port speed Port settings For information on using these tools, see Appendix A of the Ember Developer Kit Users Guide.

EmberNet Application Development Guide

120-0065-000A Final

Page 80

Chapter 6: Developing Applications

Uploading Applications

Uploading Applications
Choosing the Correct Upload Method for an Application
Table 6-2 lists the methods available for uploading different types of applications.

Table 6-2: File Upload Methods Application (File Type)


EmberNet stack application (.bin)

Upload Method/s
Ember Studio or Ember development board serial line connection, to upload to a device that is mounted on an Ember development board. Direct serial connection to a custom device, to upload an EmberNet application to the device for the first time.

Leaf node application (.hex) Bootloader application (.hex) EmberNet stack tokens (.ebin) Leaf Node stack tokens (.ehex)

ISP programmer ISP programmer Serial line ISP programmer

Uploading Via Ember Studio


You may use Ember Studio to upload an application to devices that can connect to Ember Studio and that are mounted on the Ember development board. Ember Studio provides three uploading methods: over the air, over the Ethernet backchannel, and over a serial connection. The over-the-air and Ethernet backchannel methods allow you to upload to multiple devices at a time. The serial connection method is restricted to one device at a time. For information on using these methods, see Chapter 5 of the Ember Studio Users Guide.

Uploading Via the Ember Development Board Serial Line Connection


Using a Terminal Emulator to Perform a Serial Upload
You must use this method to upload a token file to a device. You may also use it to upload an EmberNet application to a device. You can use any terminal emulator, as long as it is configured as described in the procedure. To upload over a serial line using a terminal emulator: 1. Put the device into bootloader mode, using one of these methods: Manual method: Press and hold the carrier board bootload button, press and release the RF communication module reset button, then release the bootload button (to locate these buttons, see Figure 6-1). Online method: Issue the bootload backchannel command over the backchannel administrative port. (For information on the bootload command and on issuing backchannel commands, see Chapter 5 of the Ember Developer Kit Users Guide.) When the node enters bootloader mode, two LEDs on the carrier board and two LEDs on the RF communication module flash simultaneously. EmberNet Application Development Guide 120-0065-000A Final Page 81

Chapter 6: Developing Applications 2. 3.

Uploading Applications

Locate the serial configuration array headers on the board (see Figure 6-1). Write down the existing configuration of the headers so that you can restore it when you are done. Configure the headers as shown below. This configuration allows the RF communication module to receive data over a DB-9 connection. (For more information on this specific configuration and on configuring the headers in general, see the Ember Developer Kit Carrier Board Technical Specification.) J27 J28 J29 J25 J26

4. 5.

Connect carrier board serial port 1 (see Figure 6-1) to a computer serial port. Open a terminal emulator and set its com port settings to 19200, N, 8, 1, no flow control. The bootloader menu displays: 3219 8 MHz EM2420 1.program upload (.bin image) 3.run program image 7.stack and application token defaults (.ebin image) 8.application token defaults (.ebin image) 6.Enter the option number for the type of file you are uploading. The terminal will echo begin upload. Transfer the .ebin file using the XModem protocol.

6.

When the upload finishes, the upload complete message displays.

Note: If the upload terminates with an error, repeat the upload procedure until it terminates
successfully. 7. 8. Optional: Use option 3 to run the application on the node. Restore the serial configuration array headers to their original configuration.

EmberNet Application Development Guide

120-0065-000A Final

Page 82

Chapter 6: Developing Applications

Uploading Applications

Using Ember Studio to Perform a Serial Upload


You may use this method to upload an EmberNet stack application to a single device. To upload over a serial line using Ember Studio: 1. 2. Perform steps 1 to 4 of the preceding procedure. In Ember Studio, select Tools > Bootloader. The Select Bootload Mode window displays.

3.

Select Serial. The Serial Bootload window displays.

4.

Enter the com port and browse to the image file to upload. Click Bootload. Ember Studio displays the progress of the upload in the status bar. The upload is done when the node beeps and the status bar says Successful. You can close the window at that point.

Note: If the upload terminates with an error, repeat the upload procedure until it terminates
successfully. 5. Optional: Restore the serial configuration array headers to their original configuration.

EmberNet Application Development Guide

120-0065-000A Final

Page 83

Chapter 6: Developing Applications

Uploading Applications

Uploading Via an ISP Programmer


Use this method to upload the bootloader to a device or a application to a leaf node. Only .hex and .ehex files can be uploaded with an ISP device. For information about using an ISP programmer, see Application Note 5001, Bringing Up Custom Nodes.

EmberNet Application Development Guide

120-0065-000A Final

Page 84

Chapter 6: Developing Applications

Uploading Applications

Figure 6-1: Developer Kit carrier board layout

Serial Port 0

Serial Port 1

Buzzer

RF Communication Module

White triangle

Emulator/Debug Module EM4 RF Communication Module LEDs EM5 EM3 Serial Configuration Array Headers 10/100 Controller Chip Emulator/Debug Module LEDs

EM3: RF Comm. Module Reset Button EM4: Bootloader Button EM5: Emulator/Debug Module Reset Button

RJ-45 Connector

Power Jack

EmberNet Application Development Guide

120-0065-000A Final

Page 85

APPENDIX A

Creating a .ebin File

A .ebin file is a binary image of EEPROM data. EmberNet stack tokens must be compiled into this type of file before they can be uploaded to a node. To create a .ebin file, you must use IAR Embedded Workbench (EW) version 3.10D. To create a .ebin file: 1. Either create an additional build target (called a configuration in IAR Embedded Workbench) and add it to the project that you are using to build the application or import a project from a previous version. Select Edit Configurations from the Project menu. Click New in the window that opens. The New Configuration window displays.

2.

3.

In the Name field, enter a title for the configuration. In the Based on configuration drop-down list, select the release configuration used to produce your program image. Select Release in the Factory settings field. Click OK to add the configuration and OK again in the Edit Configurations window. The workspace view returns. Select the configuration that you just created from the drop-down list at the top of the workspace view. The active configuration changes to the new one, with all nodes (files and groups) included in the build.

4. 5.

EmberNet Application Development Guide

120-0065-000A Final

Page 86

Appendix A: Creating a .ebin File 6. To omit files or groups that you dont want to include, such as debug files, right-click them and select Options from the context menu to display the Options window. Select Exclude from build and click OK. Right-click on the top-most node in the project and select Options from the context menu. The Options window displays. Select the XLINK category, then click the Output tab. Make sure that Override default is checked and that the filename below ends in the .ebin extension, not the .bin extension. You should not need to change any other settings in this tab. In the XLINK category, select the Extra Options tab. Change the command line option -y(CODE) to -y(XDATA). The -w6 argument is optional. Select the Custom Build category and make sure that all fields are blank. (No additional processing is needed to produce a suitable EEPROM image once the .ebin file has been linked.)

7.

8. 9.

10. Select Make from the Project menu, or press F7. IAR Embedded Workbench builds the .ebin file in the same directory as the .lbin and .bin files that were created during the building of the program image.

EmberNet Application Development Guide

120-0065-000A Final

Page 87

Вам также может понравиться