In the past few weeks I have been working hard at a few projects for end-of-term at Uni. One of the projects is what I called "SmartHome", for Embedded computing [link] course, is a home monitoring [link] application. In the course the students were given an LPC2148 arm7-MCU (NXP) based education board, implemented by Embedded Artists [link]. My partner Gil and I decided to work with ZigBee extension modules [link] to enable remote communication.
Here are the steps we took to bring this project to life.
Our vision is to create a home monitoring and controlling system, that will enable tracking different sensors around the house and also control switches.The system should be centralized by a master controller, and also wireless so it will not need cumbersome wiring throughout the house. We would also like the system to be easily controlled by a PC, so visual information could be displayed to the user, as well as allow manual control of the electronic switches.
Such a system will be able to automatically:
- Turn off the garden lighting when the light outside is bright enough,
- Control the lawn watering system,
- Control air conditioning in the house according to the temperature,
As I mentioned, we were given an LPC2148 education board [link], implemented by Embedded Artists, that boasts a 12Mhz ARM CPU, and many peripheral subsystems. Among the systems are: LCD screen, numerous LEDs, a LED matrix, a fan, analog dials, USB and UART I/O and more. The boards also has a port for connecting a ZigBee module to enable RF communication, but it doesn't contain the actual module. Since we needed remote communication between our stations, we bought 3 XBee modules from Maxstream [link].
The LPC boards can be programmed very easily using tools provided by Embedded Artists, such as GCC with Newlib for compiling (both Win and Linux), and Flashmagic (for windows) or lpc21isp for loading the compiled program. We used these tools for programing the "embedded" part of the application, for the PC client we used Java with SWT and serial port connectivity (RxTx for Windows and Linux).
The embedded program on the LPC board has two parts: A master and A client. The system has only one master, and up to 3 clients. The master gathers information from the clients, and controls their behavior according to the user requests. For communication between the master and clients we created a communication protocol that has only a few simple messages:
- INIT - The master sends this request to initialize the connection between itself and a client.
- ACK - This is the response for every request.
- POLL - The clients answers this request with the data from all it's sensors.
- OPERATE - The master commands the client to switch something on or off.
- ERROR - A general error response.
All commands / responses have a unified structure described here:
General struct: ___________________________________________ _____ | OP | To | From | <----- DATA ------> | EOM |_________|____|______|_____________________|_____ Data: POLL (response) _ ____________ ______ ______ ________ | Temperature| ADC0 | ADC1 | Button | _|____________|______|______|________| OPERATE _ _________ | BITMASK | _|_________|
This way we had a very easy implementation of the communication module, since we always had to look for only 14 bytes on the wire.
Communication with ZigBee module
To jumpstart our implementation we used the examples provided by Embedded Artists for operating the ZigBee module [link]. The communication with the ZigBee module is on the UART1 port of the MCU. The example code takes care of opening the correct GPIO pins, setting the IRQ masks to enable interrupts and provides a very simple API for transmitting and receiving characters with the XBee over UART (described in uart.h and uart.c files).
We took the XBee example code and expanded it to be able to recieve and send data between two stations. That means setting up each station's module with it's ID, address, channel and target address by AT commands [spec, see page. 28]: ATID, ATCH, ATMY and ATDL. Two other key features are putting the module into command mode (rather than transmit mode) to set the mentioned parameters, this is done by '+++' to enter command mode and ATCN to exit. Once we had a decent framework to communicate between the stations, we started to build the logic.
The master station logic is like so:
- Initialize XBee module.
- INIT all client stations, and see which station answers - these will be our "up" stations.
- POLL each "up" station in a loop.
- Take care of any OPERATE requests from the PC client.
This way, the client's logic boils down to just looping, testing for any request and taking care of it. Both client and master share most of the code, so only the main process code is essentially different. The example code uses a framework called "Preemtive OS" to allow multitasking / processes (code was bundled in the examples).
Communication with PC
Communication between the master and PC client also required some lightweight "protocol". The communication is again over UART (0 this time, 1 is used by XBee), only now the PC is doing a UART-over-USB with the board. The protocol we ended up with supports these features:
- Commands the PC wants the master to perform look like "m=<command>=<parameters>", such commands can be:
- "poll=<i>", send a POLL to the station indexed i
- "test=<i>", send an INIT to the station indexed i
- "toggle=<i>_<sw>_<onoff>", set the switch sw on the station indexed i to onoff status
- Notifications the master would like to share with the user (PC) look like "pc=<notification>", such notifications can be:
- "up=<i>", the station indexed i is up
- "temp=<i> <temp>", the station indexed i has a temperature reading of temp
- "e=<error message>", error message from the master
This is an incomplete set of features, but it's representative of the idea we want to present.
PC client program
The PC client we built using Java, so it would (and should) be portable between OSs. The GUI was built with the SWT, using the eclipse Visual Editor plug-in which simplified the process. Communication with the LPC board is done over the serial port of the board, as I mentioned the PC creates a virtual COM port using a USB-to-UART driver (FTDI, bundled with windows) [link].
To test the GUI we created a "simulator", that mimics the operation of a master station, that is shown in the video above.
The high-level design of the program is described in this inheritance UML diagram:
Our PC client uses serial-port connectivity based on the old javax.serial APIs. Though these APIs have been abandoned by Sun, and there is no official Win32 implementation bundled with the JDK (only for *NIXs/Solaris), a project named RxTx is upkeeping an implementation of this API for windows [link].
We are releasing the code under the BSD license, for everyone to use, enjoy, learn and expand.
It is available via the blog's SVN repo:
PC Client (requires RxTx serial port impl and SWT)
svn checkout http://morethantechnical.googlecode.com/svn/trunk/SmartHomePCClient
Embedded program (includes all dependencies)
svn checkout http://morethantechnical.googlecode.com/svn/trunk/smarthome_embedded/final project
To compile the master program "make" in the master directory, and you'll get an "xbee_master.hex" file, same goes for the client in the client directory (these directories don't contain code, only a makefile). Then you have to upload the hex into the board, this is done either by "make deploy" (if you have lpc21isp), or FlashMagic on Win.
Java is compiled as usual... just remember the dependencies.
We would like to thank Sivan Toledo for the guidance, loaned hardware and inspiration.
And thanks all for listening!
Roy S. & Gil Ramon