I plan on running the XBee on a LiPo battery for the small form factor and high power density. In order to avoid damaging the battery (and lighting my apartment on fire), I added an undervoltage protection circuit to the board. When the battery voltage dips below ~3v the voltage regulator is disabled. When the regulator is disabled, the entire board is effectively put into in a ultra lowpower sleep mode. A LM3671 DC-DC regulator is used in combination with a STM811T reset circuit.
XBee Series 1 modules can be configured to periodically sample ADC/Digital IO data and transmit samples, without the use of an external microcontroller. Neat huh? They also can be configured to enter a low power sleep mode between samples. In this manner, XBee Series 1 modules can be used as low power data collection devices. With a reasonably sized battery, a device can run several months before recharging. XBee configuration is done with the X-CTU tool from Digi. For this project four XBees will be used, three configured as data collecting "end-points" and one as a "coordinator". The end-point devices will be battery powered and will utilize the low power sleep mode. At set intervals (currently 45 seconds), the devices will wake up, sample the temperature sensor, transmit the data back to the coordinator, then go back to sleep. My XCTU profile for the endpoint is here, the "MY" 16-bit source address needs to be changed to a unique value for each endpoint.
The LM335A temperature sensor has a range of -40C to 100C. The sample circuit runs off a 5v supply, however, with a 3.3v supply the maximum temperature is 330K aka 134F. I certainly hope that my apartment never gets quite so hot! The calculations below show how the resistor, R1, is selected based on a 3.3v supply and a target 1 mA current. The LM335A operates with between 400uA and 5mA of current. I read that "self-heating" is a factor, as such, I figured lower currents were less likely to heat the device up and introduce measurement error. I selected a 300 ohm resistor primarly because I had three 100 ohm resistors on hand.
The LM335A can connect to any of the ADC inputs on the XBee series 1 modules. As seen in the Eagle schematic below, I selected ADC1. The STM811 chip in the schematic disables the LM3671 DC-DC regulator if the battery voltage drops below 3.08v. This undervoltage protection circuit prevents the LiPo battery from being damaged from being overdrawn.
The python-xbee library provides an easy to use interface for receiving XBee sample data. The code below runs on the Raspberry Pi recording data samples to a log file for futureplotting.
A cronjob runs every 5 minutes:
from xbee import XBee import serial from datetime import datetime import calendar PORT = '/dev/ttyUSB0' BAUD_RATE = 9600 f = open('tempData0.log','a',0) f1 = open('tempData1.log','a',0) # Open serial port ser = serial.Serial(PORT, BAUD_RATE) # Create API object xbee = XBee(ser) # Continuously read and print packets while True: try: response = xbee.wait_read_frame() print response temp = float(0.0) samples = response['samples'] for ea in samples: temp += float(ea['adc-1']) avgADC = temp/len(samples) print "# Samples ",len(samples) print avgADC #tempStr = response['samples']['adc-1'] tempK = (avgADC/1024.0)*3.24*100 tempF = ((tempK-273.15)*1.8)+32.00 d = datetime.utcnow() now = calendar.timegm(d.utctimetuple()) ps = str(tempK) + "," + str(tempF) + "," + str(now) print ps if(response['source_addr'] == "\x00\x00"): f.write(ps) f.write("\n") elif(response['source_addr'] == "\x00\x01"): f1.write(ps) f1.write("\n") #print "Received data from other than node 0" except KeyboardInterrupt: break f.close() f1.close() ser.close()
The script "getTemp.sh" takes the last 10000 samples gathered and plots them in octave.
# m h dom mon dow command */5 * * * * /home/pi/getTemp.sh
The octave script "temp.m" reads the 10000 samples in (formatted in CSV), generates a plot and saves it as a JPG image.
#!/bin/bash cd /home/pi/ tail -n 10000 tempData0.log > temp0_10000.log tail -n 10000 tempData1.log > temp1_10000.log octave temp.m
z = csvread('temp0_10000.log'); z1 = csvread('temp1_10000.log'); y = z(:,2); x = z(:,3); y1 = z1(:,2); x1 = z1(:,3); h = figure(1); plot(x,y,'b'); hold on plot(x1,y1,'r'); xlim([min(x1(1),x(1)) max(x(length(x)),x1(length(x1)))]) set(gca,'xgrid','on'); set(gca,'ygrid','on'); set(gca,'yminortick','on','yminorgrid','on','xminorgrid','off'); saveas(h,'autoTemp','jpeg'); exit
The image, "autoTemp.jpg" is symbolically linked in the Apache server directory, thereby hosting the most up to date image.