preload
Feb 14

On my desk i have a JeeNode, equipped with a Pressure sensor. This JeeNode is also controlling a XBee Series 2 module which is configured as Zigbee End Device. All this is battery powered. Calculations on power usage of the JeeNode+Sensor+XBee are good enough to expect an acceptible battery life. A Sparkfun XBee RS232 holds another XBee module, configured as Zigbee coordinator. This setup has been operating for more than a week now. It all looks stable enough to go ahead and connect the Zigbee network (ok, it’s only 2 nodes right now :-) ) to my Domotica system and  actually do something with it; something different from logging the incoming pressure data to a text file and reviewing this file periodically to see if everything is still up and running; so i added another (the 16th) interface to my Domotica system: Zigbee! :-)

In fact all the hard work had already been done in an earlier stage where i created an API-mode interface for Zigbee; in essence, the only thing left to do was making this interface ‘talk’ to the rest of the Home Automation system, add some records in the database for this new sensor type and write a routine that would convert the incoming packets to the measured values of temperature and pressure.

Zigbee interface

Wow! It’s great to see my first Zigbee based sensor really working! The pressure data is being stored in the database, so in a few hours i can start creating an additional web page to show a pressure chart… and here it is!

BMP085 Pressure sensor data

BMP085 Pressure sensor data

Next on the list: finding a suitable, small housing, making a light sensor, a motion sensor, humidity sensor, … the list is to long! :-)

Tagged with:
Feb 14

Now that i have 2 JeeNodes up and running for more than a week and everything’s working fine, it’s time to do some calculations on power usage of the sensors. First thing i wanted to know was how much power a combination of a sensorless Jeenode and XBee module was using, so i created a sketch that would give me some ‘inside’ information about what was going on inside the Jeenode. The sketch i made informs me about a couple of things, like:

- the timespan the JeeNode is awake to power up the XBee, send a packet to the XBee and wait for it to finish transmission;

- the timespan the XBee is powered to send that packet of 10 bytes.

Battery powered JeeNode

With these numbers i should be able to roughly calculate the power usage of this sensor. The power that is used by the JeeNode while it’s awake is about 35 mA, while the XBee uses around 40 mA while transmitting. When both the JeeNode and XBee are in deep sleep, the combination of both uses only 60 μA.

The time measurements i did to find out the timespans mentioned above gave me the following figures: the total time the JeeNode is awake to read a sample from the Pressure sensor, wake the XBee, transmit the data and go back to sleep is 40 ms. The time that the XBee is awake is around 25 ms. With a sample interval of 30 seconds, and a 2000 mAh battery, i have calculated a battery life of more than a year; increase the interval to 60 seconds (still good enough for this type of information) and batteries should survive more than 2 years… i think.

Just ask me in a year or so ..

But good enough to go ahead with the expedition! :-)

Tagged with:
Jan 31

The fact that in the setup i made yesterday, the XBee module sometimes had trouble setting up the connection was troubling me, so i tried to figure out what was going on. My guess was that the CTS line was not monitored, so i built a counter into the loop that waits for CTS to get high; and made this counter part of the packet payload so that i could monitor what was going on; this counter  was always 1, meaning CTS was high at the time the first CTS check was done!

Hmm, seeing that, the error was found very quickly: CTS was attached to the wrong digital input, so CTS wasn’t monitored at all… fixed the wiring and now everything’s OK.

Second thing i changed was for the sake of convenience: the new sketch does the temperature and pressure calculations “on board”, so now the payload immediately shows value that are easily interpreted. I also took the time to create a small Delphi program that uses my XBee API to log all the packets that are received in a more readable style:

31-1-2010 20:43:30:Packet payload=[2 215 100159]
31-1-2010 20:43:41:Packet payload=[7 215 100150]
31-1-2010 20:43:52:Packet payload=[0 215 100153]
31-1-2010 20:44:03:Packet payload=[0 215 100156]
31-1-2010 20:44:14:Packet payload=[0 215 100166]
31-1-2010 20:44:25:Packet payload=[5 215 100156]
31-1-2010 20:44:36:Packet payload=[10 215 100159]
31-1-2010 20:44:47:Packet payload=[0 215 100150]
31-1-2010 20:44:59:Packet payload=[0 215 100156]
31-1-2010 20:45:10:Packet payload=[0 214 100153]

The first value is the time in milliseconds that it takes for the CTS to become high, the second value is the temperature in 1/10th of a degree and the last value is the pressure in mbar.  Neat :-)

Tagged with:
Jan 30
JeeNode connected to XBee

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

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);
       }

    }
}
Tagged with:
Jan 30

I don’t own a weather station, nor do i intend to buy one, but i always did like the idea of having a pressure sensor. Now i have :-)

This BMP085 based pressure sensor doesn’t only do pressure, but can also measure the temperature. Time to hook it up to a JeeNode!

Due to the fact that our plans for today had to be canceled by the bad weather, i had some extra time to test this Pressure Sensor. First i had to solder the 2nd JeeNode i bought last week, cause it was still unassembled in it’s plastic bag. Soldering a JeeNode is quite easy to do; it’s really hard to do something wrong… This time i left the RF12 radio off because i wanted to use one of my XBee modules to send the raw measured values. And i attached a battery holder, cause eventually this is my goal: a battery powered pressure sensor.

I installed the Ports library, uploaded the BMP085 demo sketch from the Ports Library examples  to the JeeNode and everything ran fine:

BMP 26265 39759 225 99390
BMP 26260 39755 225 99372
BMP 26267 39761 226 99400
BMP 26263 39756 225 99378
BMP 26265 39759 225 99390
BMP 26263 39758 225 99384
BMP 26261 39757 225 99378

Next step will be adding code for the XBee and sleeping. To bad, time’s up for now… hopefully, later this evening i have some time left to finish this sensor.

JeeNodev4 with BMP085 Sensor

JeeNodev4 with BMP085 Sensor

Tagged with:
Jan 06

Recently i bought a new sensor to see if i can improve the way my outdoor lights are switched on when it gets dark.

Currently, this is done by calculating sunset and switching the lights on exactly at sunset.
I’m not very satisfied with that, cause sometimes this is to early and sometimes this is to late.
So i bought a KlikAanKlikUit ABST-604 sensor to see if this sensor can improve on this.

I’m going to watch the times at which this sensor thinks it’s dark enough to switch on the lights and if this looks better then the sunset-calculated switching, i’ll change the trigger for switching the outdoor lights on to this sensor.

Tagged with:
Aug 12

While going through the log file of packets that arrive on my RFXCOM receivers but that are not recognized as coming from one of my own devices, i discovered one of my neighbors must have bought some stuff from Oregon Scientific. It looked like i was receiving signals from a Oregon Scientific, namely a RGR918 (a rain gauge) and a WGR918 (an anemometer). Wow, this hasn’t happened before; this is the first time I’m receiving interesting packets from devices that are not mine…

The RGR918 transmits the current rain fall rate, total rain fall, and battery status. The accuracy is 1 mm. Transmission is done every minute IIRC.

The WGR918 sends out information about wind speed, average wind speed and the wind direction. And battery status ofcourse.

So all i had to do was add some lines of code to my HA application et voila, i had all the information mentioned above right where i wanted them; because of the ‘modular’ structure, it was very easy for me to start collecting and storing the data, produce charts of them, and so on. I can even watch the battery status of those 2 devices and warn my neighbour when the time has come to replace them :-)

All i have to do for that is find out who that neighbor is … i haven’t found the location of the Oregon devices yet!

Tagged with:
May 20

Today the Oregon Scientific THWR288 Water Thermo Sensor arrived. It can be viewed on the DeviceStatus page and there’s a Chart of the Temperature in our swimming pool.

Tagged with: