Saturday, February 9, 2013

The Raspberry Pi and Wireless RF (XRF) Temperature Loggers

Remote Temperature Logging - Why?

In our house one room has three exposed wall, as well as two double width windows fitted (one on each side of the room).  In the winter, this is a cold room. Very, very cold.

We're in the process of getting the central heating and double glazing replaced (they're both over 15-20 years old respectively) and are very ineffecient - I was however wondering what improvement we'd see once this work had been done. Really though what I wanted was an excuse to use as the basis for a project with my Pi, which I'd bought over 8 months ago and hadn't yet gotten aaround to playing with.

A Pi, wireless communication, python, Linux, soldering...now this sounded like fun!

First I searched for what I could use for this - what could I use that captured and could transmit temperature information - and most importantly, what could do this in a wireless way?

I found the answer using a combination of 1 Slice of Pi, a 2 Temperature XRF Sensor's and 3 XRF Wireless RF Radios, all of which I got from CISECO.

The documentation of the above is pretty decent, but there were still a number of threads you have to tie together to get all of this to work, so here we go:

The XRF that will sit on the Pi will act as a pass-thru receiver, where any data received from the Serial line will be broadcast on PANID, and for our purposes, any data received on PANID or PANID2 will be sent to the Serial line. (more on PANID later).

The remote sensors XRF will need to be configured as Thermistor "personality" - this will capture the temperator from the onboard thermistor and transmit it.

Out of the box the XRF modules will have the serial pass-through personality, so the first thing we have to is upload the thermistor firmare to the two XRF modules that will be used for temperature capture.

At a high level, you'll need to do the following:
  • Configure the Pi so that you can use the Serial Port
  • Install pySerial onto your Pi
  • Get the XRF Uploader downloaded and compiled onto your Pi
  • Download the latest XRF Thermistor firmware
  • Upload the Thermistor firmware to each of the remote modules
  • Configure the remote devices
  • Write software to read what's being sent!

Configure the Pi Serial Port

By default the stock raspbian (and debian I think) images use the UART for serial console communication - we need to change this so that we can use the serial port.

Note: For each of the system files modified here I suggest you back them up first, in case you need/want to roll the changes back

Modify /boot/cmdLine.txt to remove references to ttyAMA0 - this is the serial port

sudo vi /boot/cmdLine.txt

I needed to remove the following lines:

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200  

and my cmdLine.txt now looks like this:

dwc_otg.lpm_enable=0 rpitestmode=1 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait

Next we need to edit /etc/inittab:

sudo vi /etc/inittab

and comment our (or remove) the following line:

T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

Install pySerial 

I used pySerial for my final program, but I also found it useful to use the included miniterm.py serial terminal for configuration and debugging.

Navigate to where you'd like to install pySerial - I'll assume you're installing into your home directory for now (/home/pi or the shorthand ~)


Download pySerial 2.5 (and use Python 2.x, not Python 3) from here and copy it to /home/pi (or your preferred location)
 

cd ~
gunzip pyserial-2.5.tar.gz tar - xvf pyserial-2.5.tar
cd pyserial-2.5
sudo python setup.py install


You can test your installation by doing the following:

pi@raspberrypi ~ $ python
Python 2.7.3rc2 (default, May  6 2012, 20:02:25)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser=serial.Serial('/dev/ttyAMA0',9600)
>>> ser.inWaiting()
0


If you don't get any errors with this you're probably ok - your serial port is ready for your use and pySerial is install correctly.

Thermistor Firmware - Download and Prepare

You need to do this on the remote sensors.

You can, optionally, also do follow the same steps for the local XRF module if you want to upload the very latest serial pass-through firmware too.  The same steps, but you'll download/upload the serial pass-through firmware instead.

The official process can be found on the OpenMicro site, but here are my abbreviated steps:

Note: All of these steps are to be done on your Pi
  • Get the XRF Uploader from here: http://github.com/CisecoPlc/XRF-Uploader
  • Copy this to your PI and run the following on it  g++ xfr_uploader.cpp -o xrf_uploader
  • chmod +x xrf_uploader
  • Download the appropriate firmware - you want the latest llapThermistor-XXX version

Firmware Upload

Ensure your Slice of Pi is fitted to your Pi first.

A Raspberry Pi, a Slice of Pi and an XRF module
A Raspberry Pi, a Slice of Pi and an XRF module

For each of the XRF modules you want to update (the remote modules and optionally the local one, if you want to update the serial pass-through firmware), do the following:
  • Switch off your Pi (you can do this by hot-swapping I've heard, but I wouldn't recommend it )
  • Plug in your XRF module into your Slice of Pi
  • Switch your Pi back on
  • ./xrf_uploader -d /dev/ttyAMA0 -f llapThermistor-XXX
If you see something along the lines of:

pi@raspberrypi ~/xrf_loader $ ./xrf_uploader -d /dev/ttyAMA0 -f llapThermistor-V0.50-24MHz.bin
Writing new firmware file llapThermistor-V0.50-24MHz.bin to device /dev/ttyAMA0 with baud rate 9600...
Reading firmware file...
Read 1162 lines from firmware file
Opening device...
Setting serial parameters...
Waiting for device to settle...

<> Entering command modus
Timeout, no data received within 10 seconds


Either retry again, or switch off and reseat the XRF, and retry the process again.

A successful upload should look as follows:

pi@raspberrypi ~/xrf_loader $ ./xrf_uploader -d /dev/ttyAMA0 -f llapThermistor-V0.50-24MHz.bin
Writing new firmware file llapThermistor-V0.50-24MHz.bin to device /dev/ttyAMA0 with baud rate 9600...
Reading firmware file...
Read 1162 lines from firmware file
Opening device...
Setting serial parameters...
Waiting for device to settle...

<> Entering command modus
<- OK
-> ATVR
<- 0.63B XRF
<- OK
-> ATPG
<- OK
<> Sent 1162 of 1162 lines...


All OK, XRF successfully reprogrammed!

Waiting for device to settle...

<> Entering command modus
<- OK
-> ATVR
<- 0.50B APTHERM
<- OK

Optional! Set the PANID

The PANID is the ID that the XRF network will communicate on - if you leave it do the default everything will work just fine - I've changed mine mostly for security.  I'm probably just being over cautious - if you leave yours on the default PANID every else documented here will still work.

Note: If you do decide to set the PANID then the best time do to this is probably immediately after the firmware upload, and note too that you'll need to set the same PANID for every XRF module in your network

I'm using miniterm.py (included with pySerial, found under /pyserial-2.5/examples/miniterm.py) for these steps:

pi@raspberrypi ~ $ python ~/pyserial-2.5/examples/miniterm.py /dev/ttyAMA0
--- Miniterm on /dev/ttyAMA0: 9600,8,N,1 ---
--- Quit: Ctrl+]  |  Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---


(Note: Entering Ctrl+T and then Ctrl+E will enable local echo, which can be useful when debugging)

The XRF should to each command with respond with "OK":

+++<no return>
ATID[4 hex chars, up to a max of EFFF]<return>
ATAC<return>
ATWR<return>


To Check the ID (but note, the output may be partly overwritten with OK):

Wait for 5 seconds
+++
ATID<return>

Test our new XRF network!

First a note on the two type of communication protocols available with the XRF modules - one is the the one we've used up until now, which the AT command mechanism and is the "direct", plugged in protocol.

The second is the over the air LLAP protocol - this is what we'll use to communicate between the XRF modules.

See here for the AT command reference and here for the LLAP command reference documentation.

Plug your remote XRF modules into the Thermistor boards - below are mine, one bare and one in the included enclosure (with holes drilled in by me for the XRF aerial and thermistor):

XRF Thermistor Modules
XRF Thermistor Modules

Ensure your Pi is setup with the Slice of Pi and your "local" XRF module plugged in.

Log into your Pi and using the serial terminal of your choice (I'm using miniterm.py) hop onto the serial port:

python ~/pyserial/pyserial-2.5/examples/miniterm.py /dev/ttyAMA0

Now plug the battery into one of your remote sensors (note: you probably want to hook up to a 3.3V power supply while testing as permanently on use while testing will drain the small 3V cells included in the remote modules really quickly)

You should see the following in your terminal:

a--STARTED--a--STARTED--a--STARTED--a--STARTED--a--STARTED--a--STARTED--

A quick note on the LLAP protocol (please see the command reference above for the full documentation), taken from the OpenMicro site:

The message is 12 characters long and in 3 distinct sections. To illustrate the 3 separate parts to the message, see this example:

aXXDDDDDDDD

1.  "a" is lower case and shows the start of the message
2.  XX is the device identifier (address A-Z & A-Z)
3.  DDDDDDDDDD is the data being exchanged.


So the a--STARTED message above is letting us know that the remote XRF module is talking to our local one - yay! Now lets see if we can communicate back to the remote XRF module:

Enter a--HELLO---- into your terminal - the remote XRF module should respond with HELLO - you can now communicate both way - fantastic.

Lets set the device ID of the remote XRF module - this is optional but if you're planning on more than 1 remote module I'd recommend it as you'll then be able to identify which module is talking.

In your serial terminal, issue the following commands:

a--CHDEVID[A-Z][A-Z]     (for example, a--CHDEVIDZZ will set the device ID to ZZ)
a--REBOOT---

The device should respond with the started messages again, but with the new ID:

aZZSTARTED--aZZSTARTED--aZZSTARTED--aZZSTARTED--aZZSTARTED--aZZSTARTED--

(assuming you used ZZ as your device ID)

Lets test it again:

Enter aZZHELLO---- into your terminal - the remote XRF module should respond with HELLO once more - you can now communicate using the new ID.

Finally, lets test that we can get a temperate reading back (which after all is what we're really after here!):

Enter the following command into your serial terminal:

aZZTEMP-----

You should get the temperature in Celcius back, along the lines of:

aZZTMPA18.78

You can get the thermistor module to send this periodically too, which is useful while testing:

aZZINTVL005S - this will get the device to send the temperature every 5 seconds

(the interval is 1 to 999 and the periods can be S(seconds), M(minutes), H(hours), D(days))

Once you're finished testing you can save the interval setting and make the device sleep between intervals by issuing the following command:

aZZCYCLE----

In addition to sending out the temperature at the set frequency, it will also send out the battery level every 10 cycles, which is useful.

Note however, that once you do this you'll be unable to communicate to the device while its sleeping, so only do this once you're happy that your network is working as desired (if you do however get it into a cycle and you decide you want to change the interval you can (again from the OpenMicro site) Ground pin 6 - this will force the device to be awake, you can then issue commands to change to interval or other settings. Note that unless you tell the device to stay awake (axxWAKE-----) then it will resume sleep as soon as you remove the ground from pin 6.)

Repeat the above exercise for each remote device - one at a time.

 

Write software to read what's being sent!

Below is a small program that will poll the serial port every minute for new messages (for this example I've set the XRF modules to send out a response once every 5 minutes):

import serial
from time import sleep, gmtime, strftime

DEVICE = '/dev/ttyAMA0'
BAUD = 9600

print (strftime("%a, %d %b %Y %H:%M:%S: Starting\n", gmtime()))

ser = serial.Serial(DEVICE, BAUD)
while True:
    print("%s: Checking..." % strftime("%a, %d %b %Y %H:%M:%S", gmtime()))
    n = ser.inWaiting()
    if n != 0:
        msg = ser.read(n)
        print("%s: %s" % (strftime("%a, %d %b %Y %H:%M:%S", gmtime()), msg))
    sleep(1 * 60)


An example of the output I get is:

Sat, 09 Feb 2013 21:00:14: Checking...
Sat, 09 Feb 2013 21:01:14: Checking...
Sat, 09 Feb 2013 21:01:14: aAATMPA3.242aABTMPA12.45
Sat, 09 Feb 2013 21:02:14: Checking...
Sat, 09 Feb 2013 21:03:14: Checking...


Note that I have two devices sending me data here, AA and AB.

That's it - I hope you find this useful!

29 comments:

  1. Nice build. Since each xrf sensor has it's own unique hardware identifier, why are you using a separate xrf radio for each sensor? On the base unit (pi + slice of pi), why not have a single xrf radio, then have your program parse the poll data from each remote data source (Eg. each remote xrf sensor)?

    ReplyDelete
    Replies
    1. Hi David

      Thanks for your comment.

      I'm not sure I follow your suggestion though. There is only 1 XRF radio on the actual PI (for a total of 3 altogether, including the 2 remote ones): the Slice of PI is on the PI, and the XRF module is on the Slice of PI - there is only 1 XRF radio on the base unit.

      As for the remote sensors, they each need a dedicated XRF radio in order to transmit their respective temperature readings as they're not anywhere near each other.

      Is this what you meant or am I missing something?

      thanks!

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi Sean, thanks for your post!
    I have a question: has you put the interval to 5 secondes (aZZINTVL005S) I do not understand your output example with a check every 60 seconds but strangely (for me) you do not have all the time an answer, why?

    Sat, 09 Feb 2013 21:00:14: Checking... No answer?
    Sat, 09 Feb 2013 21:01:14: Checking...
    Sat, 09 Feb 2013 21:01:14: aAATMPA3.242aABTMPA12.45
    Sat, 09 Feb 2013 21:02:14: Checking... No answer?
    Sat, 09 Feb 2013 21:03:14: Checking... No answer?

    ReplyDelete
    Replies
    1. Hi Llyod

      Sorry for the delay in replying.

      I can see the confusion here - the aZZINTVL005S was an example, but in the later program the poll was actually set to 5 minutes. I've updated the the relevant section to clarify this - thanks for giving me feedback!:

      "Below is a small program that will poll the serial port every minute for new messages (for this example I've set the XRF modules to send out a response once every 5 minutes):"

      Delete
  4. Hi,
    Excellent article!
    Can You tell why I'm getting only a--STARTED-- message, but no response for the a--HELLO----?
    I understood enter is not required after command.
    I'm using Dallas sensor.

    Br. Jari

    ReplyDelete
    Replies
    1. Hi

      Thats a tricky one - what are you using to communicate with the Pi? Maybe you can read the data from the Pi but arent able to send?

      Delete
    2. Hi Jari,

      I'm experiencing the same problem. Did you ever find a solution?

      Louis

      Delete
    3. Hi Louis

      Sorry to hear you're both having problems with this - what are you using to communicate with the XRF?

      Delete
    4. Hi Sean,

      Thanks for the quick reply.

      I have one XRF radio plugged into the pi (via one Slice of Pi) and I am monitoring this using miniterm.

      The other XRF radio is currently plugged into my Windows PC via USB XBee Explorer and I am monitoring this using XCM.

      When I add the radio to the XBee explorer I see 6 a-STARTED-- in miniterm.

      Also when I insert the battery into the remote thermistor board I get 6 a--STARTED-- in miniterm.

      I'm struggling with the next step.

      Louis

      Delete
    5. Hi Louis

      Sorry for the delay, I've recently started a new job which is keeping me pretty busy.

      Have you managed to get this to work yet?

      If not, then as I'm not using exactly the same setup as you it may be difficult to help here, but the only thing I can think of is that your outbound communication isnt working. Did you try to enable local echo (Ctrl+T and then Ctrl+E) to see if what you're typing is actually being output?

      If possible you could also try to talk to your PC (or another Pi etc) and see if your commands from miniterm are being received.

      Delete
    6. Yes, I did get it work in the end.

      I couldn't get the a--HELLO---- communication to work, but I managed to communicate via a some python code.

      Thanks for the tutorial.

      Louis

      Delete
    7. I was having the same problem. The way to make a--HELLO---- to work on miniterm is to prepare the command and paste it.
      Source: http://openmicros.org/index.php/component/kunena/10-ciseco-support/3077-xrf-responds-to-some-at-commands-but-not-llap?Itemid=0#4551

      Delete
    8. Great link - thanks for that!

      Delete
  5. I just placed an order for a Slice of Radio / Slice of Pi (for reprogramming purposes), 1 thermistor temperature sensor with XRF module, 1 double button kit with XRF module and 1 double relay kit with XRF module with Ciseco after reading this very handy guide.
    All for testing purposes and will later move on to a project where I read temperatures from a couple of rooms inhouse and depending on some user based settings get my Heater to start pumping hot water to my rooms or not.
    After that will even add some electrovalves on the collectors to replace my thermostat valves on the heating elements.
    That way the hot water will only reach to cold rooms.

    ReplyDelete
    Replies
    1. Sounds like a great plan - I'm hoping to do something similar next. At the moment I'm writing a desktop app that will receive the temperatures from the Pi and plot the different zones. Later I'll add the ability to configure the XRFs from the app too.

      Good luck!

      Delete
  6. Just wanted to say kudos on the handy guide. Hope all goes well over here with the reprogramming part of the XRFs

    ReplyDelete
  7. Hello,
    Thank you for this excellent tutorial !
    Can please tell me why you need to order 2 Slice of Pi ? One is not enough ?

    ReplyDelete
    Replies
    1. Also, did you buy any other components like boxes, resistors ? Or if i buy all from your list, all is included and i can use it out of the box ?
      Thank you :-)

      Delete
    2. Hi,

      Thanks for your comments!

      You are right, only 1 Slice of Pi is needed - thanks for spotting the typo.

      As far as I remember all the parts I needed were included in the kits I bought.

      Good luck!

      Delete
  8. Hey Sean,

    i have a Problem with the PAN ID's.
    I have several Raspberrys and several XRF Thermistor modules.
    Now I want that raspberry A only communicate with XRF Thermistor modul A and Raspberry B only communicate with XRF Thermistor Modul B.

    But how set i the PAN ID for the XRF Modul on the PI.

    I hope you can understand me

    Greetz

    ReplyDelete
    Replies
    1. Hi,

      I'd try set the PAN IDs for each pair, one pair at a time, as shown above.

      If you set them to different PAN IDs then the respective pairs shouldn't have any knowledge of each other.

      As my reply is a bit late (sorry!) you may already have gotten this to work - if so I'd be interested in what you did :-)

      thanks!

      Delete
  9. Hi,

    Thanks for your article.

    I did setup a system with 2 temperature sensor but having strange issue and can't find any solution yet.

    I receive fancy temperature readings out of my sensors.
    2 sensors are at 2 cm of each other.
    i am receiving a difference of 2 or 3 degrees Celsius difference between them
    one is giving me 24 degrees and the other 27.

    The one at 24 degrees after approximately 5 or 6 intervals is giving me 27 degrees and then goes back slowly to the normal temperature (26 and then 24 again).

    Does anyone here have the same reaction ?

    What can i do to correct this issue ? i know there is a setting to define the 25° of the themistor (aXXRNOM10000) but don't know what i need to do with it, i typed this command and get the same temperature after.

    Am i the only one to get weird temperature readings ?

    ReplyDelete
  10. Thanks for a great post - the only place I have found that walks through a typical use case for a Ciseco Thermistor and an XRF in easy steps. Got my set up working a treat!

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. This is the most comprehensive guide I've found on the XRF modules. Thanks

    ReplyDelete
  13. Superb article, thanks so much.

    Q: is it the remote xrf radio modules or the thermistor modules you had to upgrade the firmware on? Also do received messages on the pi xrf wait in the buffer until they are read by the polling python programme?

    ReplyDelete
  14. Hi, I use the xbee module not the xrf module, can I do in the same way??I have checked the AT command link here, I am not find ATDH+DL there, which I think is required in Xbee, I am not sure if I can follow your guide. Now I am at the step
    "pi@raspberrypi ~/xrf_loader $ ./xrf_uploader -d /dev/ttyAMA0 -f llapThermistor-V0.50-24MHz.bin
    Writing new firmware file llapThermistor-V0.50-24MHz.bin to device /dev/ttyAMA0 with baud rate 9600...
    Reading firmware file...
    Read 1162 lines from firmware file
    Opening device...
    Setting serial parameters...
    Waiting for device to settle...

    <> Entering command modus
    Timeout, no data received within 10 seconds"

    Mine is timeout, no matter how many time I retried, it always timeout there.

    ReplyDelete