19 May 2015

A GroveStreams Wireless Sensor Network

In this post I describe how to build an XBee-based wireless sensor network that feeds data to the GroveStreams Data Analytics Platform. I've been using GroveStreams for a couple years now and I am very impressed. The GroveStreams platform has features and power far beyond other "IoT" data services that I have tried. Perhaps even more impressive is how eager the GroveStreams team is to work with their users. User input frequently results in improvements to the platform, and usually quite rapidly at that. GroveStreams delivers a great service, great performance, and they are intensely focused on their customers.

GroveStreams accounts are free, up to certain levels of utilization; above this, rates seem quite reasonable. See the site for details.

This project consists of two network nodes, connected by a ZigBee mesh network implemented with XBee ZB modules (f.k.a. Series 2). One node is the web gateway. Its XBee is configured as the network coordinator. The gateway forwards data sent to it by other nodes to the GroveStreams service via an Ethernet shield.

The other node is a sensor node; its XBee is configured as a router. This node uses a simple analog temperature sensor and sends the data to GroveStreams via the gateway node. Multiple copies of the sensor node are easily added to the network. These can have the same sensor, or with additional programming, other sensors could be added.

Hardware required for this project

(2) Arduino Uno boards
(1) Arduino Ethernet shield
(2) XBee ZB modules (I use part no. XB24-Z7WIT-004 with the wire antenna)
(2) Adafruit XBee Adapter kits
(1) Adafruit FTDI Friend (used to configure the XBees with XCTU)
(1) USB A Male to Mini B cable to connect the FTDI friend to a computer
(2) Yellow LEDs (use any common 3mm or 5mm LED)
(2) Red LEDs (ditto)
(4) 330-ohm resistors (anything between 220 ohms and 1000 ohms should be OK)
(1) 100nF ceramic capacitor
(1) Analog Devices TMP36 temperature sensor
Breadboards, jumper wires, USB and Ethernet cables, power supplies, etc.

Step-by-step instructions

  1. Build the Gateway and Sensor nodes per the schematic diagram.

Gateway Node

Sensor Node
  1. Download and install the XBee Configuration and Test Utility software (XCTU) from digi.com (version 6.2.0 is current as of this writing).
  2. If you have not used FTDI on your computer before, install the FTDI drivers.
  3. Install one XBee in an Adafruit XBee adapter. Using the FTDI Friend, connect it to the computer with a USB A-to-Mini-B cable.
Configuring an XBee with Adafruit's FTDI Friend
  1. Download the latest Coordinator API firmware (21A7 as of this writing) to the XBee. Then, configure the ID, NI, BD, and AP parameters as described in the gsGateway example sketch. (The PAN ID can be any number you like; all XBees on the same network must have the same PAN ID. However, I do recommend a non-zero value.)
  2. Repeat with the other XBee, except download the latest Router API firmware (23A7 as of this writing) and set the four parameters as described in the gsSensor example sketch.
  3. Install the Coordinator XBee in the Gateway node and the Router XBee in the Sensor node.
  4. On both the Gateway and Sensor nodes, temporarily disconnect Arduino Pin 0 from the XBee to allow programming. (Since the XBee connects to the Arduino's serial port, it must be disconnected from the RXD pin to allow the Arduino to be programmed via the bootloader.)
  5. Now go to the GroveStreams web site and create an account. This involves a verification email which should be a familiar process. Once the account is verified, log in and you should see the following message that offers to create an Organization.
After initial GroveStreams Sign-In

Let's digress here for a very quick and incomplete primer on some GroveStreams terminology. An Organization is a container for one or more Components. A Component can represent a physical object in the real world. For this project, the Gateway node will be one Component and the Sensor node will be another. Components in turn contain one or more Datastreams, which contain the actual data sent to the GroveStreams site, for example by our sensor. Keep these concepts in mind for now and we'll see how it all fits together shortly.
  1. Continuing on, respond to the message by clicking Yes to create an Organization. Give it any name you like, then click the Create Organization button.
Creating an Organization
  1. Now we see the GroveStreams start page which lists our Organizations, of which there should be only one, namely the one we just created.
GroveStreams Start Page
  1. Click on the Organization name to open the GroveStreams Observation Studio, which is the main interface to configuring and observing everything in GroveStreams. On the left, note there is a folder for Components, but if the little triangle is clicked, the folder doesn't expand, since no components have been created yet. We can create Components from Observation Studio, but GroveStreams also has a handy feature to create Components automatically when data is first received. Being mostly lazy, we'll use that method for this project.
GroveStreams Observation Studio
  1. Next click on the yellow lock "API Keys" icon near the top right. This will open a dialog that allows keys to be displayed. Our Gateway node needs a key so that GroveStreams can validate it and associate the incoming data with our Organization. Check the box, "Feed Put API Key (with auto-registration and request stream rights)", then click View Secret Key.
API Keys Dialog
  1. In the dialog box that appears, use the mouse to select the key. Press Ctrl-C to copy it to the clipboard, then open Notepad or other convenient application and press Ctrl-V to paste the key. We'll use it shortly, but for now just close the API Secret Key dialog box and the API Keys dialog box.
  2. We are almost ready to program the Gateway and Sensor nodes. But first we need to install the prerequisite libraries. If you are not familiar with installing libraries, please click this link.

    Install each of these libraries:

    http://github.com/JChristensen/GroveStreams
    This library manages the connection to the GroveStreams web site, allows data to be sent, etc.

    http://github.com/JChristensen/gsXBee
    This library handles interface to the XBees.

    http://github.com/andrewrapp/xbee-arduino
    An essential library for working with XBees in API mode.

    http://arduiniana.org/libraries/streaming/
    A very convenient alternative to Serial.print(). (I don't know why it's not part of the Arduino core.)
  3. Start the Arduino IDE and open the gsGateway example sketch from the GroveStreams library (File > Examples > GroveStreams > gsGateway). Change this line of code by pasting in the API key that was copied earlier. (You may also want to change the MAC address on the following line, but chances are that the existing one will work fine.)
  4. Upload the modified gsGateway sketch to the Gateway node. Disconnect the Gateway node. Reconnect Pin 0 to the XBee.
  5. Open the gsSensor example sketch (File > Examples > GroveStreams > gsSensor) and upload it to the Sensor node. No code changes are needed. Disconnect the Sensor node. Reconnect Pin 0 to the XBee.
  6. Connect the Gateway node to your LAN with an Ethernet cable. Apply power to the Arduino. After several seconds, the red wait LED should blink once and the yellow heartbeat LED should begin blinking on and off. Upon startup or reset, the Gateway sends a single message to GroveStreams. Go to the GroveStreams Observation Studio and there should now be a Component named "Coord" created for the Gateway/Coordinator node. This may take several seconds; if you don't see it, try refreshing the web page. Expand the Coord Component and one datastream named "msg" should be visible. This is the startup message sent by the Gateway.
Coord Component created, Startup message sent
  1.  Connect power to the Sensor node. The first data will be sent in one minute, then at one minute intervals thereafter. Wait at least a minute, then refresh the Observation Studio web page and the Sensor node should now be visible as Component "TMP36a". It has three datastreams: "s" which is a sequence number, "C" which is the temperature in Celsius, and "rss" which is the received signal strength at the Gateway XBee. ("rss" is added by the Gateway node. Note that in larger XBee networks, several hops may occur between source and destination nodes. The RSS value only represents that of the last hop.)
TMP36a Sensor Component created

Both nodes write diagnostic information to the serial port; open the Arduino serial monitor or other terminal program at 115,200 baud to observe this information.

Concluding remarks

This has been a long post but it's basically a cookbook approach and only scratches the surface. I hope it will be a starting point for further exploration into both GroveStreams and wireless sensor networks. GroveStreams has much more functionality than I have mentioned so far. Dashboards can display and aggregate data in many different ways, events can be defined to key off certain data values and cause various alerts to be sent, and derived streams can perform various calculations on data. For instance, GroveStreams can easily convert the temperature data sent by the Sensor node from Celsius to Fahrenheit; it would not be necessary to do this in the microcontroller firmware.

I also have not elaborated on the XBee node naming convention. The XBee Node Identifiers (NI) need to start with a one- to eight-character name. This name is used as the GroveStreams Component ID. The name is followed by an underscore character, then eight digits. The eight digits comprise four numbers that control the timing and frequency of data transmission. In this relatively simple project, even though the code for the Gateway node does not use any of these numbers, and the Sensor node only uses the interval, the naming convention still needs to be followed.

One advantage of the naming convention is that it allows identical sensor nodes to be deployed without having to change the microcontroller code. Only the XBee NI parameter needs to be changed. See the comments in the gsXBee.h file for a more complete description of the naming convention.

More to come

I'll be following up with a future post about another project that builds on this one: A battery-powered sensor node. Using two AA cells, it should run for at least a year, taking advantage of the low-power sleep modes of both the ATmega328P microcontroller and the XBee. So stay tuned for that.


22 November 2014

Serial Data Logger Redux

The serial data logger that I blogged about previously now has its own custom PC board. I've had two of them running nearly continuously for a few weeks and they seem very solid. A few other folks are building them as well. I'm glad to have them on dedicated boards, I think I will get a lot of use out of them. On GitHub you can find the Eagle board design, the updated firmware to match the board, and there is a bill of materials on Mouser.com.

Arduino-based Serial Data Logger

22 July 2014

An Arduino Library for External I2C EEPROMs

This is an update of a library I wrote last year for a data logger project. At that time I only needed it to support a couple different EEPROM sizes. Now I've made it more general; it will support EEPROMs between 2k bits and 2M bits (256 bytes to 256k bytes). The library supports multiple EEPROMs on the I2C bus as a single address space (the EEPROMs must be of the same type and their address pins must be appropriately strapped). I/Os can span blocks (for EEPROMs with an internal block structure), pages and devices.

I even wrote some reasonably complete documentation(!) If you try the library and like it, or not, or find issues, please let me know. There is a list of devices that it's been tested with in the ReadMe file; I'd especially like to hear from anyone that tries it with a device not yet listed.

The library can be downloaded from GitHub.

03 July 2014

A Serial Data Logger

This is a project I've been wanting to do for a while. A lot of my projects write debug and other status information to the serial port. Fairly often it seems that I have to let them run for hours or even days to catch an elusive intermittent bug. Until now, this has meant keeping a PC running with a terminal program connected to the microcontroller to log the serial output, which seems pretty inefficient. My primary goal with this logger was to improve that situation.

Hardware consists of an Arduino Uno or compatible, Adafruit's Micro SD breakout board, a button switch and three LEDs. It should be easily adaptable to work with the Micro SD on an Ethernet shield or other hardware. (I use the card detect contact on AFI's board; I don't think the shield has that feature, but it would be minor to remove it from the code.)

The serial input is double-buffered and interrupt driven to maximize throughput. Details, code and schematic are on GitHub.

04 April 2013

How Long Was The Power Out?

I’ve always liked clocks, and especially digital clocks, since I built my first one using TTL ICs back in high school. What I don’t like about mains-powered digital clocks is that many of them need to be reset when power is lost.

Our power has been quite reliable lately, but I can remember coming home from work many times to find all the clocks blinking, and of course the first question was always, “How long was the power out?”

For years my answer to this question was to keep an inexpensive synchronous electric clock in my workshop. (For you youngsters, these are mains-powered analog clocks that derive their timing from the utility frequency via a small AC synchronous motor. They have the characteristic of simply stopping when the power goes out, and when it comes back on, they begin running again right where they left off. Hence it is a simple matter to determine how long the power was out.)

I became increasingly dissatisfied with this solution, as in recent times the clocks didn’t seem to last that long before the motor became noisy, and then they either stopped or no longer kept accurate time. They just don’t make ‘em like they used to.

Last year I began experimenting with Microchip’s MCP79412 Real-Time Clock/Calendar. This chip has several nice features, not the least of which is the ability to store power-down and power-up times associated with a power failure. Not long after I had designed a breakout board for the MCP79412 and written an Arduino library to accompany it, there was a discussion on the Arduino forum about logging utility power outages.

It occurred to me that the MCP79412 could form the heart of such a logger, using its memory in conjunction with the power-fail time-stamps to create a simple Arduino-based “Power Outage Logger”. It seemed like such a neat project that I went ahead and designed a circuit and had boards made. My MCP79412 breakout board plugs in as a daughter board, as does a standard 16x2 LCD display.

The <2> on the display indicates that two outages have been logged.
The red LED indicates that the most recent outage has not been viewed.
The logger will record up to seven outages in the RTC’s static RAM. After a new outage occurs, an LED is illuminated. Using the buttons, the user can scroll through the outages on the display. In addition to setting the date and time, the user can select from several time zones, set the RTC’s calibration register to trim its accuracy, and clear the log.

Displaying the second outage logged, which was ten minutes long.

Ironically, since I built the Power Outage Logger, we haven’t had any actual power outages. There has been scant evidence so far, but they tell me that spring (which can bring storms and maybe some real power outages) is in fact on its way. I hope I haven’t jinxed myself by writing that, but if nothing else, the logger does make a nice little desk clock as well.

The main board with the display and RTC removed.

The Power Outage Logger is an open source project. Hardware design (schematic and board) and software are both available on github.

24 September 2012

Simple XBee ZB (Series 2) P2P Communications

Some folks have difficulty using the XBee Series 2 modules (now called XBee ZB) for simple point-to-point communication in transparent (AT) mode. For this reason, the XBee Series 1 modules (now called XBee 802.15.4) are often recommended for simple P2P applications, with the S2 modules being considered "too complicated".

I disagree with this recommendation because the XBee ZB modules are more capable (and are perfectly capable of simple P2P communication), their radios are a little better than the XBee 802.15.4 modules (both in transmitter power and receiver sensitivity) and they even cost a couple bucks less. With a pair of ZB modules, if you ever want to try mesh networking with three or more nodes, there's nothing else you need to do (except to buy more modules).

The downside is that the XBee ZB modules do require some configuration to establish a P2P link. (I have not experimented with the XBee 802.15.4 modules myself, and I have heard conflicting stories regarding whether a pair can be used as a P2P link "out of the box" without further configuration.)

Getting to the point, I was discussing an XBee ZB issue on the Arduino forum the other day, when I hit on what I think is the minimal amount of configuration required to establish a point-to-point, transparent mode (AT) link with two brand-new XBee ZB modules right out of the box.

First, two assumptions. One, we assume that the modules come from the factory with the Router AT firmware loaded. I think this is a pretty good assumption, all the ZB modules that I have came this way (and BTW, the interface speed is set to 9600 baud). Two, we assume that there are no other XBee networks operating nearby. This is probably a good assumption for folks with their first pair of XBees, but more on that later in case it's not a good assumption for you.

It turns out that there is only one step required to get the new pair of XBee ZBs talking! Using Digi's X-CTU program, load the Coordinator AT firmware on one of the two modules. (Every XBee ZB network needs to have exactly one coordinator, so the first thing when setting up a network is to satisfy this basic requirement anyway.)

This works because the modules' default value of zero for the network ID (PAN ID) causes the coordinator to select a random PAN ID and causes the router to join any PAN ID available. Hence there is a potential issue if there is already another XBee network operating, the router may join it instead of talking to the new coordinator. If this is the case, then there is an additional step: The PAN ID for both units needs to be set to some non-zero value different from that of the other network(s). I like to always set the PAN ID anyway, since what passes for normal around here seems to be a minimum of two separate XBee ZB networks in simultaneous operation, but if you just have that first pair of modules, then more than likely you don't have to worry about it (unless your neighbor hasn't come out of the closet about his XBee addiction).

The other thing that makes this work is that the default destination address (DH and DL parameters) will be zero for the router and 0x000000000000FFFF for the coordinator. Zero is a special address that causes the router to send its traffic to the coordinator. 0x000000000000FFFF is also a special address called the broadcast address. This means that the coordinator will send to every other node on the network.

To broadcast or not to broadcast

As it turns out, using the broadcast address is OK for a simple demonstration with two nodes, but in general, broadcast transmissions should be used sparingly because they cause a lot of network overhead, and this can be significant on larger networks. In the case of two nodes, it's easy enough to avoid and just have the coordinator address its traffic directly to the router. First determine the router's 64-bit (16 hex digit) address. In X-CTU, it's the SH (Serial number High) and SL (Serial number Low) parameters. It's also printed on the label on the bottom of each XBee. SH and SL are each 8 hex digits, and the high part will always be 0x0013A200 for XBees made by Digi International. The low part will be a unique number, for instance 0x406B85A5. Next, connect the coordinator to X-CTU and set its Destination address High (DH) and Destination address Low (DL) to be the router's address. This will cause all transmissions from the coordinator to be unicast transmissions rather than broadcast, and to be directed to the router.

Well this post ended up a bit longer than I thought it would. I hope you stuck in there, and I hope it was useful. I hope to expand on this in another post at a later date, with more details regarding loading firmware, setting parameters, and connecting the XBees, but I wanted to get the thought out there for now. Happy networking!

14 September 2012

Yet Another Real-Time Clock

Real-Time Clocks (RTCs) are popular add-ons to microcontroller projects. I am no exception, I have a lot of them kicking around. The most common RTC seems to be the Maxim DS1307. A lot of my RTCs are DS1307s. It's a real workhorse chip, and easy to use. Still, it has disappointed me in a couple ways. For one, it's not always as accurate as I would like. I've used inexpensive no-name crystals and I've used more expensive ones from the top-shelf distributors. Sometimes they don't even seem to operate within the crystal's specs (typically ±20ppm). Not sure why this is, and it certainly could be my fault, but there it is. Another thing is that sometimes I have a 3.3V microcontroller circuit, but the DS1307 requires 5V.

Another alternative is the Maxim DS3231 (or its SPI relative, the DS3234). I love this chip, it is so cool. The integrated, temperature-compensated crystal makes it very accurate (±2ppm from 0°C to +40°C), and it will operate on 3.3V. This addresses all of my gripes with the DS1307. But it is more expensive, nearly $9 from Mouser in single quantities as I write this, where the DS1307 is about half that. (Yes, I know DS1307s can be had for significantly less from other sources.) But the DS3231 is harder to find at discount prices, and is only available in a surface-mount package if that makes a difference to you.

Enter the Microchip MCP79412. It operates off a crystal similar to that used by the DS1307, so the basic accuracy is about the same. But, it can be calibrated by setting an internal register. It will operate down to 1.8V. And while it does require a few more external passive components than the DS1307, it costs only $1.23 in single quantities. I popped for ten and paid $0.98 per copy. Again, it is only available as a surface-mount component.

The MCP79412 has some other cool tricks up its sleeve as well, including alarms, tracking power outages, and EEPROM in addition to SRAM. I've detailed these in the table below.

To summarize, I've been tinkering with the MCP79412 on and off for the last couple months and have come to like it quite well. I designed a breakout board for it (pictures below) and wrote an Arduino library to support it. I've only used three of the ten chips so far, but they have all operated well within the ±20ppm spec of the crystal I chose. One unit seems to be within 2ppm, and so hardly needs trimming.

If you are also using this chip, or would be interested in it, I'd love to hear from you!

PS: For a comprehensive example using the MCP79412, see my Power Outage Logger project.

Real-Time Clock Comparison
Feature MCP79412 DS1307
On-Chip Calibration ±127 ppm N/A
Alarms Dual alarms (single output) N/A
Power Fail/Restore Timestamps Yes N/A
Unique ID 64-bit ID N/A
EEPROM 128 bytes N/A
Battery-Backed SRAM 64 bytes 56 bytes
Vcc 1.8 - 5.5V 4.5 - 5.5V
I2C Interface Clock Frequency 400 kHz (Vcc ≥ 2.5V) 100 kHz
Square-Wave Output 1, 4096, 8192 or 32,768 Hz 1, 4096, 8192 or 32,768 Hz


MCP79412 RTC Breakout Board, Top
MCP79412 RTC Breakout Board, Bottom

04 September 2012

Warning! One Million Ohms

An electronic version of an old joke known among physicists and engineers.


Amuse your friends and confuse your enemies! Keep the uninitiated away from your workbench or desk and out of your lab!
  • Great conversation piece or gag gift
  • Big, scary 1,000,000 Ω resistor in the middle of the board
  • Pre-programmed AVR microcontroller (ATtiny85)
  • Arduino-compatible, hackable open-source hardware and software Can be re-programmed with an ICSP programmer, using either the Arduino integrated development environment or WinAVR
  • Runs on two AA batteries (not included)
Pressing the SELECT button turns the circuit on and causes the red LEDs to flash. To change the flashing speed and pattern, press SELECT again. Hold SELECT down to turn the circuit off, or it will automatically turn itself off after five minutes.