Home > Zigbee > Project Zigbee PIR sensor part 1

Project Zigbee PIR sensor part 1

Intro

The Zigbee PIR sensor will be a Zigbee based motion detection sensor, working on batteries so you can put the sensor anywhere without having to deal with data or power cables.

Required:

  • simple (I don’t have an smd oven or PCB etching device)
  • cheap (obvious)
  • power efficient (batteries should last for 1.5-2 years)

Optional:

  • The sensor should “tell” when the batteries are almost dead.

Parts

The sensor consists of four main parts:

Schematic



Description

As soon as someone is detected by the PIR, the D-line (data) will become high (3.3v) for 1-2 seconds. If the detected object stays within the scope of the PIR, the D-line will remain high until the object leaves. The uC will detect that the D-line became active on PB3 and will:

  • activate led on PB4
  • waken up Xbee by making PB2 low
  • make PB1 high so that the Xbee will be alerted too that there was a pin change
  • make Xbee go to sleep by making PB2 high

When the D-line goes low (PIR does not detect anything anymore), the same in reverse happens:

  • deactivate led on PB4
  • waken up Xbee by making PB2 low
  • make PB1 low so that the Xbee will be alerted too that there was a pin change
  • make Xbee go to sleep by making PB2 high

To save power, the uC and Xbee will go to sleep as soon as a Zigbee transmission has been completed:

  • The uC will go in power down mode using only 100 uA.
  • Xbee will use SM=1 (pin hibernate) and use 90 uA.
  • The PIR will use only 60 uA if not detecting anything.

In total around 250uA will be used. Using 4x 2000 mAh batteries would mean 8000 [mAh]/0.25 [mA]=32000 hour=approx 3.5 years.

As more power will be used when the PIR is active and Zigbee transmissions are done, I expect that 2 years should be no problem.

I chose pin hibernate (SM=1) to make the Xbee go to sleep. The reason is that I only want to use the Xbee when the PIR detects movement so I can save power.

The disadvantage is that it can take days before any movement is detected and as a result of this the coordinator will time out the Xbee end device thinking it left the network as it got no response (it’s sleeping!). During a sleep the Xbee end device will not poll the coordinator.

This is what the Xbee manual says:

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.

The child poll timeout is settable on the coordinator with the SP and SN commands. SP and SN should be set such that SP * SN matches the longest expected sleep time of any end devices in the network. The actual timeout is calculated as (3 * SP * SN), with a minimum of 5 seconds. For networks consisting of pin sleep end devices, the SP and SN values on the coordinator and routers should be set such that SP * SN matches the longest expected sleep period of any pin sleep device. The 3 multiplier ensures the end device will not be removed unless 3 sleep cycles pass without receiving a poll request. The poll timeout is settable up to a couple of months.

So by using the correct SP and SN values you can prevent the end device timing out.

I could also have selected SM=4 (cyclic sleep) or SM=5 (cyclic sleep with pin awake). This has the advantage that the Xbee will periodically waken up to check for packets and therefor tell the coordinator that it is still alive. This will consume more power of course. SM=5 makes it possible to waken up the Xbee with pin 9 when it is still in a cyclic sleep, however, it will not make it go back to sleep when pin 9 is asserted (high) again (in contrary to SM=1). The Xbee will go back to sleep only when ST expires. It took me some time before I figured this out as it is not very clear in the manual.

The voltage regulator used (TS2950CT-3.3) is a low power regulator which can handle 150 mA which is enough for this setup. You should not forget to put a capacitor (0.22uF) between ground and output to prevent it from oscillating. I didn’t read the manual well enough when I started with this little device and for some reason the Xbee kept sending “Frame sent after power cycle event occurred” indication packets. You only see these events after a cold start of an Xbee, so I suspected a power problem. Reading the manual I found the statement of the need for this capacitor.  After I placed it the (multiple) power cycle events disappeared.


Battery monitor

A PIR that does not alert you when the battery is dead should be prevented at all times. That’s why I use a voltage divider (R3 & R4) to monitor the battery voltage. The divider has a ratio of 1:5.7 which means that the voltage at the AD converter (pin 20) of the Xbee is a factor 5.7 lower then the battery voltage. So if the battery voltage is 6V (max), pin 20 will read 6/5.7=1.02V. The AD converter of Xbee has a max of 1.2V so this is fine. Note that Vref is not used anymore on newer Xbee’s. Manual:

Vref: Not used on this module. For compatibility with other XBee modules, we recommend connecting this pin to a voltage reference if Analog sampling is desired. Otherwise, connect to GND.

So when will the battery be monitored? This is the responsibility of the Attiny13 that periodically wakes the Xbee to send an IO (AD) sample. How? The Attiny13 will use its watchdog timer to wake up and then toggle the sleep pin of the Xbee. As soon as the Xbee wakes up, it will send an IO sample if the IR command on the Xbee is set correctly and if at least one IO pin is set as AD. The IR command will set the sampling rate set in milliseconds. If IR=0 no sample will be sent, if it is set to 1000, a sample is sent every second.  To send just one sample, the trick is to set IR very high (say 10 secs). As soon as Xbee wakes up it will send a sample and starts an internal timer. When this timer expires the next sample will be sent (after 10 sec). If you make the Xbee go to sleep before the timer expires you will send only 1 sample.

The Attiny13 has 8 secs maximum for each watchdog cycle which is a bit short. To extend the cycle before a new IO event is sent, the Attiny13 will increases a counter and goes back to sleep until the next wake up call by either the watchdog or alarm event. If waken up by the watchdog event, the counter will be increased and then it will check if a maximum (450) has been reached. If this max has been reached an hour has passed (450 * 8 sec =3600 sec) and it’s time to send a battery status event (toggle sleep pin of Xbee). The counter will be reset and the cycle starts all over.

Note: it is also possible to let the Xbee (cyclic) sleep and send out IO-samples when it awakes. This means that pin hibernate (SM=1) cannot be used anymore and that SM=5 should be used.

On the coordinator a periodically IO (AD) sample looks like this:

[02/08 20:57:06] Received XBEE IO Data RX Indication packet
64-bits address sender 00:13:A2:00:40:0A:56:2E
16-bits address sender 43:EE
Options 41
Number of sample sets 01
Bitmask digital 00:10
Bitmask analog 81
Digital sample 00:00
Analog sample AD0 02:B6
Analog sample Vss 0A:C8

The alarm event starts with an analog IO sample when the Xbee wakes up:

[02/08 20:56:14] Received XBEE IO Data RX Indication packet
64-bits address sender 00:13:A2:00:40:0A:56:2E
16-bits address sender 43:EE
Options 41
Number of sample sets 01
Bitmask digital 00:10
Bitmask analog 81
Digital sample 00:00
Analog sample AD0 02:B6
Analog sample Vss 0A:C7

Then PB4 is set high to indicate an alarm. This triggers a digital IO event:

[02/08 20:56:15] Received XBEE IO Data RX Indication packet
64-bits address sender 00:13:A2:00:40:0A:56:2E
16-bits address sender 43:EE
Options 41
Number of sample sets 01
Bitmask digital 00:10
Bitmask analog 00
Digital sample 00:10

Some time later PB4 goes down which wakes up Xbee again.

02/08 20:56:16] Received XBEE IO Data RX Indication packet
64-bits address sender 00:13:A2:00:40:0A:56:2E
16-bits address sender 43:EE
Options 41
Number of sample sets 01
Bitmask digital 00:10
Bitmask analog 81
Digital sample 00:00
Analog sample AD0 02:BB
Analog sample Vss 0A:C7

Then the digital sample is sent to indicate the alarm is gone:

[02/08 20:56:17] Received XBEE IO Data RX Indication packet
64-bits address sender 00:13:A2:00:40:0A:56:2E
16-bits address sender 43:EE
Options 41
Number of sample sets 01
Bitmask digital 00:10
Bitmask analog 00
Digital sample 00:00

Note that PB4 is used as input in this example for the PIR instead of PB3.

Alternatives that might (not) work.

I looked at some other setups as well to use the PIR and Xbee. Such a setup was without the Attiny13 and voltage regulator. This looks like this:

Alternative setup

