Temperature sensors working

Temperature sensing using digital temperature sensors is easy to get working.

The temperature sensing part of the project requires three sensors for ambient, high-up and low-down measurement. The DS18B20 temperature sensor seems well-suited for the job.

DS18B20

Three DS18B20 temperature sensors sharing a OneWire bus, standard (rail) power mode

Hooking-up a OneWire bus for the three sensors lets them share a single microcontroller pin -- which isn't important for hardware reasons in this project, but also saves some microcontroller RAM, which might be. The circuit is very simple, with the three sensors sharing power and ground lines and with a common data line pulled-up to the power rail through a 4.7K resistor. The DQ line is attached to one of the Arduino's digital lines. The OneWire library is then used to instantiate a protocol handler for that line, and passed to the temperature control library to manage the interaction with the devices, including their conversion from raw to "real" temperature values.

The resulting code is almost comically simple:

#include <DallasTemperature.h>

OneWire onewire(8);                  // OneWire bus on pin 8
DallasTemperature sensors(&onewire);

void setup(void) {
  Serial.begin(9600);
  sensors.begin();
}

void loop(void) {
  sensors.requestTemperatures();
  for(int i = 0; i < 3; i++) {
    float c - sensors.getTempCByIndex(i);
    Serial.print("Sensor ");   Serial.print(i);   Serial.print(" = ");
    Serial.print(c);   Serial.println("C");
  }
  delay(5000);
}

That's it! The temperature library packages everything up nicely, including the conversion and the interaction with the OneWire protocol (which is quite fiddly).

Three DS18B30s on a prototyping shield

One potential problem for the future is that access to the sensors is by index, not by any particular identifier, and it;s not clear whether the ordering is always the same: does the sensor closest to the microcontroller always appear as index 0, for example? If not, then we'll have to identify which sensor is which somehow to sample the temperature from the correct place, or run each one on a different OneWire bus instance.

There's also an interesting point about parasite power mode, which is where the DS18B20 draws its power from the data bus rather than from a dedicated power rail. This might make power management easier, since the sensor would be unpowered when not being used, such as when the Arduino is asleep. This suggests it's probably worth looking into parasite power a bit more.

DS18B20 digital thermometer

The DS18B20 is a programmable digital thermometer that needs no calibration and uses only one wire of the microcontroller.

The DS18B20 is extremely popular as a temperature sensor, for obvious reasons: they're digital, and require no calibration, in contrast to using a thermistor or similar analogue device which would need to be characterised against reference temperatures. They're not as cheap as analogue components, but their simplicity of use and accuracy probably make up for that in scientific applications.

The devices are also notable as using the OneWire protocol developed by Dallas Semiconductor (now Maxim) and used in (amongst other devices) their iButton devices. Essentially OneWire is an embedded systems equivalent of USB that allows a set of devices to be chained together and addressed using only one pin on a microcontroller. This means that there's no real limit on the number of sensors that even a small chip can make use of. The datasheet is available if needed, but they're so easy to use and have such good software support (see below) that there's no real need to refer to it.

The sensors are packaged almost like transistors, with three wires for ground, power, and data. The easiest way to use them is to power them directly with 5V and ground, and use the third wire for communications. (There's also a "parasitic" mode that takes power from the data bus, which I haven't got to work yet.) The communications line is the "one wire" that runs the communications protocol.

Using OneWire devices, and DS18B20s in particular, is made very simple by the existence of two libraries, providing the protocol driver and temperature conversion and packaging respectively. Links and installation instructions can be found on the 3rd-part tools and libraries page.

API communications now working

A small sensor network now working, with two edge devices talking to a base station.

Network

This step of the project accomplishes two things: is gets API networking mode working for the XBee radios, and makes sure the the interaction between software on the Arduinos and software running on the base station work too.

The data stream is simple enough: each Arduino counts up from 0 to 255 every 5s, passing the result up to the co-ordinator radio. A Processing program on the laptop collects the numbers and prints them. Naturally they become somewhat intertwined as their clocks aren't quite synchronised.

Actually this is enough to perform a simple radio survey to check transmission distance: we can move the radios away from the base station until they lose contact (nominally 100m for these 2mW radios, in reality probably substantially less), then move back into range, and then move one of the radios again to check that it meshes with the intermediate node in reaching back to the base station. This will also check that battery power works.

Meshing

The software is quite straightforward, and the xbee-arduino library handles all the low-level communications -- although it's very low-level, fine for the experienced programmer but probably all but mystifying to anyone not used to this kind of software. The corresponding Java xbee-api library is slightly more friendly, but only slightly: they probably both need wrapping into a framework that hides the radio nastiness.

I think the biggest hurdle for this sort of system is the data format -- or, more precisely, the need (or desire, at least) to to use C at one end and Processing/Java at the other, which means that the data on the wire is being described twice. A framework approach could use (for example) JSON, although there'd still be a need to make sure it was compactly encoded and transmitted.

The xbee-arduino library

A library for using XBee radios with Arduinos.

The XBee radio operates in two modes: transparent or text-based, and API or binary-based. The latter (API mode) is generally considered more suitable for computer-to-computer interactions, as it's faster and simpler for computers to manipulate. However, using an XBee in this mode requires additional software.

The xbee-arduino library provides Arduino functions to access the API mode functionality of the various XBee radio modules. The library is quite low-level, but does provide access to all the necessary functions like issuing AT commands to control the modem and sensing and receiving packets of data to other radios in the mesh network.

To use the library you download the latest version from the web page and unpack it into the libraries/ directory of your Arduino IDE. You also need to make sure that the radios you use have the API function set installed using X-CTU, as the library only makes sense for radios in API mode. You also have to set the "AP" parameter to 2 when writing the firmware.

XBee firmware management with X-CTU

Managing Digi's XBee radio modules requires using their X-CTU package to upload the correct firmware. In this post we explain how.

This post is slightly depressing: not because it's on an unhappy topic, but because the effort and software needed to manage XBee radios is so complex to set up. In many ways this is just a function of the good design of the XBee: it's so minimal in terms of footprint and power consumption at run-time that it offloads a lot of work to external tools (and the user) at system build-time. But it's still a lot of work to get such a small piece of kit running.

X-CTU is intended to upload firmware to XBee radio modules. This is needed to change the firmware between router and co-ordinator of the Zigbee mesh network, and between the different protocol variants that the XBee radios can support.

Xbee on USB

One limitation of X-CTU is that it only works on Windows: if you're running Linux, X-CTU will run under Wine. You can download the latest X-CTU from Digi's X-CTU page; alternatively, there's a version installed on the Citizen Sensing VM.

To use X-CTU you need to connect your XBee module to your computer. The easiest way to do this is using an XBee USB breakout board, which provides an XBee socket and a USB socket. Insert the radio into the board, plug in a USB cable, and plug the other end into a USB socket. The light on the breakout board will then come on (see photograph above).

X-CTU in operation

You next need to start up X-CTU and tell it where the XBee is. It hangs off a Windows COM port, and X-CTU will typically find it automatically. You should then be able to press the "Test/Query" button, and X-CTU will interrogate the XBee and display a small window showing some information about it, as shown in the screenshot on the right: the details don't matter, but this shows that the XBee is talking to the computer properly.

X-CTU router firmware

Assuming everything is now working correctly, the next step is to decide what firmware to download to the radio. Click on the "Modem configuration" tab, and then click the "Read" button: this reads the firmware that's on the XBee at the moment, and puts the details into the window. Typically this results in a display like that shown on the left. The important things to notice are the two drop-down boxes labelled "Function Set" and "Version". The function set is the description of the firmware, in which case indicating that the XBee is running Zigbee router firmware that responds to AT commands (more on this below).

X-CTU co-ordinator firmware

To download a new firmware, we then select the function set and version we want to use. Suppose we want to make this XBee into the mesh co-ordinator. We change the function set to "Zigbee Coordinator AT" (keeping with Zigbee and the AT command set) in  "Function set" the drop-down, then select the most recent version of this function set from the "Version" drop-down. (Versions are identified by hex numbers: the most recent in the screenshot right is "20A7", that being the highest hex number. Unfortunately X-CTU orders the numbers alphabetically, not in hex-numeric order.) Pressing "Write" will update the radio's firmware, and the radio is then ready for use as a co-ordinator.

If you look through the list of function sets, there will be quite a few options, including protocols other than Zigbee. These probably aren't worth too much exploration, but you'll also notice that there are Zigbee AT and API function sets corresponding to the two modes (transparent and API) that the XBee can support. Be sure to select the correct one for your application.

That's it: the radio is now ready for use.

Advanced use: setting optional parameters

There's one more thing that X-CTU can be used for: it can set parameters to the firmware function set, and this is sometimes important when using the radios.

X-CTU parameter setting

When you've read the firmware from a radio, the main part of the X-CTU window contains a hierarchy of folders and cryptic values, for example "(4) PL - Power level". These are parameters that can be changed to modify the detailed behaviour of the radio. Some can also be set using AT commands. The example we used sets the radio's power level to 4. If you click on this, it will show a drop-down box giving other options. You might, for some applications, choose to reduce the radio power to 1 ("low") to save batteries. If you choose this and then write the firmware to the radio, the module will use this power setting.

In the example shown on the left, we're changing the AP parameter ("API enable") to 2, which is needed for the xbee-arduino library to work properly. If we now write the firmware (with the Zigbee co-ordinator API function set selected as shown), the radio will be ready for use.

Mesh networking

A mesh network is a way of setting up a communications system when there's no fixed infrastructure available. They're often used for communications in remote sites, and on sensor networks.

If you've used wifi, you've used an infrastructural wireless network in which there is a dedicated router that talks to all the devices in its range (phones, tablets, laptops, wireless-enabled printers, ...) and connects them to the internet. The devices don't talk to each other directly: if they want to exchange information (to print a document, for example) they do via the router.

Another kind of infrastructural network is the cellular telephone service. All calls go through the cell towers: if you call your friend, and she happens to be standing next to you, your phone still talks to the nearest cell tower which then talks to her phone -- a round trip that might be a couple of kilometres! While this sounds a bit barmy, it simplifies the design of the network and the software needed to manage it, and is fine in situations where there is plenty of power and room for the infrastructure.

By contrast to these large-scale systems, XBees provide mesh networking in which the devices co-operate to route traffic from the sensor motes (using router radios) to the base station (running a co-ordinator radio). As well as generating and receiving messages, nodes in the network also co-operate in moving other nodes' traffic. There is no infrastructure -- the nodes are both the users and the providers of the network -- which means a mesh can be deployed in areas without any "official" network coverage, or to provide functions (like low power) that the infrastructure that is available can't deliver. Each mesh network works on a particular network protocol, different to the ones used for wifi or cellular telephony.

XBee radios

The XBee is a series of small radio modules that implement the Zigbee protocol and work well with Arduinos.

Xbees and an Arduino

XBees are made by Digi. The range includes a number of options: you almost certainly want some variant of the Zigbee range. The Series 2 (S2) modules seem to offer good performance, low power, and a useful range of functions. There are several different antenna types and two different radio powers (2mW and 50mW): larger power provides more range (1km nominal as opposed to 100m) at the cost of twenty-five times the power consumption: best avoided unless really needed. A collection of XBee modules co-operate to form a mesh network that's quite robust against partial failure, which makes them great for use in the field.

To get XBees working with an Arduino you need several pieces of hardware and software:

  • Two or more radios (obvious, but surprisingly easy to only buy one...)
  • One or more Arduinos
  • One Arduino XBee shield for each radio-equipped Arduino
  • One XBee USB breakout board
  • The X-CTU firmware management software
There are also variations of Arduinos that take XBee modules directly, as well as other sensor mote systems that can work with them: they're not completely Arduino-specific.

When buying radios, buy them all the same series: the different series aren't guaranteed to interwork (although they often do). In the photograph above there are two different XBees: one with a patch antenna and one with a whip antenna.

The Xbee shield fits on top of the Arduino. They're sold without a radio module.

The breakout board is used to connect an XBee to the USB port of a computer, allowing your network to be accessed from the desktop. This is useful for debugging and for data logging, unless you're also going to build a dedicated data logger.

The X-CTU software manages the firmware on the radio module. Because the radios are small and low-power, they don't have room for a sophisticated software stack, and so aren't programmed in the normal way. Instead you download a firmware providing exactly the functions you need. Each network is given an identifier (a personal area network id or PAN) so that several networks can co-exist in the same area without interfering with each other. Each network has exactly one co-ordinator, with the others being routers, Co-ordinator and router use different firmware: you nominate one of your radios as co-ordinator (which will typically live on the base station, or on the data logger) and use X-CTU to load co-ordinator firmware to it; the other radios get router firmware and are placed onto the sensor motes.

XBees actually have two communication modes you can choose between, by choosing different firmware. The simplest is the AT firmware. These provide simple, text-based communications between radios: what one Arduino writes as text comes out on the other. In this mode the XBee also responds to Hayes AT commands, a standard way of controlling a modem (which is what an XBee technically is): we'll explore these commands in another post. This function set -- router and co-ordinator -- sets up what might be called a transparent network, in the sense that it behaves just like a serial pipe. This makes it easy to get things up and running.Text-based interaction isn't great for computer-to-computer communications, however, not least because of the effort (and memory) needed to understand text-based protocols. For this reason, the XBee also supports API function sets that provide binary communications. These are better for computers, and faster when running, but require more programming and more intellectual effort to understand. We'll deal with API communications in another post too.

We'll deal with the details of using X-CTU in another post, as well as explaining how to set up a simple network.

First bit of soldering done

The first proto-shield has been assembled.

The SparkFun prototype shield for the Arduino essentially lets you put a small custom circuit onto an Arduino shield.

Arduino prototyping shield

The "bare" version has a small area for soldering-up in the middle of the shield. I decided to make a slightly more re-usable version with a small breadboard so I could experiment with the electronics without soldering.  The assembly is very easy, although the board is of course very cramped. The "helping hands"  were invaluable.

Several lessons learned: I need a finer bit for my soldering iron, a smaller pair of side-cutters for trimming the wires, and my soldering skills are truly appallingly rusty. The shield has a couple of places where it can take additional headers (for controlling the LEDs and using the spare button that's not being used for reset, and to bring the ICSP connectors through) which it would be useful to have.

The parts arrive

The parts have arrived for the ditch project.

The first tranche of hardware came (in a small box) today:

Enough parts for four sensors and a base station

There are parts here for four sensor packages and a base station. The sensor nodes have an Arduino, a 2mW XBee radio, and a digital temperature sensor. The base station has an XBee and a wired ethernet for connecting up to the internet. There are also some prototyping shields to simplify integration, a wall wart power supply for the base station, and some other goodies to support some other development.

Sensor mote initial parts list

The initial design for a sensor mote puts three temperature sensors together with an Arduino and short-range radio module.

The following is the parts list for a single sensor mote:

  • Arduino Uno -- £18.50
  • Arduino XBee shield -- £12.10
  • Arduino Series 2 2mW XBee radio module -- £17.50
  • Arduino prototype shield -- £10.40
  • Mini-breadboard -- £2.00
  • 3 x DS18B20 one-wire digital temperature sensor -- £11.70
  • Battery holder -- £1.20
  • Enclosure (waterproof, resealable food box) -- £3.50
A total of £76.90 (+ VAT) per sensor, not including assorted wires and resistors.

[UPDATED 11Jul2013: added cost of enclosure]