This post outlines how to run a PIR sensor with 2xAA batteries and use interrupts to sleep a 3V3 8 MHz Arduino between both tripped and not-tripped states. This seems pretty straight forward, however there are a couple subtleties.
- The stock PIR is outfitted with a voltage regulator that requires ~4V5.
- Voltage ripple from the voltage booster (2xAA boost to 3V3) can cause certain sensitive sensors to reset and oscillate. Especially when entering sleep (SLEEP_MODE_PWR_DOWN), because of the large change in operating current. The reduction of the operating current, when entering sleep, will cause the booster to change frequency and magnitude of the output voltage ripple.
Here, I will describe how I overcame this problem by modifying the PIR to work at 3V0.
Steps:
PIR PCB modification
- Remove the voltage regulator and diode from the PIR PCB
- Solder a wire (red wire in the photo) from the VCC pin to the former location of the output pin of the voltage regulator
The board should look like the photo shown below
Prepare the power source for the PIR
- The voltage from the 2xAA batteries (in my case) are boosted by a XC9140 low quiescent current 3V3 voltage regulator to power the Arduino pro mini. The radio is powered directly from the 2xAA batteries as it has its own regulator and can operate down to 1V9.
- The PIR sensor is based on the BISS0001 which as a supply voltage range of ~3-5 V. The modification done in earlier makes the module very sensitive to voltage ripple. In fact, the voltage ripple that occurs when switching from an awake to sleeping Arduino is enough, I believe, to cause the BISS0001 to reset and either oscillate or freeze.
- I investigated a couple of solutions, but the best is to use a low-drop-out-voltage high-ripple-rejection-ratio regulator (FT531IA, 3V0, 36 µA supply current) to reduce the 3V3 boosted high-ripple supply to a steady 3V0. I know this seems silly to boost and then regulate down to another voltage but the data speaks for itself, below.
Figure 1. Comparison of the output of the 3V3 booster and the LDO 3V0 regulator while the Arduino is sleeping. AC coupled scope termination. Note: the LDO is multiplied by 100 and offset for clarity.
Figure 2. Motion at around 1100 ms causes the PIR output to go high and the Arduino to wake up. Note the output from the booster quiets down and the output from the LDO is smooth. PIR and LDO outputs are offset for clarity.
Figure 3. Entering sleep once the PIR goes from tripped to non-tripped state. Once the Arduino starts to sleep, the output from the booster becomes noisy, while the LDO is smooth. PIR and LDO outputs are offset for clarity.
Here is my example code (nothing fancy and much of it is borrowed from various places).
//This program will test the PIR using interrupts
#include <avr/sleep.h>
#include <avr/interrupt.h>
void setup()
{
Serial.begin(115200);
pinMode(3,INPUT);
digitalWrite(3, LOW);
pinMode(4,OUTPUT);
//Signal PIR startup by flashing an LED
digitalWrite(4,HIGH);
delay(5000);
digitalWrite(4,LOW);
delay(200);
}
void loop()
{
//Come out of sleep and read state of PIR pin
bool flag = digitalRead(3);
if (flag == true)
{
Serial.println("tripped");
digitalWrite(4,HIGH);
}
else
{
Serial.println("not tripped");
digitalWrite(4,LOW);
}
delay(100);
sleepNow();
}
void sleepNow()
{
Serial.println("Entering Sleep");
// Set pin 3 as interrupt and attach handler:
attachInterrupt(1, wakeUp, CHANGE);
delay(100);
// Choose our preferred sleep mode:
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Set sleep enable (SE) bit:
sleep_enable();
// Put the device to sleep:
sleep_mode();
// Upon waking up, sketch continues from this point.
sleep_disable();
}
void wakeUp(void)
{
detachInterrupt(1);
}
One last thing, it is necessary to attach a pull-down resistor on the PIR output pin in order to help the signal line go low when transitioning to the non-tripped state.