preload
Jul 26

While i was quite happy yesterday with the new way i’m going to handle things on the JeeNode regarding the motion sensor (PIR), i already knew i wasn’t finished yet; this was nice, but only a first step.

Cause what i had created was an IRQ being fired when the input becomes low. Well, the PIR output becomes high when there’s motion detected, so this is unusable, actually. For a brief moment i considered using a transistor as a NOT gate to invert the PIR output, but there had to be an easier way. Why would you only be able to activate an External Interrupt when a pin becomes low?? I read some topics on various forums, but those were very contradictory; some said i could, some said otherwise. OK, in that case, i’ll sort it out myself .. cause i really need interrupts based on a rise or a change!

Page 71 of the ATmega datasheet learned me that INT0 and INT1 indeed have Interrupt Sense Control and it’s only a matter of setting the right bits in the External Interrupt Control Register A, aka EICRA:

Bit 3 and 2 of EICRA

So it can be done, only thing is to figure out how…

The Arduino attachInterrupt() function has a 2nd parameter with which you can control what triggers an interrupt; the values are the constants LOW, CHANGE, RISING and FALLING (found in wiring.h). So why didn’t that nice Sleep library i found earlier have this feature? All i can do is call this function:

void SleepClass::powerDownAndWakeupExternalEvent(uint8_t interruptNumber)
{
 attachInterrupt(interruptNumber, SleepClass::external_event_handler, LOW);
 set_sleep_mode_and_sleep(SLEEP_MODE_PWR_DOWN);
 detachInterrupt(interruptNumber);
}

OK; changing things in the library depending on the kind of Sense Control i need for a specific sensor type is not an option of course, so i added a 2nd parameter to that function:

void SleepClass::powerDownAnd...Event(uint8_t interruptNumber, int mode)
{
 attachInterrupt(interruptNumber, SleepClass::external_event_handler, mode);
 set_sleep_mode_and_sleep(SLEEP_MODE_PWR_DOWN);
 detachInterrupt(interruptNumber);

}

That’s better; now i can choose whatever Sense Control I want; I’ve checked all of them right away:

Sleep.powerDownAndWakeupExternalEvent(0, RISING);

What a surprise, its working, all of them! RISING is just what i need right now for the PIR; CHANGE is what i would need for a door sensor.

Now i’m already modifying libraries and I can even understand what

EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);

does… i wonder where or when (if ever) this will end…

But I’m still not finished! Cause with all this powering down going on, it has become increasingly hard to keep a notion of time; millis() has become useless cause how can i determine the time that has passed since the last power down? On the other hand, do i really need to know that? Time will tell :-)

Tagged with:
Jul 25

Having a first set of batteries empty wasn’t  funny.. they lasted only 7 weeks! Way to short. And i kept on thinking that it might not have been caused by a bad battery.. what could i do next? Wait another 7 weeks to find out that I’m wrong? Neh.. that didn’t feel the right thing to do; Power down as much as possible and use an external interrupt would possibly give the best results anyway, so why not start with that right now!

I started with attaching a push-button to an Arduino, using a pull-up resistor to keep the input high when the button isn’t pressed:

Arduino with push-button

After that i started reading about interrupts. Here’s a table that shows the Wake-up sources that are available in the various sleep modes:

ATmega48PA/88PA/168PA/328P Wake-up sources

Both things i need are available: INT0 and/or INT1 and the Watchdog Timer, so it was time to start sketching :-)

After 5 different sketches with all the same miserable results (freezing Arduino), i finally found a sleep library that did exactly what i wanted. I combined this library with code i had found earlier regarding setting up and using the Watchdog Timer, and what i have now, is just what i need. Below a sample of the Serial Monitor output and here is the sketch that produced it.

39171 I'm awake, caused by the WDT
39205 Sleeping...
39327 I'm awake, caused by the WDT
39362 Sleeping...
39484 I'm awake, caused by the WDT
39519 Sleeping...
39640 I'm awake, caused by the WDT
39674 Sleeping...
39796 I'm awake, caused by INT0
Doing some work...finished!
40257 Sleeping...
40377 I'm awake, caused by INT0
Doing some work...finished!
40839 Sleeping...
40960 I'm awake, caused by INT0
Doing some work...finished!
41421 Sleeping...
41542 I'm awake, caused by the WDT
41577 Sleeping...
41698 I'm awake, caused by INT0
Doing some work...finished!
42160 Sleeping...
42280 I'm awake, caused by the WDT
42315 Sleeping...
42437 I'm awake, caused by the WDT
42472 Sleeping...
42593 I'm awake, caused by the WDT
42628 Sleeping...

etc. etc.

Cool stuff! :-) Let’s see how we can change the motion sensor to make use of this!

Tagged with:
Jul 16

Lennart Herlaar and me are really hooked up to all this Arduino(-compatible) stuff; we both started somewhere in September 2009 with our first ‘trials’. My first experiment was with an Arduino Duemilanove and some LEDs; resulting in instant addiction! Once you discover what can be done with this platform and how you can use it, every day new ideas and interesting projects pass by. Exciting!

We decided to see if we could share our enthusiasm with a larger group of Domoticans; cause there are a lot of Domotica related things you can do with the Arduino platform. Normally Domotica related hardware is quite expensive and closed, in the sence that every manufacturer creates its own proprietary protocol and tries to keep it a secret as much as possible; even changing it for the sole purpose of making all knowledge gathered by reverse engineering useless(!). Interaction between products of different companies is still very hard (if at all) to find – and most Domoticans are forced to use commercial Home Automation software like Homeseer to tie it all together. However, without a Plugin available for that special type of hardware you’d like to use, you’re practically doomed…

So when we started thinking about organizing an Arduino workshop for the members of the Domoticaforum Europe, we knew right away that we couldn’t do that without also supplying a Homeseer Plugin with it; well at least create a framework that would enable the workshop attendees to connect their new Arduino-based hardware to the most used HA software here in the Netherlands.

And that’s exactly what’s going to happen; when we get enough response (a mimimum of 15) to our post on the Domotica forum and we decide to go ahead with organizing this workshop, we’ll also have to start thinking about how to create an easy to use, flexible, future proof Plugin that can interface with the Arduino platform and it’s compatibles like (my favorite) JeeNodes..

It will be fun! As always :-)

Tagged with:
Jun 20

After my problems with the MS13 sensors yesterday, i managed to find some spare time (even though, or maybe because it was father’s day) to write a sketch for the new motion sensor i created during the last couple of weeks. Always taking one step at a time, i located the first prototype of this sensor at a place where i can see the enclosure LED from the living room: i want to know how it performs…

New motion sensor

New motion sensor

Now powered by 3 rechargable NiCd batteries and with all hardware nicely put away in the enclosure. In due time the enclosure will be moved out of sight so only the PIR will be visible. I’ve decided to use 3.5 mm jack plugs to be able to disconnect the enclosure from the sensor, so i can easily take the enclosure back to my office, because i don’t think the JeeNode is already running the final version of the ‘PIR’ sketch… :-)

A new class, 2 database records and 1 line of code were enough to get the sensor working in my Domotica system:

procedure TAMN31112.ProcessInterfaceData;
begin
  Pin(1).AsBoolean:= (O.Data[1]='1');
end;

The new PIR can be viewed from my website (it’s called BP PIR):

Battery powered PIR

Battery powered PIR

The sketch is still under development; for instance, how much difference would it make if i change the DigitalRead() into a bitRead()? I’ll have to read more about that on JeeLabs … Other questions are: should i increase the heartbeat interval (currently 45 seconds) or the Motion report interval? Can i create some sort of battery power monitoring with the XBee? But that will all be investigated when i’ve finished building my second motion sensor based on JeeNode and XBee..

Tagged with:
May 05

Now 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 to something more permanent. While ordering new Jeenodes at Jean-Claude Wipplers shop, i stumbled upon a post (i should read his daily weblog more often!) that showed me just what i needed: an enclosure that looked just right for this job. I ordered the Jeenodes, 2 enclosures (1 extra for when i mess up the first one and don’t want to wait for a second delivery..) and some other handy stuff.

First i sawed off the part of the PCB that i didn’t need, to decrease it’s size.

JeeNode PCB without RF part

JeeNode PCB size reduction

Guess what? Now the length of the PCB equals the internal width of the enclosure! Nice… I still had some battery holders laying around that also fitted quite well:

Enclose, batt holder and JeeNode

Enclosure, batt holder and JeeNode

I didn’t want to leave off the FTDI headers, so i used 6 straight headers and removed the plastic strip from the headers after the headers were soldered onto the PCB. With the plastic headers left on, the completed PCB was just a bit to wide for the enclosure, which caused tension and the enclosure wouldn’t close well anymore.

Next item that had to be prepared, was the XBee Breakout Board. Normally the top of this Breakout Board contains the 2mm XBee headers and the 0.1″ spaced headers are at the opposite side. I removed the bottom headers i soldered in when i used this board for other purposes and soldered 6 wires on it from the top, only for those pins i really needed:

XBee Breakout Board

XBee Breakout Board

Pin 1 (labeled Vcc) for Power, Pin 3  (labeled DIN) for transmission, Pin 9 (DTR) for controlling Sleep mode, Pin 10 (GND), Pin 11(CTS) and Pin 12 (ON) for the LED. This makes the Breakout board a lot thinner and the wires are coming out between the board and the XBee module.

After soldering the wires coming from the XBee board to the JeeNode, drilling a hole for the LED (which blinks when a pressure sample is being sent), soldering the wires and gluing the battery holder into the enclosure, it looked like this:

Almost done!

Almost done!

The FTDI headers are very handy now, for uploading the sketch with the JeeNode already inside the enclosure; cause all you have to do is open the enclosure, gently lift up the left side of the JeeNode and connect the cable. So whenever i need to upgrade the JeeNode, i don’t have to worry about connecting issues.

FTDI cable connected to the JeeNode

FTDI cable connected to the JeeNode

Now all there was left to do was moving the XBee module and the Pressure Plug from the Breadboard to their new ‘home’, add 4 batteries, click on the other half of the enclosure and.. my first WAF certified sensor was born!

Zigbee Pressure sensor

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 27

Last Friday a Digital Code Lock arrived. I want to see if i can do something useful with it. It is intended for use with a door opener.
Above the keypad there are 3 LEDs of which 2 are freely usable; the 3rd (middle) bi-color LED shows the status of the code lock.  The code lock comes with a manual with description of all connections and some connection examples.

Digital Code Lock

Digital Code Lock

Code Lock Internals

Code Lock Internals

It’s one of the cheaper code locks, but if all goes well and i’m satisfied i might buy another more eye-catching one.

This model has a sabotage switch inside just like the tamper switch on the inside of Visonic sensors. I’m going to connect this switch to a Visonic MCT302 aux input located inside my house and any attempt to sabotage the code lock will fire the alarm. One of the freely usable LEDs is going to display the status of the alarm, the other free LED doesn’t have a function assigned yet. Just a matter of time…

The Code Lock will be supervised by an Arduino so i can make full use of all the functionality it has to offer.

To be continued…

Tagged with:
Dec 27

Today i had some spare time to combine a few of the things i’ve been working on lately:

  • My Zigbee API;
  • Arduino;
  • Pan & Tilt mechanism

I wanted to create a small executable that would enable me to control the position of the 2 servo’s.

XBee module

I started with programming the XBee: Zigbee End Device AT firmware, the right PAN, Node Identifier ED5 (as in End Device 5), Sleep Mode=1 (Pin Hibernate). I put the module on a breadboard by use of a Breakout Board. Grounded pin 9 and used the 3.3V output of the Arduino to power the module.

Arduino

I strapped the Arduino Duemilanove to the same breadboard and wired the 2 servo’s. Pins 9 and 10 of the Arduino are used as PWM output for the 2 servo’s. Arduino pins 2 & 3 were connected to the DIN and DOUT pins of the XBee module.

Sketch

Now it was time to write a sketch that would receive commands from the XBee and move the servo’s accordingly. The sketch is a real quick and dirty one, low on error handling and validation. I made up a small ‘protocol’: commands have to end with the exclamation mark (“!”) and can be either 1 or 2 characters long.

P+! would Pan right 3 degrees, P-! would Pan left 3 degrees, T+! would Tilt up 3 degrees and so on. H! is the command to go back to the Home position. Of course you can extend this as much as you like, e.g. add absolute positioning, presets, you name it.

This is the sketch:

#include <NewSoftSerial.h>
#include <ServoTimer1.h>
#include <PString.h>

ServoTimer1 PanServo;
ServoTimer1 TiltServo;

int PanAngle = 90;
int TiltAngle = 90;
byte DeltaPan = 3;         // move 3 degrees
byte DeltaTilt = 3;        // move 3 degrees
char cbuffer[40] = "";     // receive buffer
NewSoftSerial XBSerial = NewSoftSerial(2, 3);
PString buffer(cbuffer, sizeof(cbuffer));

void setup() {

  XBSerial.begin(9600);         // set up XBee at 9600 bps
  delay(10000);                 // wait 10 sec. for possible joining

  PanServo.attach(9);
  TiltServo.attach(10);

  PanServo.write(PanAngle);
  TiltServo.write(TiltAngle);
}

void waitforcommand()
{
  while (true)
  {
    if (XBSerial.available())
    {
      int c = XBSerial.read();
      if (c == 0x21)     // command terminator = "!"
      {
        break;
      }
      else
      {
        // add to buffer
        buffer.print(c,BYTE);
      };
    };
  };
}

void loop() {

  buffer="";
  waitforcommand();

  // what's the first character?
  switch (buffer[0])
  {
    case 0x50:             // P for Pan
      {
        // what's the next character?
        switch (buffer[1])
        {
          case 0x2B:       // +
            PanAngle += DeltaPan;
            break;

          case 0x2D:       // -
            PanAngle -= DeltaPan;
            break;
          };
          break;
      };
    case 0x54:            // T for Tilt
      {
        // what's the next character?
        switch (buffer[1])
        {
          case 0x2B:       // +
            TiltAngle += DeltaTilt;
            break;

          case 0x2D:       // -
            TiltAngle -= DeltaTilt;
            break;
          };
          break;
      };
    case 0x48:            // H for Home
      {
        PanAngle=90;
        TiltAngle=90;
        break;
      };  

  };

  // check boundaries for Pan
  PanAngle=(PanAngle < 0)?0:PanAngle;
  PanAngle=(PanAngle > 180)?180:PanAngle;

  // check boundaries for Tilt
  TiltAngle=(TiltAngle < 90)?90:TiltAngle;
  TiltAngle=(TiltAngle > 180)?180:TiltAngle;

  // Set dervo's accordingly
  PanServo.write(PanAngle);
  TiltServo.write(TiltAngle);

}

PC software

Next item was a small program that would use the API to address the XBee module.

XBee servo control

XBee servo control

4  buttons for Left, Rigth, Up and Down, a Home button and a button to connect to the Zigbee network. Not very spectacular, I’d say.

There are 2 important API functions that are used to communicate with the Zigbee module:

  • Node Discovery
  • XBee Transmit Request.

The code that is executed when the “Connect” button is pressed, sends out a Node Discovery command. This will trigger all joined Zigbee modules to respond with information about themselves, like 16- and 64-bit address, node identifier and some more interesting stuff. The code goes something like this:

  XB:=TXBEE.Create(14,9600);
  XB.Open;
  gXBeeModules.Clear;
  cmd:=TXBee_NodeDiscover.Create('');
  XB.SendPacket(cmd.GetPacket);

The Node Identifier is used to see if the Zigbee module that is connected to the Arduino, is “in the air”. Cause it doesn’t have to be, it could be disconnected from power or whatever…

When the Zigbee module with Node Identifier “”ED5″ has responded, the 5 buttons are enabled and clicking them will move the servo’s. This is done with the XBee Transmit Request function; a string is being sent to the XBee and the XBee will take care of transferring it out on the UART.  Below the code for the “Home” button:

i:=gXBeeModules.Indexof('ED5');
if i >=0
then begin
Module := TXBeeModule(gXBeeModules.Objects[i]);
Addr16:= Module.Addr16 ;
Addr64:= Module.Addr64 ;
TR:=TXBeeTransmitRequest.Create(1,Addr16,Addr64,"H!");
X.SendPacket(TR.GetPacket);
end;

Et voila, the servo’s start moving!

To see how (good or bad) it works, i’ve made a small video.
The power of Arduino and Zigbee!!!

Tagged with:
Dec 25

Now that i managed to put an XBee ZB module to sleep, all i had left to do was being able to put the RBBB to sleep for a certain amount of time (and have it wake up again!).  It would be very nice if i could use 2 triggers for waking up the controller: based on a predefined interval and by some external source (for example an attached motion detector that detects motion).

