Sie sind auf Seite 1von 55

Departm ent of Electrical & Com puter Engineering Ryerson University Toronto, Canada.

ELE800: Engineering Design Project - Final Report

Low Power Embedded System with Zigbee Wireless Connectivity


For:

Professor K. Clowes
April 11 th, 2006

Prepared by:

Balkar Jagpal - 4th year, Electrical Engineering Program Harpreet Singh - 4th year, Electrical Engineering Program

TABLE OF CONTENTS

Abstract .................................................................. Introduction............................................................. Objective................................................................. Theory..................................................................... Hardware Design..................................................... Software Design...................................................... Parts List....................................................... Schematics....................................................... Performance Specifications....................................................... Performance Analysis.............................................. Conclusions............................................................. References.............................................................. Appendix A............................................................... Appendix B...............................................................

3 4 6 7 10 12 15 18 20 21 24 27 29 58

ABSTRACT

The focus of Zigbee technology is centered around self-forming and self-healing adhoc wireless networks with star, tree, and mesh topologies being supported. The application developer need not worry of technical details surrounding network formation, as these conditions are established and maintained by the protocol itself. Zigbee is considered ideal for many control, and remote monitoring applications. Being a relatively simple protocol, Zigbee can be implemented on low-cost hardware consisting primarily of a 2.4GHz radio transceiver in tandem with a low power, 8-bit microcontroller. W hile other wireless communication standards- including Bluetooth- are limited to a few dozen nodes at best, Zigbee can theoretically support a network of up to 64,000 individual nodes. The transmission range between Zigbee modules varies between 30-300 meters, depending upon several factors including the presence of concrete barriers, and the transceiver power characteristics.

To examine the suitability of Zigbee technology for relatively simple embedded applications, a design project was proposed; essentially a low power embedded bicycle computer utilizing the Zigbee protocol to facilitate wireless data transfer. This device will consist of two network nodes one for sensing purposes, and the other for data display via an LCD. To carry out the required tasks, several technologies are applied: transducer based sensors for determining wheel rotation; microcontroller facilities for data processing; and RF transceivers for wireless data communication. This design proposal not only allowed for practical implementation within a restricted time frame, but also to an extent demonstrates the capabilities of the Zigbee protocol, within the context of low power, wireless embedded applications.

INTRODUCTION
It is clear that embedded systems have become an integral part of everyday life. Found in home appliances, automobiles, and even in advanced spacecraft - these systems are depended upon to carry out a boundless variety of tasks. Vast amounts of research and development have gone into the design and implementation of embedded systems, however the area of wireless data transfer across these systems has for the most part been left to proprietary solutions. The potential applications of wireless data communication are seemingly limitless; Although some wireless technologies can provide reliable, standards oriented data transmission, they are not particularly suitable for applications with low bandwidth requirements. As well, the energy consumption of devices employing these protocols is extremely high, often requiring large batteries or a fixed power supply. W ith these shortcomings and limitations being addressed, another protocol has recently emerged - the Zigbee wireless protocol. Zigbee is a standards based technology that facilitates wireless communication with design emphasis being placed on low cost, low power consumption, and interoperability between all Zigbee compliant devices.

Figure 1 - Current Wireless Standards

The associated data transmission rate tops out at approximately 250 kilobits per second, however for a multitude of monitoring and control applications, this is more than sufficient. The protocol itself has been developed by the Zigbee Alliance, an industry consortium with over 150 members including Freescale, Samsung, and Panasonic. Currently the Zigbee protocol is experiencing rapid growth in both the industrial sector and that of consumer electronics. It is in particular, an attractive option for use in remote monitoring applications. It has been forecast that over 80 million Zigbee enabled devices will be shipped by the end of 2006, demonstrating the broad popularity and demand for this emerging technology.

OBJECTIVE
As required in ELE 700/800, students must research and carry out the design of a device that falls within the realms of electrical and computer engineering. Although there were many interesting project topics available, one in particular involved several aspects of the discipline, namely the wireless bicycle computer. Traditionally, this device gathers information regarding a bicycle ride and communicates this data to the rider via an LCD display. A bicycle computer performs its various tasks with the use of several technologies including: transducer based sensors for determining wheel rotation; microcontroller facilities for data processing; and RF transceivers for wireless data transfer between devices. There currently exist on the market, several different models of wireless bicycle computers however the protocols and technologies employed in each of these devices is of a proprietary nature. The primary objective of our Engineering Design Project will be to design and implement a wireless bicycle computer based upon the Zigbee wireless standard. The device will consist of two individual nodes with the primary design emphasis being on functionality, durability, and low power operation.

THEORY
A typical Zigbee node can be configured as a network Coordinator, router, or enddevice. W ith this type of organization, mesh, cluster tree, and star network topologies are possible. A network coordinator is required in all Zigbee networks as it is responsible for network formation, administration, and security management. In addition to the coordinator, a router device can be defined to relay messages across the network to various end-nodes. The coordinator and router devices are considered full function devices (FFDs), while the end-nodes are reduced function devices (RFDs). Being a more complex entity, a FFD requires the entire protocol stack, while only a skeleton version of the stack is needed by a RFD. In our application of a wireless bicycle computer, we will implement a simple star topology, with a single network coordinator and one end-device node.

Figure 2 - Netw ork Topologies Supported by Zigbee

W hile the Zigbee standard defines the Networking and Application layers of the wireless network, it is built upon a robust physical layer implementation commonly referred to as the IEEE 802.15.4 standard. This existing standard allows Zigbee to be structured in a manner conducive to low power operation. IEEE 802.15.4 is an open standard that is designed for low data rate- wireless personal area networks (LR-W PAN). The Physical

layer and the Medium Access Control (MAC) layer are defined by 802.15.4, and devices built upon it are typically battery powered, resistant to interference, and have a relatively short transmission range. A graphical interpretation of the Zigbee protocol stack is shown in Figure 3.

Although Zigbee supports a beacon-mode (broadcast signal sent out at regular intervals to coordinate communication), most applications - including our own - will be of the non-beacon-mode type. In this setup, the transceivers of the network coordinators and routers are always be powered on, as they must listen for incoming communication. However all end-device nodes - which form the bulk of a wireless network - are governed by an on-board, event driven operating system which allows for the transceivers to be powered off at all times except when required for transmission. The powering down of the transceiver results in a significant reduction in overall power consumption. W ith proper components and careful design, Zigbee end-devices can last for years on the same battery, but coordinators and routers must either be mains powered, or will have to have their batteries replaced at more frequent intervals.

Figure 3 - Zigbee Protocol Stack

At the application level, all Zigbee networks must have an associated profile. This is an

agreed upon collection of variables, data types, and addresses that are used in a specified application. Each profile contains clusters, which in turn contain attributes. Each attribute is essentially a variable, whose contents are transmitted during wireless communication. Like all wireless networks, Zigbee provides broadcast communication. In this configuration, all network nodes receive all transmissions, and it is up to the onboard software- using the cluster ID- to determine whether or not its host is the intended recipient of the transmitted cluster. If an incoming data packets cluster ID does not match one of the hosts approved cluster IDs, the packet is simply discarded. In the event a match is found, the packet is saved and processed as desired. W ithin the Zigbee application framework, two types of data can be transmitted in packets. The first type is a Key Value Pair (KVP), or an attribute that corresponds to the numerical contents of a variable. This type of transmission is useful for setting a value in another node, or on the other hand in getting a value from a distant node. The second type of data that can be wirelessly transmitted in a packet is a Message (MSG). This is typically a string of characters comprising a message, which is initially defined by the user. This type of data transfer is useful for relaying text messages across the network.

The Zigbee protocol stack used in our application is the Z-Stack from Figure8 W ireless, Inc. This version - 1.0 - was designed specifically for Freescale's Zigbee-ready platform with a MC13193 radio transceiver. In addition to providing all the network formation routines, several basic messaging routines are also included. W ith a little bit of research, the application developer can design and implement custom Zigbee enabled devices.

Figure 4 - Freescale Zigbee Platform

HARDWARE DESIGN
For the wireless bicycle computer, two nodes - a coordinator and an end device - were to be implemented. One node will be mounted next to the rear wheel of the bicycle and will monitor wheel motion. The second node will be mounted on the handlebars of the bicycle with an LCD providing data display to the rider. Each node is managed by a Panasonic PAN802153HAR Zigbee module consisting of a MCS08 8-bit microcontroller, and a low power MC13193 transceiver. The transceivers operate at a frequency of 2.4Ghz, and are capable of supporting a maximum bit-rate of 250 Kb/s over a 100 meter range. The microcontroller is equipped with a 10-bit A/D converter and two associated input pins are accessible, along with six general I/O pins. W ith a clock rate of 16Mhz and 60 KB of onboard Flash memory, the MCS08 has ample resources for collecting data and running the Zigbee stack..

Figure 5 - Panasonic Zigbee Module (actual size)

W ith limited pins available for use on the microcontroller, it was decided that the LCD be interfaced to the coordinator module (LCDStation), while utilizing the other module (WheelSensor), strictly for data collection. All sensors utilized in our application will be interfaced to the W heelSensor node where information regarding speed, temperature, and humidity will be processed. The onboard temperature/humidity sensor is capable of outputting two analog voltages proportional to relative humidity, and ambient temperature. Both analog voltages - after being fed through our A/D converter- yield

digital values which are converted and stored. Data collection and transmission will be carried out on a regular basis using software and a timer generated interrupt. The Panasonic DN6848 Hall-Effect sensor helps facilitate wheel rotation detection, and provides a falling edge when in the presence of a 'South' magnetic pole. Speed will be calculated through a digital tachometer built around the DN6848. The tachometer's output signal will be fed into a microcontroller input which is configured for falling-edge detection. Each falling-edge will represent one full rotation and will trigger an interrupt routine that stores the precise time. This information is used along with wheel circumference to determine current speed, and distance covered.

Figure 6 - Netw ork Nodes in Plastic Housing

The final hardware implementation for each module- including all circuitry and sensorswas mounted in a rigid plastic housing approximately 80x110x40 mm in size. The W heelSensor module has two holes drilled in its housing for ventilation. Both nodes (as shown in Figure 6) are equipped with two pushbuttons - one for switching the device power on/off, and the other to allow for bind requests and/or display scrolling.

SOFTWARE DESIGN
Metrowerks Codewarrior Development Studio V5.0 (HCS08) was the suggested development environment for Zigbee applications utilizing the Z-Stack. Since most of the protocol is coded in C and is divided over numerous header and object files, this IDE proved invaluable in our software design and development. Not only does it allow for quick and easy editing, an onboard simulator allowed for efficient and insightful debugging. In addition to Codewarrior, the Zstack Profile Builder software package was also used in creating and editing our Zigbee profile. As mentioned previously, every Zigbee networking application requires a profile. The first step in our software design was determining the exact structure and contents of this profile, entitled BikeDevice. First off, each network node was given a name:

1)W heel Sensor Module = WheelSensor 2)LCD Module =LCDStation

After this initial step, each node had to be described in terms of its incoming clusters and outgoing clusters. An incoming cluster is naturally one that the node will expect to receive, and an outgoing cluster is one which it will transmit. All clusters were defined as type KVP.

1) W heelSensor Incoming clusters: na W heelSensor Outgoing clusters: Wheel2LCD

2) LCDStation Incoming clusters: Wheel2LCD LCDStation Outgoing clusters: LCD2PC

W ith the various cluster directions defined, it came time to describe the attributes associated with each. Again, the attributes represent variables which will be transmitted.

1) Wheel2LCD = a) temperature 2) LCD2PC = a) temperature b) humidity c) distance d) speed e) average speed f) time b) humidity c) distance d) speed e) average speed f) time

Examining the contents of our profile, the basic operation of our wireless bicycle computer can be seen. Our wheel sensor module will collect six pieces of data including: temperature, humidity, distance, speed, average speed, and time. It will pack this information into a KVP cluster called W heel2LCD, and will transmit it to our LCD module at regular intervals. Upon reception of this cluster, our LCD module will display the data to a screen, before copying it to another KVP cluster entitled: LCD2PC. This cluster is prepared solely to allow for future expansion - incase information is to be sent to a host PC in the vicinity.

Figure 7 - Z-Stack Profile Builder (Figure8 Wireless Inc.)

For each network node, a separate application program must be written detailing the exact operation of each host device. Since the operating system loaded onto our modules is event driven, nothing explicitly occurs unless an event is detected. The application source code for each of our network nodes can be found in Appendix A.

For our wheel sensor module, events are generated by: keyboard interrupt, tachometer interrupt, timer interrupt. The keyboard interrupt in this case is triggered by the depression of a pushbutton switch, and the interrupt service routine simply sets an OSAL (operating system abstraction layer) event and exits. Once this OSAL event is acknowledged, a separate function - Handlekeys() - is called upon to process the pushbutton triggered event. Handlekeys() is a simple routine that sends a Bind request to the network coordinator; this type of request allows the end device to join the network

and coordinate communication activities. Each device need only be bound once, after which, Handlekeys() exits. The tachometer interrupt is triggered each time the wheel completes a full revolution. Again, the interrupt routine sets an OSAL event and then exits. Once acknowledged, a function - Process() - is invoked, which carries out the calculation of all parameters including: speed, average speed, and distance. Along with these calculations, the time, humidity and temperature is recorded and stored in appropriate variables, before Process() exits. The third and final event generation action is linked to the timer interrupt. Every 1000ms, a timer interrupt is triggered and an OSAL event is set. Once acknowledged, the Send() function is invoked, which takes the stored attribute values, populates an application frame data packet, and transmits the entire KVP cluster to the LCD module.

The application on our LCD module has its events generated by two sources, namely the keyboard interrupt, and the incoming KVP message interrupt. The keyboard interrupt event acts identically to its counterpart on the wheel sensor module. Its sole purpose is to accept bind requests from end devices. Once a bind request has been made from a distant end device, the user must push the onboard switch on the LCD module (coordinator) to accept and complete the binding process. The incoming KVP message interrupt will set an OSAL event each time it detects that a message has been received. Once acknowledged, IncomingKVPmsg() is called upon to process the data packet. The first thing that this function performs is a cluster ID check. Assuming the cluster ID matches one that the LCD module is expecting, the function continues on to extract the attribute data and process it accordingly. Once stored, various LCD routines are invoked to display the desired data to the screen.

PARTS LIST
The major components of each network node include:

WheelSensor Module: 1) 2) 3) 4) LM341 5.0 Volt regulator Panasonic PAN802154HAR Zigbee module Humirel HTM1505-ND Humidity/Temperature sensor Panasonic DN6848 Unipolar Hall-Effect Sensor

LCD Module: 1) 2) 3) LM341 5.0 Volt regulator Panasonic PAN802154HAR Zigbee module Epson D1601 16x1 Character Liquid Crystal Display

PAN802154HAR -

Our Engineering Design Project will primarily consist of two Zigbee compliant communication modules. These modules have been built upon Freescales Zigbee ready platform, and are manufactured by Panasonic. The PAN802154HAR has the following characteristics: Dimensions: 48 x 34 x 3 mm Operating Voltage: 2.2 - 3.4 Volts DC Power consumption: 35 - 40 mA, less than 100 uA when dormant Output RF power: 0 - 3 dB Receive sensitivity: -92 dBm Microcontroller: Freescale MCS08-GT60, w/ 4K RAM, 60K Flash Input/Output:8 digital I/Os, with up to 2 10-bit ADC Inputs, RS-232 header Transceiver: Freescale MC13193, 2.4 GHz These Panasonic modules - like all Zigbee devices - operate in the ISM 2.4 Ghz band, and work on top of the IEEE 802.15.4 physical/MAC layer. They have onboard antennae that are etched into the surface, for minimal implementation time.

HTM1505-ND -

The main sensor used in our W heelSensor node is manufactured by Humirel, and provides linear voltage output in proportion to both temperature and humidity. This

component can be powered with 5 V DC and typically uses 0.4 mA. Relative humidity ranging from 1-99% can be accurately measured with a voltage output range of 1-4 V. The humidity coefficient is fixed at 25 mV/%RH, and response time is listed at 5 seconds. The temperature sensing range of the HTM1505-ND is [-30C - 80C], however the user can improve the accuracy by restricting the range via an external resistor. Our temperature sensor is configured to provide the most accurate results within the range of [5C - 40C], and with this setup a temperature coefficient of -19.6 mV/C is achieved.

Figure 8 - HTM1505-ND (Humirel)

DN6848 -

To measure wheel rotation, a hall effect sensor manufactured by Panasonic was used. The DN6848 has all signal conditioning circuitry onboard, including a Schmidt trigger, a stable power supply, and an amplifier circuit that will output 5 V normally, and will drop to 0 V when exposed to a South magnetic field. This component can accept supply power up to 18 V, however in our application a 5 V supply is used. The DN6848 can operate in temperatures as low as -40C, so there is no concern of performance degradation in adverse conditions. To trigger the hall-effect sensor, a 25,000 gauss permanent magnet will be affixed to the wheel, in line with our W heelSensor node.

Figure 9 - Block Diagram of DN6848 (Panasonic)

D1601-16x1 Char LCD -

The LCD module used on our LCDStation node is manufactured by Epson and consists of a 16 character by one-line alpha-numeric display. The controller is based upon the popular Hitachi HD44780, and a 4-bit data interface is used to connect it to our MCU I/O pins. Although this LCD module is of a current design, further power reduction could be achieved by using a custom low-power LCD.

Figure 10 - D1601 LCD Module (Epson)

*All component datasheets can be found in Appendix B.

SCHEMATICS
Shown below, the schematic diagram for our LCDStation node:

Figure 11 - LCDStation Schematic

Figure 12 - LCDStation Node

Shown below, the schematic diagram for our WheelSensor node:

Figure 13 - WheelSensor Schematic

Figure 14 - WheelSensor Schematic

PERFORMANCE SPECIFICATIONS
Networking - W ireless Communication over the 2.4GHz radio-frequency band. - Utilization of the IEEE 802.15.4 standard for Medium Access Control (MAC). - Networking and Application layers to be administered using the Zigbee standard protocol, Version 1.0.

Electrical - Should accept both internal and external RF interference in the 2.4GHz band. - Devices should operate from a low voltage battery source. - Instrumentation circuitry to yield accurate and repeatable results during use. - Low power consumption and extended battery life.

Functional - Allow user to quickly and easily establish a wireless Zigbee network. - Allow user to easily scroll through the display options. - Determine and display current values of speed and average speed to the rider in kilometers per hour, with a refresh rate of 1Hz.

- Display the total distance covered in kilometers, updated at 10 meter intervals. - Update and display current values of temperature and humidity in C and %RH. - Show the elapsed time on the display, in [hh:mm:ss] format.

Environmental - Device should withstand adverse conditions to a reasonable degree. For bicycling purposes, this means temperatures between - 5C and 45C, and humidity up to 100%. -Due to the inherent nature of the application, finished device should be sturdy, rugged and strong, yet lightweight and unobtrusive.

PERFORMANCE ANALYSIS
In terms of network operation, our device adhered to all proposed performance specifications. Firstly, wireless communication was to be accomplished using the 2.4GHz frequency band, and more specifically - the IEEE 802.15.4 standard. In order to meet this objective, specific hardware requirements had to be met. Utilizing the Panasonic communications module based on the Freescale Zigbee platform- dealt with this issue completely. The RF transceiver in this unit, along with onboard software, successfully communicates in the 2.4GHz band with the IEEE 802.15.4 physical MAC layer being used. In addition to the MAC implementation, our device utilizes a fully functional Zigbee protocol stack to implement the Network and Application layers of our Zigbee device. This ensures that the Zigbee protocol administers all network formation and maintenance tasks. Using Figure8 W ireless Z-Stack software, correct software was developed at the application level to implement a Zigbee communication scheme based on the Version 1.0 specifications.

Being a relatively simple embedded system - hardware wise- the electrical specifications were not overly demanding. Our finished device is able to deal with both internal and external RF interference. All devices that operate within the 2.4GHz band are required to accept interference without performance degradation. During the development phase of the PAN802154HAR modules, careful design consideration was taken to ensure proper operation in an interference-rich RF band. The modules themselves are FCC approved, so in essence all devices built upon them have approved interference handling capability. From a power standpoint, our device is portable so the components should be operational from a battery source. Unfortunately, due to the power requirements of our LCD and

transducer components, a 9V battery source - regulated to 5V- was used, even though our communication modules could operate on as low as 3.4 volts. Practically speaking, the user should not have to change the batteries frequently, so low power consumption and extended battery life were required. Battery life is currently measured in hours, and the devices have no trouble running as a portable embedded system.

Users can quickly power-on the Zigbee bicycle computer and establish a communication network between the two devices. This is accomplished by simply depressing a pushbutton on one node to initiate a bind request, and accepting the request on the remaining node in the same manner. The elapsed time is immediately displayed to the screen, and the user can use the pushbutton on the LCDStation module to scroll through the display options. Current speed, and average speed values are calculated and displayed in km/h, with one decimal place precision. The maximum speed measurable with our hardware and software configuration is approximately 99.0 km/h. There are some skips in revolution counts, but for the most part our hall effect scheme works as expected. The total distance covered updates its value in kilometers, at every 10 meters, or after every 5 wheel revolutions. The maximum distance that can be stored on our device is approximately 655.35 kilometers, with two decimal place precision. The temperature and humidity readings are predictable and accurate. The %RH change can be detected by simply blowing on the unit or exposing it to dry air. On the LCD display, values ranging from 0%-100% are achieved, and they are updated at one second intervals. Although our bicycle computer can measure temperatures below zero, we have restricted its most accurate range as being from 5C - 40C. W hen temperatures approach the extreme limits of this range, the linearity begins to break down and readings become less accurate. Nevertheless, temperature is displayed in C with one decimal place precision.

Using rigid plastic boxes to house our device components ensured that they would be rugged, and ready for any inadvertent contact or routine wear. The housings are completely sealed except for ventilation holes in the W heelSensor node. These holes seem adequate for air flow purposes, yet they are not large enough to admit rain droplets. Our device was temperature tested to -10C before the communication modules began flickering and correct operation ceased.

Although our particular application did not require long range data transmission, testing was carried out to determine the communication range of our Zigbee enabled devices. At room

temperature and without the presence of concrete barriers, our two network nodes could communicate flawlessly over a distance of 55 meters. Beyond that, intermittent communication between nodes was possible, at distances of up to 80 meters. This transmission range could be improved by using stronger transceivers, and indeed such implementations do exist on alternative Zigbee-ready platforms.

CONCLUSIONS

At the outset of our Engineering Design Project, there were several major hurdles that needed to be overcome in order for successful device implementation. All software programming was to be coded in standard C++ language, onto an embedded platform that was built around the relatively modern HCS08 8-bit microcontroller. Most of our embedded system experience to this point was centered around the low-level programming language of Assembly, and the much older - power hungry- M68HC11 MCU. So in addition to planning out the early hardware and software design, much effort was put into getting more familiar with both the new MCU, and embedded programming using the more conventional C++ development environment. The Zigbee protocol stack - being a recently developed technology- also posed a major challenge during the early days of our EDP development. Although the software stack was written in clear and well documented code, the availability of outside sources for research and reference was not plentiful. This situation was not necessarily detrimental however, as a more methodical and comprehensive approach was taken in understanding the operation of the Zigbee protocol - version 1.0. In terms of formal specifications, the Zigbee standard has ample resources available. If required, an application developer can delve deep into the structure of the protocol stack to extract whatever information may be helpful to him/her. Although this information was readily available, our wireless application did not require too great a leap into networking theory. In a sense, that is one major appeal of the Zigbee communication scheme very little time needs to be spent on RF issues, and networking details during the development of an embedded wireless application. This feature benefits the application developer immensely in terms of allowing more time to be spent on the functional requirements of the device. This leads into the question of how suitable the Zigbee protocol is in the development of relatively simple embedded systems. On this topic, it can be said that after the initial background research was carried out, the development of our EDP device moved at a smooth and rapid pace. All networking formation and maintenance issues were executed in the background for the most part, with a high-level application programming interface (API) being accessible to the developer. The simplicity in forming adhoc wireless Zigbee networks, makes the protocol a very attractive option for many industrial control, and remote monitoring applications. Dynamic sensor networks seem to be another prime application for Zigbee technology, as topologies of a very large scale can be achieved quite easily.

Figure 14 - Comparision of Wireless Technologies

Power consumption in a Zigbee-ready communication module is minimal, however care must be taken to ensure that all associated components are of a low-power nature as well. In our wireless bicycle computer, our W heelSensor node experienced long battery life due to the fact that it had low-power sensing components, and the transceiver was powered down for the majority of the time. The LCDStation however, experienced a much shorter battery, as expected. A regular LCD module was used to convey information to the user, and these devices by their very nature are power-hungry during operation. A custom, low-power display module could have been employed for lower energy use. The fact that this node was also configured as a network coordinator, puts a limit on to how much energy can be conserved. This configuration requires that the transceiver be powered on at all times to listen for incoming communication packets. In large industrial applications, it is assumed that the coordinators and routers of a Zigbee network are mains powered, resulting in very little time be spent on battery issues. Figure 14 (above) gives a generalized, but informative comparison of three popular wireless

standards. As can be seen, the Zigbee protocol is much more flexible in terms of network size, and network topologies. The Zigbee data-rate is significantly lower, but this comes with the added feature of low-power consumption. The main piece of information in the context of embedded application development is the protocol stack size. Bluetooth and W i-Fi require as much as 1 megabyte of local storage space, and that is the network protocol alone. Zigbee, with a stack size of 20 kilobytes is a much more practical option for use in devices where memory and power resources are scarce.

In summary, our Engineering Design Project can be considered a success, and much was learned in regards to the suitability of Zigbee technology in wireless embedded systems. The device was designed and developed within the allotted time frame and all functional performance specifications were met. Our particular application was not overly demanding in terms of data-rate, however this situation accurately mimics the operation of many control and monitoring applications, where only a few bytes need to be transmitted for correct performance.

REFERENCES
[1] PAN802154HAR 2.4GHz Low Power Module for the IEEE 802.15.4 Standard. Industrial Corp., Docum ent no. LR/W PAN PAN802154HAR00, 2005. Panasonic

[2]

Getting Started with HCS08 and Codewarrior Using C. Pickering, S., Freescale Sem iconductor., Docum ent no. AN2616 Rev 1.0, March 2005.

[3]

Zigbee Software Developm ent Suite. Figure8 W ireless, Inc., Rev 2.0, Septem ber 2005.

[4]

802.15.4/Zigbee Em bedded Bootloader Reference Manual. Freescal Sem iconductor., Docum ent no. 802154EBRM/D Rev 0.0, Septem ber 2004.

[5]

Zigbee/802.15.4 Evaluation Kit Application Note. Freescale Sem iconductor., Docum ent AN2772 Rev 0.0, October 2004.

no.

[6]

Perform ance Evaluation of the IEEE 802.15.4 MAC for Low-Rate, Low-Power W ireless Networks. Lu, Krishnam achari, Rahgavendra, Dept. of Electrical Engineering - University of Southern California, Los Angeles. 2004.

[7]

LR-W PAN Module P/N PAN802154HAR00 Application Notes. Panasonic Industrial July 2005.

Corp.,

[8]

Porting the Freescale Zigbee Stack to Custom HCS08 Hardware. Freescale Sem iconductor., Docum ent no. AN2994 Rev 0.0, August 2005.

[9]

Zigbee - A Suitable Base for Em bedded W ireless Developm ent?. Andersson A., Thoren M.,Chalm ers University of Technology, Sweden. 2005.

[10]

Zigbee Ready Modules for Sensor Networking. Lonn, Olsson, Gong., Dept. of Science & Technology - Linkoping University, Sweden. 2005.

[11]

Zigbee Specification. Zigbee Alliance., Docum ent no. 053474r06 Version 1.0. Decem ber 2004.

[12]

Panasonic Industrial Com pany- Zigbee Com m Module - Perform ance Specifications. Freescale Sem iconductor., Docum ent no. PANSONICCOFS Rev 0. 2005.

[13]

Zigbee Technology from Freescale. Freescale Sem iconductor., Docum ent no. BRZIGBEETECH Rev 4. 2004

[14]

AN 001: Adding a New Application to a Z-Stack Project for Freescale MC13193. Figure8 W ireless, Inc., Docum ent no. F8W -2004-0022. San Diego, California. 2005.

[15]

DN6848/SE/S. Panasonic Hall ICs Data Sheet. July 2002.

[16]

HTM1505 Relative Hum idity and Tem perature Module. Hum irel., Docum ent no. HPC033 Rev D. February 2003.

[17]

MC9S08-GT60 Data Sheet - HCS08 Microcontrollers. Freescale Sem iconductor., Docum ent no. MC9S08GB60/D Rev 2.3. Decem ber 2004.

[18]

Zigbee for Application Developers. Flexipanel Ltd. October 2005.

APPENDIX A
W heelSensor.c
/********************************************************************* Balkar Jagpal & Harpreet Singh Ryerson University 2006 Engineering Design Project - Zigbee Based W ireless Bicycle Computer Copyright (c) 2006 - Balkar Jagpal, Harpreet Singh.

This application is run on the W heel Sensor module and will be responsible for transmitting data (speed, avg.speed, distance, time temperature, humidity) on a regular basis to the LCD module which is the Zigbee Coordinator in this wireless network. All data will be gathered, processed, and calculated on-board, before being transmitted. A temperature sensor and humidity sensor will each be interfaced to the boards A/D converter, and a hall-effect based tachometer will be used to detect wheel rotation.

Revision History: 02/06/06 - produced application framework using F8W 's Profile Builder software. 02/08/06 - declared 'holder' variables for uint16 values to be sent. 02/10/06 - adjusted 'HandleKeys' to initiate Bind Requests. 02/11/06 - began 'W heelsensor_sendKVP_attrib' functions 02/15/06 - adjusted 'W heelsensor_sendKVP_attrib' to correctly populate packet to be sent. 02/20/06 - adjusted 'W heelsensor_sendKVP_attrib'to convert UINT16 into byte format before sending 02/22/06 - enabled Timer2 overflow interrupt for tachometer purposes 03/06/06 - enabled 'distance' update routine 03/14/06 - modified 'distance' routine to increment every 10 meters 03/17/06 - enabled SW 4 to allow for external binding button 03/17/06 - wrote m ini functions to read A/D for temp and humidity

Application contains some source code provided by Figure8 W ireless. Copyright (c) 2005 by Figure 8 W ireless, Inc., All Rights Reserved. Permission to use, reproduce, copy, prepare derivative works, modify, distribute, perform, display or sell this software and/or its documentation for any purpose is prohibited without the express written consent of Figure 8 W ireless, Inc. *********************************************************************/

/********************************************************************* * INCLUDES */ #include "OSAL.h" #include "AF.h" #include "ZDApp.h"

#include "W heelSensor.h" #include "OnBoard.h"

/********************************************************************* * CON STANTS */ #define NUM_ENDPOINTS 1 #define STARTING _ENDPO INT 1

/********************************************************************* * GLOBAL VARIABLES */ uint16 TxData_W HEEL2LCD_TIME = 0; uint16 TxData_W HEEL2LCD_TEMPERATURE; uint16 TxData_W HEEL2LCD_HUMIDITY; uint16 TxData_W HEEL2LCD_DISTANCE; uint16 TxData_W HEEL2LCD_SPEED; uint16 TxData_W HEEL2LCD_AVGSPEED; uint16 TIME1 =0; uint16 TIME2 =1; uint16 TIME_DIFFERENCE =0; uint8 DistanceScaler =0;

// Task ID for internal task/event processing byte W heelSensor_TaskID; // This variable will be received when W heelSensor_Init() is called. devStates_t W heelSensor_NwkState; // This is the unique message ID (counter) byte W heelSensor_TransID; // Destination addresses afAddrType_t W heelSensor_DstAddr[NUM_ENDPOINTS];

// This is the Cluster ID List

const byte W heelSensor_OutClusterList[W HEELSENSOR_MAX_OUT_CLUSTERS] =

{ W HEELSENSOR_W HEEL2LCD_CLUSTER_ID };

const SimpleDescriptionFormat_t W heelSensor_SimpleDesc[NUM_ENDPOINTS] = { { W HEELSENSOR_ENDPOINT_1, W HEELSENSOR_PROFID, W HEELSENSOR_DEVICEID, // int Endpoint;

// uint16 AppProfId[2]; // uint16 AppDeviceId[2]; // int AppDevVer:4;

W HEELSENSOR_DEVICE_VERSION , W HEELSENSOR_FLAGS, // int

AppFlags:4; // byte AppNumInClusters;

W HEELSENSOR_MAX_IN_CLUSTERS, NULL

, // byte *pAppInClusterList; // byte AppNumOutClusters;

W HEELSENSOR_MAX_OUT_CLUSTERS,

(byte*)W heelSensor_OutClusterList // byte *pAppOutClusterList; }, };

// This is the Endpoint description. const endPointDesc_t W heelSensor_epDesc[NUM_ENDPOINTS] = { { W HEELSENSOR_ENDPOINT_1, &W heelSensor_TaskID, (SimpleDescriptionFormat_t *)&W heelSensor_SimpleDesc[0], noLatencyReqs }, };

/********************************************************************* * LOCAL FUNCTIONS */ void MessageKVPCB( afIncomingKVPPacket_t *pckt ); void MessageMSGCB( afIncomingMSGPacket_t *pckt ); byte IndexFromEndpoint( byte endpoint ); void HandleKeys( byte shift, byte keys ); void W heelSensor_SendKVP_W heel2LCD_avgspeed( byte ); void W heelSensor_SendKVP_W heel2LCD_speed( byte ); void W heelSensor_SendKVP_W heel2LCD_distance( byte ); void W heelSensor_SendKVP_W heel2LCD_humidity( byte ); void W heelSensor_SendKVP_W heel2LCD_tem perature( byte );

void W heelSensor_SendKVP_W heel2LCD_time( byte );

/********************************************************************* * @ fn * * @ brief Initialization function for the Generic App Task. * * * * * * @ param * * * @ return none */ void W heelSensor_Init( byte task_id ) { byte x; task_id - the ID assigned by OSAL. This ID should be used to send messages and set timers. This is called during initialization and should contain any application specific initialization (ie. hardware initialization/setup, table initialization, power up notificaiton ... ). W heelSensor_Init

W heelSensor_TaskID = task_id; W heelSensor_NwkState = DEV_INIT; W heelSensor_TransID = 0;

// Device hardware initialization // Let's turn on LED to start SetLed( LED4, LED_ON ); // Register the endpoint description with the AF for ( x = 0; x < NUM_ENDPO INTS; x++ ) { W heelSensor_DstAddr[x].addrMode = AddrNotPresent; W heelSensor_DstAddr[x].endPoint = 0; W heelSensor_DstAddr[x].addr.shortAddr = 0; afRegister( (endPointDesc_t *)&(W heelSensor_epDesc[x]) );

// Register for all key events - This app will handle all key events RegisterForKeys( W heelSensor_TaskID ); } TimerSetControls_TPM(true); TimerSetInterruptTPM2(true); }

/********************************************************************* * @ fn * * @ brief Generic Application Task event processor. This function * * * * @ param task_id - The OSAL assigned task ID. * @ param * * * @ return none */ void W heelSensor_ProcessEvent( byte task_id, UINT16 events ) { osal_msg_received_t *msg; afIncomingKVPPacket_t *KVPpkt; afIncomingMSGPacket_t *M SGpkt; byte byte byte zAddrType_t byte byte byte byte *msgPtr; dstEP; ep; *dstAddr; sentEP; sentStatus; sentTransID; x; events - Events to process. This is a bit map and can contain more than one event. is called to process all events for the task. Events include timers, messages and any other user defined events. W heelSensor_ProcessEvent

// The following events are standard SYSTEM events. if ( events & SYS_EVENT_MSG ) { msg = osal_msg_receive( W heelSensor_TaskID ); while ( msg ) { msgPtr = msg->msg_ptr;

sw itch ( *m sgPtr ) { case KEY_CHANGE: //This event occurs when a key is pressed HandleKeys( m sgPtr[KEY_CHANGE_SHIFT_IDX], msgPtr[KEY_CHANGE_KEYS_IDX] ); break;

case AF_DATA_CONFIRM_CMD: // This m essage is received as a confirmation of a data packet sent. sentEP = msgPtr[AF_DATA_CONFIRM_ENDPOINT];

sentStatus = msgPtr[AF_DATA_CONFIRM_STATUS]; sentTransID = msgPtr[AF_DATA_CONFIRM_TRANSID]; break;

case AF_INCOM ING_KVP_CMD: case AF_INCOM ING_GRP_KVP_CMD: //KVP msg.(W e will not be receiving these events for this module) //convert to infcoming packet format KVPpkt = (afIncomingKVPPacket_t *)&(msgPtr[1]);

// Process the incoming message MessageKVPCB( KVPpkt );

// Release the data buffer osal_mem_free( KVPpkt->cmd.Data ); break;

case AF_INCOM ING_MSG_CMD: case AF_INCOM ING_GRP_MSG_CMD: //MSG msg.(W e will not be receiving these events for this module) // convert to incoming packet format MSGpkt = (afIncomingMSGPacket_t *)&(msgPtr[1]);

// Process the incoming message MessageMSGCB( MSGpkt );

// Release the data buffer osal_mem_free( MSGpkt->cmd.Data ); break;

case ZDO_NEW _DSTADDR: dstEP = msgPtr[ZDO_NEW _DSTADDR_DSTEP]; dstAddr = (zAddrType_t *)&msgPtr[ZDO_NEW _DSTADDR_DSTADDR]; ep = msgPtr[ZDO_NEW _DSTADDR_EP]; // Change the endpoint into an index x = IndexFromEndpoint( ep ); W heelSensor_DstAddr[x].addrMode = dstAddr->addrMode; W heelSensor_DstAddr[x].endPoint = dstEP;

if ( dstAddr->addrMode == Addr16Bit ) W heelSensor_DstAddr[x].addr.shortAddr = dstAddr->addr.shortAddr; else { osal_memcpy( W heelSensor_DstAddr[x].addr.extAddr, dstAddr->addr.extAddr, Z_EXTADDR_LEN ); } break;

// This 'STATE_CHAN GE' event occurs during network formation. case ZDO_STATE_CHANGE: W heelSensor_NwkState = (devStates_t)msgPtr[1]; if ( (W heelSensor_NwkState == DEV_ZB_COORD) || (W heelSensor_NwkState == DEV_ROUTER) || (W heelSensor_NwkState == DEV_END_DEVICE) ) { // Here, we begin sending W heel Sensor data at regular intervals osal_start_timer( W HEELSENSOR_SEND_MSG_EVT, W HEELSENSOR_SEND_MSG_TIMEOUT ); } break;

default: break; }

// Release the memory osal_msg_deallocate( msgPtr );

// Next msg = osal_msg_receive( W heelSensor_TaskID ); } }

// Transmit data to LCD module - This event is generated at // reg. intervals via a timer - setup in W heelSensor_Init(). if ( events & W HEELSENSOR_SEND _MSG _EVT ) { for( x = 0; x < NUM_ENDPO INTS; x++ ) { ep = W heelSensor_epDesc[x].endPoint;

// Send 'time' with a KVP cluster type TxData_W HEEL2LCD_TIME = TxData_W HEEL2LCD_TIME + 1; W heelSensor_SendKVP_W heel2LCD_time( ep );

// Send 'temperature' with a KVP cluster type (AD chan 0-PB0) TxData_W HEEL2LCD_TEMPERATURE = ReadAtoD8bit(0); W heelSensor_SendKVP_W heel2LCD_tem perature( ep );

// Send 'humidity' with a KVP cluster type (AD chan 1-PB1) //Humidity sensors output = 25mv/% RH between 1-4V TxData_W HEEL2LCD_HUMIDITY = ReadAtoD8bit(1); W heelSensor_SendKVP_W heel2LCD_humidity( ep );

// Send 'distance' with a KVP cluster type //The variable TxData_W HEEL2LCD_DISTANCE is populated in //The 'Handlekeys' function W heelSensor_SendKVP_W heel2LCD_distance( ep );

// Send 'speed' with a KVP cluster type TxData_W HEEL2LCD_SPEED = (10986 / TIME_DIFFERENCE); W heelSensor_SendKVP_W heel2LCD_speed( ep );

// Send 'avgspeed' with a KVP cluster type W heelSensor_SendKVP_W heel2LCD_avgspeed( ep );

// Setup timer to trigger this event again osal_start_timer( W HEELSENSOR_SEND_MSG_EVT, W HEELSENSOR_SEND_MSG_TIMEOUT ); } } }

/********************************************************************* * Event Generation Functions */ /********************************************************************* * @ fn * * @ brief Handles all key events for this device. * * @ param keys - bit field for key events. HandleKeys

* * @ return none */ void HandleKeys( byte shift, byte keys ) { byte x;

if ( keys & EVAL_SW 3 ) { //Lets find time elapsed between revs. TIME2 = TimerElapsed_Overflow_COUNT(); TIME_DIFFERENCE = TIME2 - TIME1; TIME1= TIME2; //current time

//time difference between pulses //time2 become old (time1)

DistanceScaler = DistanceScaler + 1; if ( DistanceScaler == 5 ) { //Increment distance value to be transm itted (every 5 revs.) TxData_W HEEL2LCD_DISTANCE = TxData_W HEEL2LCD_DISTANCE + 1; DistanceScaler = 0; } }

if ( keys & EVAL_SW 4 ) { //Initiate an End Device Bind Request from EXTERNAL BUTTON for( x = 0; x < NUM_ENDPO INTS; x++ ) ZDApp_SendEndDeviceBindReq( W heelSensor_epDesc[0].endPoint ); }

if ( keys & EVAL_SW 1 ) { //Initiate an End Device Bind Request from INTERNAL BUTTON for( x = 0; x < NUM_ENDPO INTS; x++ ) ZDApp_SendEndDeviceBindReq( W heelSensor_epDesc[0].endPoint ); } }

/********************************************************************* * LOCAL FUNCTIONS */

/*********************************************************************

* @ fn *

MessageKVPCB

* @ brief Data message processor callback. This function processes * * * * @ param * * @ return none */ void MessageKVPCB( afIncomingKVPPacket_t *pkt ) { none any incoming data - probably from other devices. So, based on cluster ID, perform the intended action.

switch ( pkt->clusterId ) { } }

/********************************************************************* * @ fn * * @ brief Data message processor callback. This function processes * * * * @ param * * @ return none */ void MessageMSGCB( afIncomingMSGPacket_t *pkt ) { switch ( pkt->clusterId ) { } } ********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * none W heelSensor_SendKVP_W heel2LCD_avgspeed none any incoming data - probably from other devices. So, based on cluster ID, perform the intended action. MessageMSGCB

* @ return none */ void W heelSensor_SendKVP_W heel2LCD_avgspeed( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFavgspd[2]; BUFavgspd[0] = LO_UINT16(TxData_W HEEL2LCD_AVGSPEED); BUFavgspd[1] = HI_UINT16(TxData_W HEEL2LCD_AVGSPEED);

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep, W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_AVGSPEED_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFavgspd, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else {

} } /********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * * @ return none */ void W heelSensor_SendKVP_W heel2LCD_speed( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFspd[2]; BUFspd[0] = LO_UINT16(TxData_W HEEL2LCD_SPEED); BUFspd[1] = HI_UINT16(TxData_W HEEL2LCD_SPEED); none W heelSensor_SendKVP_W heel2LCD_speed

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep,

W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_SPEED_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFspd, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else { } } /********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * * @ return none */ void W heelSensor_SendKVP_W heel2LCD_distance( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFdistance[2]; BUFdistance[0] = LO_UINT16(TxData_W HEEL2LCD_DISTANCE); BUFdistance[1] = HI_UINT16(TxData_W HEEL2LCD_DISTANCE); none W heelSensor_SendKVP_W heel2LCD_distance

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep, W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_DISTANCE_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFdistance, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else {

} } /********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * * @ return none */ void W heelSensor_SendKVP_W heel2LCD_humidity( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFhumidity[2]; BUFhumidity[0] = LO_UINT16(TxData_W HEEL2LCD_HUMIDITY); BUFhumidity[1] = HI_UINT16(TxData_W HEEL2LCD_HUMIDITY); none W heelSensor_SendKVP_W heel2LCD_humidity

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep, W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_HUMIDITY_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFhumidity, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else { } } /********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * * @ return none none W heelSensor_SendKVP_W heel2LCD_tem perature

*/ void W heelSensor_SendKVP_W heel2LCD_temperature( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFtem p[2]; BUFtem p[0] = LO_UINT16(TxData_W HEEL2LCD_TEMPERATURE); BUFtem p[1] = HI_UINT16(TxData_W HEEL2LCD_TEMPERATURE);

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep, W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_TEMPERATURE_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFtemp, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else {

} } /********************************************************************* * @ fn * * @ brief Send a KVP type message. * * @ param * * @ return none */ void W heelSensor_SendKVP_W heel2LCD_time( byte ep ) { //we must convert UINT16 into byte format before sending byte BUFtime[2]; BUFtime[0] = LO_UINT16(TxData_W HEEL2LCD_TIME); BUFtime[1] = HI_UINT16(TxData_W HEEL2LCD_TIME); none W heelSensor_SendKVP_W heel2LCD_time

if ( afFillAndSendMessage( &W heelSensor_DstAddr[IndexFromEndpoint( ep )], ep,

W HEELSENSOR_W HEEL2LCD_CLUSTER_ID, 1, FRAMETYPE_KVP, &W heelSensor_TransID, CMDTYPE_SET, DATATYPE_UINT16, W HEELSENSOR_W HEEL2LCD_TIME_ATTRIB_ID, ERRORCODE_SUCCESS, sizeof(DATATYPE_UINT16), BUFtime, 0, false, AF_DEFAULT_RADIUS )) { // Error occurred in request to send } else { // TOGGLE the LED to indicate m sg sent! SetLed( LED4, LED_TOGGLE ); }

/********************************************************************* * @ fn * * @ brief Utility function that returns the index for the passed in endpoint. * * @ param * * @ return index into the endpoint descriptor * */ byte IndexFromEndpoint( byte endpoint ) { byte x; NUM_ENDPO INTS if not found endpoint - which endpoint IndexFromEndpoint

for ( x = 0; x < NUM_ENDPO INTS; x++ ) { if ( endpoint == W heelSensor_epDesc[x].endPoint ) break; } return x; }

LCDStation.c
/********************************************************************* Balkar Jagpal & Harpreet Singh Ryerson University 2006 Engineering Design Project - Zigbee Based W ireless Bicycle Computer Copyright (c) 2006 - Balkar Jagpal, Harpreet Singh.

This application is run on the LCD/handlebar module and will be responsible for receiving data (speed, avg.speed, distance, time temperature, humidity) on a regular basis from the W heel Sensor module - a Zigbee End Device in this wireless network. All data will be gathered, processed, and displayed via an on-board LCD, transm itting data in 'real time' to the rider. This LCD application may be modified in the future to forward data to a third network node.

Revision History: 02/06/06 - produced application framework using F8W 's Profile Builder

software. 02/08/06 - declared 'holder' variables for received uint16 values. 02/10/06 - adjusted 'HandleKeys' to initiate Bind Requests. 02/11/06 - adjusted onboard.c file to re-map LCD connection. 02/15/06 - began 'MessageKVPCB' to handle incoming KVP events. 02/16/06 - adjusted 'M essageKVPCB' to check clusterID & attribID. 02/18/06 - adjusted 'MessageKVPCB'to store rx'ed data and introduced code to display information on LCD. 02/20/06 - created 'rcv_function' to extract byte data to uint16. 02/21/06 - changed 'holder' variables to GLOBAL. 02/22/06 - activated SW 3 and SW 4 from within onboard.c. Made routines to handle SW 3 & SW 4 events 03/20/06 - Made SW 3 initiate bind request and then used for scroll

Application contains some source code provided by Figure8 W ireless. Copyright (c) 2005 by Figure 8 W ireless, Inc., All Rights Reserved. Permission to use, reproduce, copy, prepare derivative works, modify, distribute, perform, display or sell this software and/or its documentation for any purpose is prohibited without the express written consent of Figure 8 W ireless, Inc. *********************************************************************/ /********************************************************************* * INCLUDES */ #include "OSAL.h" #include "AF.h" #include "ZDApp.h"

#include "LCDstation.h" #include "OnBoard.h"

/********************************************************************* * CON STANTS */ #define NUM_ENDPOINTS 1 #define STARTING _ENDPO INT 1

/********************************************************************* * GLOBAL VARIABLES */ //Our received values (from "W heel Sensor") uint16 rxData_W HEEL2LCD_TIME;

uint16 rxData_W HEEL2LCD_TEMPERATURE; uint16 rxData_W HEEL2LCD_HUMIDITY; uint16 rxData_W HEEL2LCD_DISTANCE; uint16 rxData_W HEEL2LCD_SPEED; uint16 rxData_W HEEL2LCD_AVGSPEED; uint8 already_bound =0;

// Holds the current display state uint8 Display_State = 1; // Task ID for internal task/event processing byte LCDstation_TaskID; // This variable will be received when LCDstation_Init() is called. devStates_t LCDstation_NwkState; // This is the unique message ID (counter) byte LCDstation_TransID; // Destination addresses afAddrType_t LCDstation_DstAddr[NUM_ENDPOINTS];

// This is the Cluster ID List const byte LCDstation_InClusterList[LCDSTATION_MAX_IN_CLUSTERS] = { LCDSTATION _W HEEL2LCD_CLUSTER_ID };

const byte LCDstation_OutClusterList[LCDSTATION_MAX_OUT_CLUSTERS] = { LCDSTATION _LCD2PC_CLUSTER_ID };

const SimpleDescriptionFormat_t LCDstation_SimpleDesc[NUM_ENDPOINTS] = { { LCDSTATION_ENDPOINT_1, LCDSTATION_PROFID, LCDSTATION_DEVICEID, // int Endpoint;

// uint16 AppProfId[2]; // uint16 AppDeviceId[2]; // int AppDevVer:4;

LCDSTATION _DEVICE_VERSION , LCDSTATION _FLAGS, // int

AppFlags:4; // byte AppNumInClusters;

LCDSTATION_MAX_IN_CLUSTERS,

(byte*)LCDstation_InClusterList, // byte *pAppInClusterList; LCDSTATION_MAX_OUT_CLUSTERS, // byte AppNumOutClusters;

(byte*)LCDstation_OutClusterList // byte *pAppOutClusterList; },

};

// This is the Endpoint description. const endPointDesc_t LCDstation_epDesc[NUM_ENDPOINTS] = { { LCDSTATION _ENDPO INT_1, &LCDstation_TaskID, (SimpleDescriptionFormat_t *)&LCDstation_SimpleDesc[0], noLatencyReqs }, };

/********************************************************************* * LOCAL FUNCTIONS */ void MessageKVPCB( afIncomingKVPPacket_t *pckt ); void MessageMSGCB( afIncomingMSGPacket_t *pckt ); byte IndexFromEndpoint( byte endpoint ); void HandleKeys( byte shift, byte keys ); uint16 rcv_function(byte* Data);

/********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @ fn * * @ brief Initialization function for the Generic App Task. * * * * * * @ param * * * @ return none */ void LCDstation_Init( byte task_id ) { byte x; task_id - the ID assigned by OSAL. This ID should be used to send messages and set timers. This is called during initialization and should contain any application specific initialization (ie. hardware initialization/setup, table initialization, power up notificaiton ... ). LCDstation_Init

LCDstation_TaskID = task_id; LCDstation_NwkState = DEV_INIT; LCDstation_TransID = 0;

// Device hardware initialization can be added here or in main() (Zmain.c).

// Lets confirm proper LCD operation W riteLCDString (1, "Network Formed!");

// Register the endpoint description with the AF for ( x = 0; x < NUM_ENDPO INTS; x++ ) { LCDstation_DstAddr[x].addrMode = AddrNotPresent; LCDstation_DstAddr[x].endPoint = 0; LCDstation_DstAddr[x].addr.shortAddr = 0; afRegister( (endPointDesc_t *)&(LCDstation_epDesc[x]) );

// Register for all key events - This app will handle all key events RegisterForKeys( LCDstation_TaskID ); } } /********************************************************************* * @ fn * * @ brief Generic Application Task event processor. This function * * * * @ param task_id - The OSAL assigned task ID. * @ param * * * @ return none */ void LCDstation_ProcessEvent( byte task_id, UINT16 events ) { osal_msg_received_t *msg; afIncomingKVPPacket_t *KVPpkt; afIncomingMSGPacket_t *M SGpkt; byte byte byte *msgPtr; dstEP; ep; events - Events to process. This is a bit map and can contain more than one event. is called to process all events for the task. Events include timers, messages and any other user defined events. LCDstation_ProcessEvent

zAddrType_t byte byte byte byte

*dstAddr; sentEP; sentStatus; sentTransID; x;

if ( events & SYS_EVENT_MSG ) { msg = osal_msg_receive( LCDstation_TaskID ); while ( msg ) { msgPtr = msg->msg_ptr;

sw itch ( *m sgPtr ) { case KEY_CHANGE: HandleKeys( m sgPtr[KEY_CHANGE_SHIFT_IDX], msgPtr[KEY_CHANGE_KEYS_IDX] ); break;

case AF_DATA_CONFIRM_CMD: // This m essage is received as a confirmation of a data packet sent. // The status is of ZStatus_t type [defined in NLMEDE.h] // The message fields are defined in AF.h sentEP = msgPtr[AF_DATA_CONFIRM_ENDPOINT];

sentStatus = msgPtr[AF_DATA_CONFIRM_STATUS]; sentTransID = msgPtr[AF_DATA_CONFIRM_TRANSID];

// Action taken when confirmation is received. /* Put code here */ break;

case AF_INCOM ING_KVP_CMD: case AF_INCOM ING_GRP_KVP_CMD: // convert to incoming packet format KVPpkt = (afIncomingKVPPacket_t *)&(msgPtr[1]);

// Process the incoming message MessageKVPCB( KVPpkt );

// Release the data buffer osal_mem_free( KVPpkt->cmd.Data ); break;

case AF_INCOM ING_MSG_CMD: case AF_INCOM ING_GRP_MSG_CMD: // convert to incoming packet format MSGpkt = (afIncomingMSGPacket_t *)&(msgPtr[1]);

// Process the incoming message MessageMSGCB( MSGpkt );

// Release the data buffer osal_mem_free( MSGpkt->cmd.Data ); break;

case ZDO_NEW _DSTADDR: dstEP = msgPtr[ZDO_NEW _DSTADDR_DSTEP]; dstAddr = (zAddrType_t *)&msgPtr[ZDO_NEW _DSTADDR_DSTADDR]; ep = msgPtr[ZDO_NEW _DSTADDR_EP]; // Change the endpoint into an index x = IndexFromEndpoint( ep ); LCDstation_DstAddr[x].addrMode = dstAddr->addrMode; LCDstation_DstAddr[x].endPoint = dstEP;

if ( dstAddr->addrMode == Addr16Bit ) LCDstation_DstAddr[x].addr.shortAddr = dstAddr->addr.shortAddr; else { osal_memcpy( LCDstation_DstAddr[x].addr.extAddr, dstAddr->addr.extAddr, Z_EXTADDR_LEN ); } break;

case ZDO_STATE_CHANGE: LCDstation_NwkState = (devStates_t)msgPtr[1]; if ( (LCDstation_NwkState == DEV_ZB_COORD) || (LCDstation_NwkState == DEV_ROUTER) || (LCDstation_NwkState == DEV_END_DEVICE) ) { // Start sending "the" message in a regular interval. //osal_start_timer( LCDSTATION_SEND_MSG_EVT, // } break; default: LCDSTATION_SEND_MSG_TIMEOUT );

break; }

// Release the memory osal_msg_deallocate( msgPtr );

// Next msg = osal_msg_receive( LCDstation_TaskID ); } } }

/********************************************************************* * Event Generation Functions */ /********************************************************************* * @ fn * * @ brief Handles all key events for this device. * * @ param * @ param * * * * * * @ return none */ void HandleKeys( byte shift, byte keys ) { byte x; shift - true if in shift/alt. keys - bit field for key events. Valid entries: EVAL_SW 4 EVAL_SW 3 EVAL_SW 2 EVAL_SW 1 HandleKeys

if ( keys & EVAL_SW 1 ) { //Initiate an End Device Bind Request for the mandatory endpoint for( x = 0; x < NUM_ENDPO INTS; x++ ) ZDApp_SendEndDeviceBindReq( LCDstation_epDesc[x].endPoint ); }

//Increment Display_State to change LCD display if ( keys & EVAL_SW 3 )

{ if(already_bound == 0) {

already_bound=1;

//Initiate an End Device Bind Request for the mandatory endpoint for( x = 0; x < NUM_ENDPO INTS; x++ ) ZDApp_SendEndDeviceBindReq( LCDstation_epDesc[x].endPoint ); }

else

if (Display_State == 6) Display_State = 0; Display_State = Display_State + 1; } }

/********************************************************************* * LOCAL FUNCTIONS */ /********************************************************************* * @ fn * * @ brief This function is called to process incoming KVP * * * * * @ param * * @ return none */ void MessageKVPCB( afIncomingKVPPacket_t *pkt ) { none messages. It first checks the cluster ID, and then the attribute ID, before extracting data from the packet and storing it in local variables. MessageKVPCB

if ( pkt->clusterId == LCDSTATION_W HEEL2LCD_CLUSTER_ID) { //Determ ine the Attribute being sent... switch ( pkt->cmd.AttribId ) { //and store in the appropriate variable.

case LCDSTATION_W HEEL2LCD_TIME_ATTRIB_ID: rxData_W HEEL2LCD_TIME = rcv_function(pkt->cmd.Data); break;

case LCDSTATION_W HEEL2LCD_TEMPERATURE_ATTRIB_ID: rxData_W HEEL2LCD_TEMPERATURE = rcv_function(pkt->cmd.Data); break;

case LCDSTATION_W HEEL2LCD_HUMIDITY_ATTRIB_ID: rxData_W HEEL2LCD_HUMIDITY = rcv_function(pkt->cmd.Data); break;

case LCDSTATION_W HEEL2LCD_DISTANCE_ATTRIB_ID: rxData_W HEEL2LCD_DISTANCE = rcv_function(pkt->cmd.Data); break;

case LCDSTATION_W HEEL2LCD_SPEED_ATTRIB_ID: rxData_W HEEL2LCD_SPEED = rcv_function(pkt->cmd.Data); break;

case LCDSTATION_W HEEL2LCD_AVGSPEED_ATTRIB_ID: rxData_W HEEL2LCD_AVGSPEED = rcv_function(pkt->cmd.Data); break; }

switch ( Display_State ) { case LCDSTATION_DISPLAY_TIME: W riteLCDStringValue("Time:", rxData_W HEEL2LCD_TIME, 10, 1); break;

case LCDSTATION_DISPLAY_TEMPERATURE: W riteLCDStringValue("Tmp:", rxData_W HEEL2LCD_TEMPERATURE, 10, 1); break;

case LCDSTATION_DISPLAY_HUMIDITY: W riteLCDStringValue("Hum:", rxData_W HEEL2LCD_HUMIDITY, 10, 1); break;

case LCDSTATION_DISPLAY_DISTANCE: W riteLCDStringValue("Dis:", rxData_W HEEL2LCD_DISTANCE, 10, 1); break;

case LCDSTATION_DISPLAY_SPEED: W riteLCDStringValue("Spd:", rxData_W HEEL2LCD_SPEED, 10, 1); break;

case LCDSTATION_DISPLAY_AVGSPEED: W riteLCDStringValue("AvgSpd:", rxData_W HEEL2LCD_AVGSPEED, 10, 1); break; } } }

/********************************************************************* * @ fn * * @ brief Data message processor callback. This function processes * * * * @ param * * @ return none */ void MessageMSGCB( afIncomingMSGPacket_t *pkt ) { switch ( pkt->clusterId ) { } } none any incoming data - probably from other devices. So, based on cluster ID, perform the intended action. MessageMSGCB

/********************************************************************* * @ fn * * @ brief Utility function that returns the index for the passed in endpoint. * * @ param * * @ return index into the endpoint descriptor * */ byte IndexFromEndpoint( byte endpoint ) { byte x; NUM_ENDPO INTS if not found endpoint - which endpoint IndexFromEndpoint

for ( x = 0; x < NUM_ENDPO INTS; x++ ) { if ( endpoint == LCDstation_epDesc[x].endPoint ) break; } return x; }

/********************************************************************* * @ fn * * @ brief Function returns UINT16 value, extracted from 2 byte * * * @ param pointer to location of "Data" Buffer * * @ return UINT16 value * */ "Data" buffer. rcv_function

uint16 rcv_function(byte* Data) { uint16 temp_hold;

temp_hold= BUILD_UINT16(Data[0], Data[1]); return temp_hold; }

APPENDIX B

**Data Sheets

Das könnte Ihnen auch gefallen