Remote sensor programming

Now that i’m very confident that my interrupt-driven motion sensor is finished, i was wondering what else there is to add; the first thing that comes to my mind is remotely adjusting the way the sketch works; no i don’t mean uploading a whole new sketch, but adjusting some parameters. For example, it should be relatively easy to adjust the heartbeat interval, or the motion report interval. Or disable sending the additional information in the packet that is being sent (packet size reduction = power reduction!); or disable motion reporting completely, e.g. disabling the sensor temporarily! What else can i think of?Β  πŸ™‚ It does sound like something that’s nice to have…

The question is, do i really need it? Or shall i proceed with a door/window sensor? Or go on building these motion sensors until i have replaced all the MS13 sensors i removed from my house some time ago and the few that are still being used? Or first finish the LED strips… tough choices!

Motion sensor v2 built and in use

Two motion sensors v2 are in use right now, yippee!

I upgraded an existing v1 sensor to a v2 and built a new one. The v2 sensor specs are very different from the v1 but much more promising, yet all i needed to do to was soldering the digital output of the PIR to another JeeNode port (namely ATmega INT1) and use a different digital port for serial I/O with the XBee. Oh, and upload a new sketch of course. Now i have 2 identical v2 sensors:

v1 upgraded to v2

Looking back at how this motion sensor evolved i am wondering, why didn’t i think of interrupts in the first place… not very smart actually..

Or maybe i did think about interrupts but unconsciously thought it would be to hard for me to handle already, cause that’s what you read all the time: interrupts are a tough subject! Maybe it is, but i didn’t notice that yet! πŸ™‚

So now I’ve got 2 motion sensors with the following features:

  • powered by 3 * 1.2V, 2000 mAh rechargeable batteries;
  • PIR with digital output, 100Β΅A standby power usage and 5m detection range;
  • a JeeNode that’s effectively running only a total of about 180 seconds per day (0.2 %), even with 350-400 motion reports and lots of heartbeats. The rest of the time the JeeNode is in power down mode;
  • it’s ZigBee based which is better than 433 MHz in my opinion, especially when you’ve got a lot of sensors;
  • relatively small sensor housing compared to commercial (mostly big and ugly) products;
  • completely DIY so everything is how i want it to be;
  • interrupt-based, the best you can get I’d say;
  • need i go on?Β  πŸ™‚

I’m gonna monitor this sensor very closely in the coming months and learn from it. Here you see one of the sensors being used in the kitchen:

Motion v2 in the kitchen

Finished? Almost; some loose ends in the sketch. Maybe it can be made even smaller/faster/less energy consuming. But I’ll look into that when the 3rd sensor is built.

Update 2010-09-16:

The sketch that’s currently running on these sensors can be found here; the Sleep library i currently use can be found here .

Motion Sensor v2

Here it is, Motion Sensor v2. Not much different from v1 really, the only thing that has changed is that the PIR output has moved to an interrupt pin. And the sketch looks somewhat different here and there. Later this week i’ll build my 2nd motion sensor and start using it right away; i’m very curious about the results! I’ll also change my 1st motion sensor that’s already in use, to an interrupt driven model. Don’t want to wait for what will happen with those batteries…

The JeeNode is completely powered down most of the time. It only gets woken up by the Watchdog timer every 8 seconds or when motion is detected. But even when motion is detected, it’s powered down most of the time, cause a ‘blip’ sent to my Domotica System every 4 seconds during continuous motion is more than enough.

When the motion interrupt is triggered, the ‘blip’ is sent to my system, followed by a power down for 4 seconds without interrupt trigger set. When those 4 seconds have passed (wake up is done by the watchdog timer) a power down is done with interrupt trigger and the whole loop starts all over again. Capice? It doesn’t get much easier than this πŸ™‚

And of course there’s a heartbeat sent every 64 (8 times 8 ) seconds.

Adding Sense Control

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 πŸ™‚

Really powering down this time

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!

One problem less

Sudden memory increase

A sudden memory increase yesterday morning made me aware that there was something wrong in my system. Memory usage was increasing fast, while the memory count wasn’t. So probably no memory leak, but a static buffer that kept on growing bigger and bigger. Reviewing the logs indicated the ZigBee Coordinator was constantly receiving packets with bad checksums:

09:50:32 ZigBee: Rcvd Frame:97 01 00 13 A2 00 40 33 1F 7B 31 D7 44 42 00 7E
09:50:32 ZigBee: Invalid Checksum !! (Rcvd=00,Calc=66)
09:50:32 ZigBee: Rcvd Frame:97 01 00 13 A2 00 40 33 1F 7B 31 D7 44 42 00 7E
09:50:32 ZigBee: Invalid Checksum !! (Rcvd=00,Calc=66)
09:50:35 ZigBee: Rcvd Frame:97 01 00 13 A2 00 40 33 1F 7B 31 D7 44 42 00 7E
09:50:35 ZigBee: Invalid Checksum !! (Rcvd=00,Calc=66)

Strange; it looks like always the same packet is being received. That can’t be right! I removed the batteries from the XBee that seemed to be constantly sending these bad packets, but they kept on coming in; yeah right, without batteries πŸ™‚

So there must be a problem with the read buffer in the ZigBee API. Looking at the code, i saw it right away… i forgot to skip a byte, resulting in always the same bad packet being spotted in the buffer! And that buffer kept on growing and growing. The fix was easy:

New batteries !?!

Not long after i noticed the rapid supply voltage drop on my motion sensor, this sensor stopped working. July 23th at 02:02 AM to be precise, cause that’s when the last motion detection was sent and no more heartbeats were received anymore after that. That same day, in the evening, i replaced the batteries:

New batteries installed

A few things i noticed are:

  • The new batteries for the motion sensor start at 3188 mV, which is significantly lower than the voltage on the other sensors;
  • The motion sensor stopped working sooner than i expected based on earlier findings;
  • The sensor behaved like i wished it would, during the time the batteries couldn’t cope anymore (no MS13 nightmares);
  • Replacing the batteries was enough to get it all working again (Yeeha!).

In the meantime, the batteries on my Lux Sensor are still within the same 5 mV range since i started logging:

Constant Supply Voltage on XBR4 (Lux sensor)

So that sensor is still doing OK i guess πŸ™‚

This time the motion sensor got 3 brand new and fully charged batteries. We’ll see what will happen this time.

I think i’ll start reading some more about handling external interrupts on the ATMega328… just in case, maybe i will need it.

But first, lets see how these new batteries keep the sensor working and if I’m not satisfied with the results, i will start using the energy saving version of the PIR, or lower the clock the ATMega328 is running on, or increase the sleep period on the JeeNode, use more powerful batteries, optimize the sketch, or …

Dropping fast…

XBee Supply Voltage dropping fast!

Oops… the Supply Voltage on my motion sensor is already down to 3060 millivolts. Suddenly it’s dropping very fast; this sensor has been operational for more then 7 weeks now, with IIRC 2 new and 1 older rechargeable battery of a brand with which i’ve had bad experiences before. I hope that’s what is causing this, cause if not, i have some work to do πŸ™

The other 2 battery powered sensors are still doing fine, BTW:

Supply Voltages (click to view the realtime values)

Monitoring Me.

Monitoring me

Yes, i’m a person who likes to monitor things… as much as he can!

The 2 charts above show the memory usage of the Domotica system i created during the past 5 years. I like to think that this system, that is running it’s 135th version since august 2008, is able to keep on running for months, even years. But will it? Actually, i can’t tell. Do i catch all errors that can occur in a correct way? Do i anticipate on abnormal situations correctly? Does my system continue working if a subsystem fails? Those are all questions that are hard to answer. I mean, I think I’m doing OK cause I have had only 1 occasion of a total system breakdown in those 5 years, but… that very special situation i didn’t think of, can happen. And that situation will happen, some day. Does the name Murphy ring a bell? Hopefully this will not happen while I’m on vacation, where there are less-than-normal resources to fix the problem right away.

With more and more tasks being performed by my Domotica System and not being able to figure out anymore what special situations will be able to crash it, I’m residing to the more obvious ones, like monitoring thingsΒ  like memory usage, odd data being received and how it’s being handled, things like that. The 2 charts shown above represent how many kilobytes are being used and how many memory allocations are made in my system. I know, this only gives me some insight in how well i wrote my own code, but it also tells me how well it will perform over a period three times as long as the average ‘up time’ of my system (5 days) without any special situations. And, it also tells me how well it performs on anticipated problems, where error handling has to take control and make sure everything keeps working as expected. But no matter how well it anticipates a problem, anticipated or not: if my system runs out of memory it’s done… the system will stop unexpected and no ‘catch’ will resolve that issue. And that’s what I’m doing these days, amongst other things: monitoring my own Home Automation system; my own creation, me

That’s the best i can do without trying to think of (and test) all scenarios my system will face while I’m away. That’s just not doable anymore, with so many different interfaces.

BTW, despite all the negative thinking above: it’s looking good; and just like the last 4 years, it will perform just fine πŸ™‚

ZigBee Coordinator relocated

This is how my ZigBee Coordinator has been on my desk since the beginning:

ZigBee Coordinator

Not a good idea to keep it this way forever. So it was time to give it a nice enclosure and move it to the meter cabinet. I found an enclosure in which there’s plenty of room for the XBee Explorer board. Some sawing, drilling and adjusting resulted in the following.

Zigbee CoordinatorCoordinator

That looks much better! It doesn’t bring any new functionality, but it does make things look more “complete”…one of those things i often forget, because the next thing is already waiting to get started… πŸ™‚