# TL;DR

A PIR sensor is triggered by itself when using a timer to wait 2 seconds after the sensor is triggered. Without using the timer to wait the sensor works as expected.

# Background and setup

I have a PIR sensor connected to an ATMega328p. The PIR sensor has three pins; VCC, GND and AL. The AL pin uses open collector to show that motion is detected.

What I have done is that I connected the AL pin to PC0 pin on my ATMega and set up the pin as input with internal pull up resistor and a LED connected to PC5 to show when motion is detected:

void setup_default_values()
{
DDRC |= (1 << PC5);
DDRC &= ~(1 << PC0);

PORTC |= (1 << PC0);
}


Then I have a function that checks when the PC0 pin is LOW:

void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);
}
}


This function lights up the LED when PC0 is LOW and turns it off when PC0 is HIGH. This function is run every cycle of my main loop:

int main()
{
setup_default_values();

for (;;) {
check_sensor();
}

return 0;
}


# Problem encountered

Everything works as expected, the LED lights up when I wave my hand infront of the sensor and it does not trigger without motion. The sensor sets the AL pin LOW for about 100 - 200 ms.

The thing is that I don't want to use the signal for 2 seconds after motion has been detected. So I implemented a timer and flag logic that ignores the signal during these 2 seconds. The problem is that now the LED lights up by itself after the timer has stop counting and start accepting motion signals

# Problematic setup

To use this timer and flag logic I added 2 LEDs, one that shows that the timer is active and one that shows when a signal is registered:

volatile bool motion_detected;

void setup_default_values()
{
DDRC |= (1 << PC5);
DDRC |= (1 << PC4);
DDRC |= (1 << PC3);
DDRC &= ~(1 << PC0);

PORTC |= (1 << PC0);

TCCR1B |= (1 << CS12); // Timer 1B set up to use a prescaler of 256
TCNT1 = 0; // Timer value set to 0

motion_detected = false;
}


Then I new logic to the check_sensor function:

void check_sensor()
{
if (PINC & (1 << PC0)) {
PORTC &= ~(1 << PC5);
}else{
PORTC |= (1 << PC5);

if (!motion_detected) {
PORTC |= (1 << PC3);
_delay_ms(50);
PORTC &= ~(1 << PC3);

PORTC |= (1 << PC4);
TCNT1 = 0;
motion_detected = true;
}
}
}


When motion is detected the first time, this is what happens:

• LED indicating signal from PIR is lit up
• LED indicating signal acceptance it blinked once
• LED indicating timer is active is lit up
• Timer is reset and flag indicating motion was detected

Then there is a new function which handles the countdown:

#define F_CPU 1000000UL

/*
* Timer increments per second
*
* This value represents how many increments the timer will do to the TCNT1 register
* per second.
*
* To produce this value you divide the clock frequency in hz with the prescaler amount.
* For example:
* 1000000 / 256 = 3906
*/

#define TMR_INC_PER_SEC 3906

void check_timer()
{
if (!motion_detected) return;

if (TCNT1 >= TMR_INC_PER_SEC * 3) {
PORTC &= ~(1 << PC4);
motion_detected = false;
}
}

int main()
{
setup_default_values();

for (;;) {
check_timer();
check_sensor();
}

return 0;
}


This function should be ignored unless there is a motion detected. When countdown has been completed timer indicating LED is turned off and motion flag is reset which indicates that a new signal can be accepted.

# Things I have tried

## Software debounce

I have tried adding software debounce functionality where motion is only accepted if PC0 is LOW for a defined amount of cycles. This did not change the faulty behavior.

## Push button instead of PIR

I have tried removing the PIR and add a push button which is LOW on push down. When using the push button the circuit and logic works as expected.

# Schematics

Here is the schematics for the power supply. The circuit is connected to a Stabilized DC power supply where the +5V rail is actually around +6.5V (I don't know how to edit the text of a component in gschem). VCC is what I connect to my microcontroller and PIR-sensor, as you will see in the second schematic.

Here is the schematics for the microcontroller, the LEDs and the PIR-sensor. Some pins are not shown in the schematics: RESET pin is connected to my programmer, same with MOSI, MISO and SCK.

• Is the PIR power decoupled from the rest? Perhaps a small fluctuation in voltage is being seen as motion. – Bobbi Bennett May 23 '13 at 17:52
• @BobbiBennett See the schematics in the edit! I'm only using decoupling caps in the power supply. The microcontroller and the PIR-sensor uses the same VCC from the power supply. I noticed something, the datasheet for the PIR-sensor says operating voltage 12V, but the shop page says 5V - 12V, that's why I'm using 5V for the PIR-sensor. Could it be a problem with both, decoupling needed and higher voltage? – rzetterberg May 24 '13 at 7:54