Sunday, March 15, 2015

PIR sensors: exploiting passivity




We have already spoken about the PIR sensor in these pages (see here) and many other pointers can be found on the web. However, the example sketches does never consider the main aspect of this sensor: passivity! The sketches always employ busy waiting (ie they continuously loop on the test for changes over the alarm pin).

The PIR sensor used in the sketch.


The idea

Use interrupts! The idea is that the alarm function is activated by the state change of the signal pin of the sensor. In this way the CPU can perform other tasks when the alarm is not activated.

Remark

When the alarm is triggered on the PIR sensor it remains in this state for a certain amount of time. Since we chose to implement the CHANGE option for the interrupt routine we have to prevent that the service routine is run twice instead of once. This is implemented using a simple flag.

The sketch

Since the sketch has only prototyping purposes, the only effect of the alarm trigger is to print a message to the serial monitor. To see the message open the serial monitor, choose the right port and communication speed.

/**
 * PIRpassExploit
 *
 * A convenient way to use PIR sensors
 *
 * \author Enrico Formenti
 * \version 1.0
 * \date 15 March 2015
 * \copyright BSD license, check the License page on the blog for
 * more information. All this text must be included in any 
 * redistribution.
 * <br><br>
 * See macduino.blogspot.com for more details.
 *
 * Remarks:
 * - OUT pin is connected to digital pin 2 of Arduino, change this
 *   if needed
 * - DELAY times depend on the type of module and/or its 
 *   configuration.
 */

// OUT pin on PIR sensor connected to digital pin 2
// (any other digital pin will do, just change the value below)
#define PIRSensorPin 2

// This is the amount that the sensor takes to setup internals
// Check your sensor datasheet for the correct value
// Mine is about 17 seconds
#define PIR_INIT_DELAY 17000

// This is used to avoid triggering alarm twice when signal returns
// to normal state
volatile bool alarmUnarmed;

void doAlarm() {
  if(alarmUnarmed) {
    alarmUnarmed = false;    
    Serial.println("Alarm triggered!");
  }
  else
    alarmUnarmed = true;
}

void setup() {
  Serial.begin(9600);
  
  pinMode(PIRSensorPin, INPUT);
  delay(PIR_INIT_DELAY);
  
  alarmUnarmed = true;
  attachInterrupt(0, doAlarm, CHANGE);
}

void loop() {

  // do some good work here ;-)
}

See also


Enjoy!