Friday, February 8, 2013

Building a Wifi Temperature Node for Journalism


Wireless sensor nodes can help monitor conditions the community, in the next state over, or across the globe. These sensors don't have to be complex or expensive to be useful -- even a simple wireless temperature node can be helpful in tracking heat waves, monitoring the heat-island effect in cities, and serving as a warning system for asthma sufferers.

Previously, I've chosen a prototyping platform and 3D printed useful parts to make a sensor node. This post covers planning, assembling, programming, and testing a wireless temperature sensor node for journalism.

ARDUINO UNO

An ATmega 328 IC - the brain of the Arduino Uno.

For this application, I’m using an ATmega 328 DIP, which is a microcontroller that serves as the brains of the Arduino Uno prototyping board. But this 28-pin chip can just as easily be popped out of the Arduino Uno board (or purchased separately) and plopped into a customized circuit board, which could help greatly reduce the cost of deploying temperature sensor nodes. That, along with its ample 32kB of flash memory, makes the 328 a good solution for this project.

GOING WIRELESS

The Roving Networks RN-XV.

The Arduino has many options when it comes to internet connectivity. This added functionality usually comes in the form of Arduino “shields,” which are specialized circuit boards that dock directly on top of the Arduino board.

There are literally hundreds of types of shields, and each can provides different abilities, from SD card storage, to interfaces for sensors and LCD screens, to internet connectivity – both wired and wireless.

The most simple, and most stable, internet solution is the Arduino Ethernet Shield. But this project is intended to be used outdoors, where routing a CAT-5 Ethernet cable may not be an option. Arduino manufactures WiFi Shield, but at nearly $100 a pop, this could easily blow the budget of a “low-cost” sensor network.

Fortunately, there are other options. Notably, Roving Networks manufactures a WiFi module called the WiFly RN-XV, also known as the RN171XV. At $35, this is almost one third the cost of comparable WiFi shields.

It’s a fairly sophisticated piece of kit for the price. It supports adhoc networking, has a realtime clock baked in (something the Arduino lacks), and runs on just 38 milliamps at 3.3 volts when active (for comparison, the official shield consumes about 220mA on the same voltage).

An adventurous person can program the RN-XV to sleep in an ultra-low power state, power up after a designated time, take a sensor reading on one of its 8 pins, post the data to a server, and turn the unit back into a blissful, low-power hibernation. But it does help to have the ATmega 328 interpret the sensor data, tap into the higher-end functions on the WiFly, and keep everything on an even keel.

The biggest potential drawback of the RN-XV is the form factor. Pin spacing on the module is 0.078”, instead of the 0.1” standard spacing of solderless breadboards and other prototyping bits.

The RN-XV can’t be plugged into a breadboard, but it can fit into the footprint of an XBee module, which is another type of wireless networking module. Because of the XBee form factor, the RN-VX can interface with the Arduino via the help of XBee adapters and shields. Even with the shield, the WiFly solution still ends up costing about half of the full WiFi shield.

SHIELD SOLUTIONS

For this application, the RN-XV will be plugged into an official Arduino Wireless SD shield. An added benefit of this shield is the SD card slot, which can be used as a backup (or primary) method of data storage.

As with any shield, it’s important to check out the schematic to see what pins will be occupied, and what kind of voltage is being applied to your components. According to schematics, the shield powers the RN-XV module via the Arduino’s 3.3v pin. That’s the recommended voltage according to the Wifly documentation, so there’s no danger of burn-out as with other shields.

None of the other pins besides +3.3v and GND on the Arduino Uno are occupied by the Wireless SD Shield, with one important exception: the RX and TX hardware serial communication pins on the Uno are wired to the TX the RX pins on the RN-XV.

That can be a problem, depending on how you want to set up serial communication between your board and your computer. As-is, you have the choice of talking to the RN-XV from your IDE’s serial monitor, or talking to the ATmega 328 in the Uno.

You can select which you want to work with by sliding the two-position microswitch located on the shield. When the switch is in the “micro” position, you’ll be able to program and communicate with the microcontroller. When the switch is in the “USB” position, you’ll be able to program and communicate with the RN-XV.

With this shield, you can't have hardware serial communications with the ATmega 328 while at the same time having the ATmega doing hardware serial communications with the WiFly to post data to a server across the internet. This can make troubleshooting difficult, considering you can't intercept the communication between the RN-XV and the Arduino to see what's failing in your system.

SET AND FORGET THE WIFLY

Many Arduino libraries tap into the WiFly's features to connect and disconnect to wireless networks, scan for networks, set static IP addresses, define encryption settings, set passphrases, change the name of the WiFly on the network, update firmware from an FTP server, etc. There's a time and a place for those functions, but in an application like this, where the sensor will be sitting unattended for months at a time, simple code is the best.

Roving Networks provides excellent documentation on how to program the RN-XV. I would recommend that anyone working with this module first read the entire manual.

For this application, the WiFly was programmed to automatically connect to a designated wireless network, and will remain connected to that network (hopefully) for the duration of its deployment. Or at least with as little down time as possible.

With these settings and a firmware update, the WiFly was essentially run in a "set it and forget it" state. Should the node ever lose power or lock up, the WiFly will automatically re-connect to the set network. It won't be necessary to tell the WiFly to connect and disconnect from a wireless network to transmit data.
WIRING UP A WIFI TEMPERATURE SENSOR


This application uses a DS18B20 one-wire temperature sensor. This sensor is about three times the cost of a thermistor, which is a simple device that changes resistance with the temperature. But thermistors are not very accurate devices; most only have an accuracy of +/- 1.25C ( +/- 2.25F).

The DS18B20, on the other hand, has an accuracy of +/- 0.5C ( +/- 0.9F) and a precision of 9 to 12 bits. Each sensor also has a unique 64-bit serial code embedded in onboard ROM, which means multiple sensors can be wired onto a single Arduino pin.

There's a few other nifty features, all of which are detailed in the datasheet, but the most important thing is this sensor converts its temperature reading into a 12-bit digital word.

The diagram above (produced with Fritzing prototyping software) shows how it all fits together solderless breadboard. Very simple.


For prototyping purposes, the Arduino Uno with shield and RN-XV, along with the breadboard and sensors, were placed in a small plastic bin. A small rotary tool was used to cut holes to permit access to an external power source, and the cord from a 9V "wall wart" power supply was threaded through the hole.

CODING FOR STABILITY

As said previously, it's imperative that this sensor node run flawlessly for months at a time. That's why the WiFly was set up to establish and hold connections to wireless networks without assistance. Solid libraries also are essential.

There are several options when it comes to libraries to run the RN-XV, but only the WiFlyHQ library allows the coder to reboot the WiFly in the event that the WiFly receives an odd response from the server, or locks up for whatever reason. Other libraries keep that function private, so those libraries aren't used for the WiFi temperature sensor node.

The RN-XV isn't the only device in this node that can be temperamental. Arduinos can lock up as well, for a multitude of reasons both preventable and not. Fortunately there's a watchdog timer baked into the ATmega firmware that lets us reboot the Arduino in the event of a crash or hang.

As its name suggests, a watchdog timer is a time that is perpetually ticking inside the ATmega. If, after a designated period of time, an appropriate command is not given to reset the timer, the microcontroller itself resets.

This is actually a system that NASA has used to save space probes from disaster. It's just as useful in other situations where systems must run for months, years, or permanently without human interference.

A command in the setup function of the sketch enables the watchdog, and determines the duration of the timer:

wdt_enable(WDTO_8S); 

In the above case, the timer is set for eight seconds. The timer can actually be set down to 16ms. I strongly advise against setting the timer for anything under eight seconds, as doing so might "brick" the ATmega chip.

If the timer is set too low, and the code is faulty and does not reset the watchdog timer, the microcontroller might reset itself before reliable code is loaded on the chip. The microcontroller might reset, reset, and reset, making it impossible to break the cycle. So always be careful when using watchdog timers.

To make everything work properly, the following command must be inserted into the sketch to reset the watchdog timer:

wdt_reset(); 

The code will need to be inserted at least in regular, eight-second intervals to prevent a reset. This sensor node, for example, includes a function that spaces transmissions by 35 seconds. But within that function, the watchdog reset command is called every three seconds during that pause. It's also included at least once in all other functions.

HOSTING, COMMUNICATING THE SENSOR DATA

Cosm was selected as the online depository for sensor data. There are other options such as Thing Speak, but I found Cosm to have the best visual layout.

Cosm recently published its own library to help with posting data, but out-of-the-box, the library only supplies support for Arduino Ethernet and WiFi shields. The WiFly is not supported as-is, and there are no existing WiFly libraries that are compatible with the Cosm library.

Using the official Cosm library would require a re-write of the WiFly library, which is one reason it's not used in this application. But more importantly, this is a very simple application for which the original Cosm code works just fine. It will continue to function as expected until Cosm decides not to support its original method for posting sensor data.

PUBLISHING THE SENSOR NODE CODE

Code for the wifly temperature sensor is available on the Node Journalism repository on Google Codebase. Visit the download section to access WiFly_Temp_Node.ino, along with libraries.zip, which contains the necessary libraries to get everything to work.

CAPTURING READINGS DURING COLD SNAP, HOT SPELL

After much tinkering with the code, at 10 p.m. on January 21, the temperature sensor node was placed outside and proceeded to transmit readings to the Cosm datastream. After 236 hours, CSV data was retrieved from Cosm (API documentation describes how to query historical data).

For comparison, I also retrieved historical dry bulb temperature readings from an NOAA weather monitor located approximately six miles from the sensor's location. The above area chart, plotted in R with the ggplot2 package, shows the NOAA temps in salmon/pink, and the sensor in cyan/blue.

The 236-hour period turned out to be relatively significant, meteorologically speaking. The time frame captured the end of a cold snap that saw temperatures dip more than 20 degrees below freezing, with temps well down in the single digits at night. But over a two day period, temps shot up from 20F to an unseasonably warm 60F.

On average, the temperature sensor node took readings that were 4.1 degrees higher than that recorded by NOAA. Some of the difference might be attributed to micro-climate, but other aspects of the graph indicate the sensor housing played the biggest role in the difference.

Note from the chart that the NOAA readings fluctuate more than the temp sensor node, and that the sensor node tends not to have such drastic drops. This could be due to the insulating qualities of the plastic bin in which the sensor was placed.

However slight, the components of the Arduino give off heat. This is especially true of the voltage regulator. Couple that with the fact that the temp sensor was located adjacent to a warm, wind-blocking house, and it's clear why the sensor may not be matching the NOAA's readings.

THE NEXT STEP


All that being said, it's hard to compete with an NOAA station. The sensors are far more accurate, elaborate, and expensive than the one-wire sensor. They're also mounted in special housings.

That still doesn't mean it's not worth it to try. Future posts will cover my efforts to build a better sensor housing, while at the same time keeping with the "low-cost, deployment-ready" ethos.

There are many more sensors to cover, too. The temperature is just the tip of the iceberg when it comes to node journalism.

In the meantime, feel free to take a look at the Cosm feed for the temperature sensor node. But note that this feed might be inactive for periods of time while better housings are developed, and more sensors are integrated.



2 comments:

  1. Hi Matthew,

    Thanks for sharing your project in such a detailed manner. I just had a few questions with regards to the programming of the RN-XV and the WiFlyHQ library.

    1. Did you bend pin 0 and 1 on the Wireless SD shield, and jumpered them to 8 and 9 to use software serial?

    2. Did you do any adhoc programming to the RN-XV before uploading the sketch?

    3. When you uploaded the sketch did you do it with the serial select on USB mode? When in operation did you set the serial select to MICRO?

    Maybe these questions seem so obvious, but I've been banging my head to connect the WiFly into the network.

    Many thanks!

    ReplyDelete
  2. I just tried mine and it worked! To answer my own questions:

    1. If you use the WiFlyHQ library, yes you bend pin 0 and 1 and jumper them to 8 and 9 respectively.

    2. I did an adhoc programming of my model, and set the parameters (SSID, password, Gateway, etc)

    3. I upload the sketch through USB and run the program on MICRO.

    What I think I was doing wrong was that my internet gateway was using a WEP-64 authentication and I was using a WPA one when setting the password of the network. (I found out that my internet gateway was using a WEP-64 by looking at the network settings of my MAC and how it was authenticating itself to the gateway). Hope this helps.

    ReplyDelete