Zigbee module

Low-power Zigbee & Arduino

Both are actually equally important, so i tossed a coin with the outcome that i started with trying to accomplish to wake up the RBBB on a predefined interval. I found an article that pretty much did what i wanted. The maximum time that the Watchdog Timer can power down the microcontroller is 8 seconds, after which it will wake up again and carry on with it’s job. I modified some things so that the power down routine is called multiple times, which results in a power down mode in multples of 8 seconds. Currently the wake up interval is set at 32 (4*8) seconds and it has run flawlessly for 16 hours now. I still have to dig in deeper to the Watchdog code see if my ‘modifications’ can be made more efficient, but for now this will be OK.

Now i wonder what the power consumption of this combination of RBBB and Zigbee module is… should i let it run on a battery and wait till it stops? How long will that be…. no; i think it’s better to find a way to estimate battery life by actually measuring the power consumption. That will probably mean i will need extra hardware and tools.

Tagged with:
Dec 24

While working on the experiments I’ve done in the past months with the Arduino Duemilanove, RBBB, XBee Series 1 and 2 modules the thought of a wireless, battery powered, ‘intelligent’ sensor kept me busy.

RBBB controlling a XBee ZB module

RBBB controlling a XBee ZB module

Finally the time had come  to do some experiments  in that direction. I’ve found several very well written articles, all by Jean-Claude Wippler regarding Low-power techniques. This was a very good starting point; one of the things that i concluded is that running on 3.3V is the best choice: it seems it’s much easier to interface with sensors at 3.3V then 5V. So i really gotta have me some JeeNodes soon now! :-)

But it wouldn’t hurt to already start searching the net for code that would support bringing the ATMega to a state in which it would consume much less power.  I had already found a way to bring an XBee module to deep sleep by setting Sleep Mode (SM) to 1 and grounding pin 9, so now it was time to start sketching and produce something that could put both the RBBB and the attached XBee to sleep for a fixed period, wake them up, take samples of whatever sensor is attached, send the data to the Zigbee Coordinator and go back to sleep again. I didn’t want to use any external trigger, so the solution had to be found inside the MCU itself.

Putting XBee to sleep

First i wrote a sketch that periodically woke up the XBee, send some data and put the XBee back to sleep. That shouldn’t be that hard.  How wrong could i be….

The job to do comes down to the following sequence:

  • wake up the XBee (use a Digital Output from the RBBB to set XBee pin 9 low);
  • wait for the XBee to be ready (CTS pin to go low);
  • send some dummy data;
  • wait a little more and put the XBee back to sleep (set XBee pin 9 back to high);
  • delay the loop for a number of seconds.

At first run all worked fine. However, after increasing the interval at which the job listed above were to be executed, i started losing packets. Because i enclosed a counter value into the sent data, i could see a very strange behavior: depending on the interval i saw packets coming only once every 2 or 3 times a packet was sent… What’s that?? By playing around with the interval i could determine that something strange was happening when the interval was set above 5 seconds. Why ? It took me some time to figure this out.

Sleeping XBee

Sleeping XBee

I  remembered the 5 seconds to be the default value for the “Time Before Sleep” (ST) Command. But this Command and the value set, are only applicable for Cyclic Sleep End Devices. And indeed, changing the Time Before Sleep didn’t make things better. OK, so now it was time to start reading the manual really well :-)

And there it was: the “Child Poll Timeout” must be what is bugging me. This is what the manual has to say about Child Poll Timeout:

“Router and coordinator devices maintain a timestamp for each end device child indicating when the end device sent its last poll request to check for buffered data packets. If an end device does not send a poll request to its parent for a certain period of time, the parent will assume the end device has moved out of range and will remove the end device from its child table. This allows routers and coordinators to be responsive to changing network conditions.”

So, if an End Device doesn’t let it’s parent (= Router, Coordinator) know that it’s still there from time to time, the End Device will be thrown out of the PAN, and has to start joining all over again; which takes a relatively long time, which it doesn’t really have being powered down all the time..

Increasing the value for the Child Poll Timeout on the Coordinator (to a higher value then the minimum of 5 seconds) resolved everything.

On to the next ‘easy’ job; using the ATMega328 Watchdog Timer to put the RBBB to sleep :-)

Tagged with: