
JeeNode connected to XBee
Here you see my first setup of a JeeNode with pressure sensor connected to a XBee Series 2 module. And it’s working! With Hyperterminal i captured the raw data coming in on my XStick:

XBee API mode packets with sensor data
The ‘experts’ will immediately recognize the first character (tilde, ~) as being the frame header of a XBee packet. The payload on the first line is ’26311 39767′. All characters before that are XBee API frame related as well as the last character, which is the checksum. When you have a look at the code you can see what the payload is made of.
This is absolutely very cool; it think in total it has cost me an evening to put this all together; something i would have never dared dreaming about a year ago!
But there’s still a lot to do:
There seems to be a timing issue in the code, cause i saw the XBee having a bit of trouble joining the PAN. Maybe give it some more time in the setup routine, or give some more time during powering up the XBee to send a new sample… we’ll see.
I need to write some software on PC-side to test reliability of it all.
How long will the batteries survive? I haven’t got a clue… and how am i going to test this? For example, i can’t switch off my PC now, cause the XStick is powered by it; XStick not powered means no PAN means the XBee will keep on searching for the PAN and will use much much more power…
To make the whole package smaller, i need to stop using the pin headers on the JeeNode and just solder the wires right onto the board.
A big step ahead, but still a lot of questions to be answered…
Here’s the code that is currently running on the JeeNode:
#include <Ports.h>
#include <RF12.h>
#include "PortsBMP085.h"
#include <avr/sleep.h>
#include <NewSoftSerial.h>
NewSoftSerial XBSerial = NewSoftSerial(2, 3);
PortI2C two (2);
BMP085 psensor (two);
int pinXBee=7; // to Control XBee on/off
int pinCTS=6; // to monitor CTS
static int SampleInterval = 1000; // 60000;
static int HeartBeatInterval = 10000; // 300000;
static int CTS=0; // value of XBee CTS pin
struct {
int16_t temp;
int32_t pres;
} payload;
static void lowPower (byte mode) {
// prepare to go into power down mode
set_sleep_mode(mode);
// disable the ADC
byte prrSave = PRR, adcsraSave = ADCSRA;
ADCSRA &= ~ bit(ADEN);
PRR &= ~ bit(PRADC);
// zzzzz...
sleep_mode();
// re-enable the ADC
PRR = prrSave;
ADCSRA = adcsraSave;
}
EMPTY_INTERRUPT(WDT_vect); // just wakes us up to resume
static void watchdogInterrupts (uint8_t mode) {
MCUSR &= ~(1<<WDRF); // only generate interrupts, no reset
cli();
WDTCSR |= (1<<WDCE) | (1<<WDE); // start timed sequence
WDTCSR = bit(WDIE) | mode; // mode is a slightly quirky bit-pattern
sei();
}
static byte loseSomeTime (word msecs) {
// only slow down for periods longer than twice the watchdog granularity
if (msecs >= 32) {
for (word ticks = msecs / 16; ticks > 0; --ticks) {
lowPower(SLEEP_MODE_PWR_DOWN); // now completely power down
// adjust the milli ticks, since we will have missed several
extern volatile unsigned long timer0_millis;
timer0_millis += 16L;
}
return 1;
}
return 0;
}
static MilliTimer SampleTimer; // Interval for reading a sample from the BMP085
static MilliTimer HeartBeatTimer; // forced maximum interval (Heartbeat)
static byte periodicSleep (word msecs) {
// switch to idle mode while waiting for the next event
lowPower(SLEEP_MODE_IDLE);
return SampleTimer.poll(msecs);
}
static void Send (const void* ptr, byte len) {
unsigned long tXB1; // time XBee was woken up
unsigned long tXB0; // time XBee was put to sleep
Serial.println("Sending payload");
HeartBeatTimer.set(0);
CTS = HIGH;
tXB1=millis();
// wake up Xbee
digitalWrite(pinXBee,LOW);
// wait for CTS to become LOW
do
{
CTS=digitalRead(pinCTS);
} while (CTS != LOW);
// wait 2 msec otherwise data will be received all messed up
delay(2);
// send dummy data
XBSerial.print(payload.temp);
XBSerial.print(" ");
XBSerial.println(payload.pres);
Serial.print(payload.temp);
Serial.print(" ");
Serial.println(payload.pres);
// wait again for XBee to finish transmission
delay(2);
// switch off XBee
digitalWrite(pinXBee,HIGH);
}
static int16_t prevTemp; // save previous temp value
static int32_t prevPres; // save previous temp value
// this code is called once per second, but not all calls will be reported
int ReadSensor() {
int16_t temp = psensor.measure(BMP085::TEMP);
int32_t pres = psensor.measure(BMP085::PRES);
Serial.print("Readings: ");
Serial.print(temp);
Serial.print(' ');
Serial.print(pres);
Serial.println(' ');
int changed = (temp != prevTemp) || (pres != prevPres);
prevTemp = temp;
prevPres = pres;
payload.temp = temp;
payload.pres = pres;
changed = 1; // force sending always during testing
return changed;
}
void setup() {
// setup XBee
pinMode(pinXBee,OUTPUT);
digitalWrite(pinXBee,LOW);
pinMode(pinCTS,INPUT);
digitalWrite(pinCTS,LOW); // really necessary?
delay(10);
XBSerial.begin(9600);
// give XBee some time to join PAN
delay(5000);
// let the world know we're here
XBSerial.println("\n[TempPres]");
Serial.println("\n[TempPres]");
watchdogInterrupts(0); // 16ms
}
void loop() {
if (periodicSleep(SampleInterval)) {
// sensor values changed or heartbeat interval elapsed?
if (ReadSensor() || (HeartBeatTimer.poll(HeartBeatInterval)))
{
Send(&payload, sizeof payload);
}
}
}

January 31st, 2010 at 21:13
[...] Wireless Pressure Sensor – first results Jan 31 [...]
May 5th, 2010 at 20:35
[...] that my Zigbee/Jeenode equipped pressure sensor is working for 3 months without any problems, it was time to leave the breadboard stage and move on [...]