The PIR will activate the transistor when something is detected. The led will go on and the signal on DIO4 of the Xbee will drop to (almost) 0 V. R1 is needed as pull up although the internal pull up resistor of the Xbee can be used as well.  To send out periodically battery updates the Xbee can use cyclic sleep (SM=4). However, I discovered that there is one major problem with this setup. When using cyclic sleep without a wake up pin, the Xbee will not react to pin changes on DIO4 when it is sleeping! You can solve this by making the sleep interval very short (say 1 sec). Within this 1 sec interval, changes on DIO4 might be noticed as the PIR will keep the D-signal minimal 2 secs activated. The drawback is that as soon as the Xbee wakes up (every second)  a battery update is sent!

Not using a voltage regulator might work as the Xbee can have a supply voltage between 2.1 and 3.6V. Therefore it can be connected directly to two AA batteries. The PIR needs a minimal of 3.5 V so an extra AA battery is needed. Even an Attiny 13 can be used as it needs a minimal power supply of 1.8V.

Some final words…

I learned a lot by making a simple PIR sensor using an Xbee. The most important things learned:

  • SM=5: Pin 9 is really a wake up pin only. It will only go back to sleep when ST expires.
  • SM=1: Pin 9 will make Xbee go to sleep (high) or wake it up (low)
  • When Xbee sleeps, it will not respond to pin IO changes
  • IO samples will be send when Xbee wakes up and then after each IR time interval (as long as it is awake).
  • To send just one IO sample, make IR bigger then ST time.

Another thing worth mentioning is that I used a Xbee 2 ZB module using firmware 2x6x.

Ok, now it’s time to really build it. To be continued…

Advertisements
Categories: Zigbee
  1. leigh
    February 27, 2011 at 09:55

    This is a really nice idea. I wish I’d seen it a while ago.

  2. tom
    September 2, 2012 at 13:53

    Hi Rene,
    Thanks for sharing this. I’m a newbie. May I know if the attiny is running a program to behave like you described (i.e. activate LED, wake up XBee…)? I haven’t used attiny.

    Thanks again,
    Tom

  3. tom
    September 2, 2012 at 17:30

    Hi Rene,
    From my last comment I’ve searched further about attiny and now understand better. Would you be able to share your program on the attiny13? I would like to understand how you controlled the pins and how you made the attiny sleep. I’ve been playing with xbee and pir for a few weeks now but couldn’t get the xbee wake up with just the pir. Hence my strong interest in your post :-).

    Thanks in advance,
    Tom

    • September 2, 2012 at 20:24

      Hi Tom,

      Here it is:

      // Remark: all #includes are relative to: /usr/avr/include

      #include <avr/io.h>
      #include <avr/interrupt.h>
      #include <util/delay.h>
      #include <avr/sleep.h>

      static volatile uint8_t counter;
      static volatile uint8_t io_flag;

      ISR(WDT_vect){

      counter++;

      }

      ISR(PCINT0_vect){
      // One of pins just changed states
      // We do nothing as we just want to wake up…..
      // Note: when entering isr routine, global interrupts will be disabled.
      // when leaving isr routine, interrupts are enabeled again.
      io_flag=1;
      }

      void main(void) {

      //Stop all interrupts
      cli();

      // Define outputs (1) for: PB0 -> LED, PB1 -> DIO4 bee, PB2 -> Sleep Xbee, PB4 is test
      DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2)| (1 <<PB4);

      // Define input (0) PB3 for IR
      DDRB &= ~(1 <<PB3);

      //enable pull up for PB3
      PORTB |= (1<<PB3);

      // Set initial states:
      PORTB &= ~(1 << PB0) & ~(1 << PB1); //Led off and PB1 low
      PORTB |= (1<<PB2); //Xbee sleep (high)
      PORTB &= ~(1<<PB4); //led off on PB4

      //enable pull up for PB3
      PORTB |= (1<<PB3);

      // Set initial states:
      PORTB &= ~(1 << PB0) & ~(1 << PB1); //Led off and PB1 low
      PORTB |= (1<<PB2); //Xbee sleep (high)
      PORTB &= ~(1<<PB4); //led off on PB4

      //enable pull up for PB3
      PORTB |= (1<<PB3);

      // Set initial states:
      PORTB &= ~(1 << PB0) & ~(1 << PB1); //Led off and PB1 low
      PORTB |= (1<<PB2); //Xbee sleep (high)
      PORTB &= ~(1<<PB4); //led off on PB4

      //enable pull up for PB3
      PORTB |= (1<<PB3);

      // Set initial states:
      PORTB &= ~(1 << PB0) & ~(1 << PB1); //Led off and PB1 low
      PORTB |= (1<<PB2); //Xbee sleep (high)
      PORTB &= ~(1<<PB4); //led off on PB4

      //Reset Watchdog reset flag
      MCUSR &= ~(1<<WDRF);

      //Watchdog change enable and watchdog enable
      WDTCR |= (1<<WDCE) | (1<<WDE);

      //Enable watchdog Timer interrupt (WDTEI) and set new prescaler for 8 secs.
      WDTCR = (1<<WDTIE) | (1<<WDP3) | (1<<WDP0);

      //setup pin interrupt
      PCMSK |= 1<< PCINT3; //Pin Change Mask Register; enable PCINT3
      GIMSK |= 1<< PCIE; //Pin Change Interrupt Enable
      sei(); // Enable all interrupts

      // oneindige lus
      while(1)
      {

      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_mode(); //go to deep sleep now…

      //We must have been waken up by a pin change on PB3 (alarm) so read PB3.
      if (io_flag==1){
      if ( bit_is_set(PINB,PB3) ) {
      //Alarm triggered (PB3=high)
      PORTB |=(1<<PB0); //Activate led
      PORTB &= ~(1<<PB2); //Wake up Xbee by making SLEEP=0
      _delay_ms(15); //Wait for 15ms to wake up Xbee (not verified)
      PORTB |=(1<<PB1); //Make DIO4 Xbee high to send out IO sample
      _delay_ms(5); //Give Xbee some time to send IO sample.
      PORTB |= (1<<PB2); //Make Xbee go to sleep
      } else {
      //Alarm gone
      PORTB &= ~(1 << PB0); //Deactivate led
      PORTB &= ~(1 << PB2); //Wake up Xbee by making SLEEP=0
      _delay_ms(15); //Wait for 15ms to wake up Xbee (not verified)
      PORTB &= ~(1 << PB1); //Make DIO4 Xbee low to send out IO sample
      _delay_ms(5); //Give some time for Xbee to send IO sample
      PORTB |= (1 << PB2); //Make Xbee go to sleep
      }
      io_flag=0;
      } else {

      //Every minute (64 secs)
      if (counter==7){
      counter=0;
      PORTB ^= (1<<PB4);

      //Wake up Xbee
      //As soon as Xbee wakes up, an IO sample will be sent as IR=10 (sec).
      //But as Xbee will be waken up just <1 sec only one sample will be sent.
      PORTB &= ~(1<<PB2); //Wake up Xbee by making SLEEP=0
      _delay_ms(30); //Wait for ?ms to wake up Xbee (not verified); is it 13.2ms?
      PORTB |= (1<<PB2); //Make Xbee go to sleep
      }
      }

      } //while

      return 0;

      }

      • Tom
        September 5, 2012 at 10:16

        Hi Rene,

        Thanks a lot for your quick reply. I’ll study your code and tinker on my new attiny13A. Exciting!

        Thanks again.
        Tom

  4. Nico
    February 23, 2015 at 07:36

    Hi rene,
    This is a very nice project i ‘m also going to do.
    I also struggled with sm=5 and your solution with external micro seems the best keeping sm=1 on the xbee.
    However did you reallly test the battery life? Does it work for 2years ?
    Please let me know in order to keeping going on this way .

    • February 23, 2015 at 09:00

      Hi Nico,

      The battery did not last longer than 4 months unfortunately. I do not know how many mAh the battery is I was using so it is hard to compare. I think if you use two AA batteries it will go for more than a year.

      Rene

  5. nico
    February 23, 2015 at 16:57

    ok I’m going to test your circuit and i’ll keep you updated!
    The little problem with this configuration is that even if the mcu and xbee are slepping, the PIR and the DC/DC work all the time . 1 year is good, hope to rach this target !
    bye

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: