2

So I was starting to gain some knowledge on the PIR sensor and how to let the Arduino 'sleep' while there is no movement detected by the PIR.

I found the following code somewhere and looked fairly simple. So I thought I would give it a try and grabbed my Mega2560, a LED and a PIR sensor.

While it was seeming to work at first sight, the Arduino is doing the opposite from what I was expecting. It turns off the LED and the Arduino when there is movement, instead of turning off the Arduino when there is NO movement. As I said before, it is doing pretty much the inverse.

Probably an easy solution, but can't figure it out on my own.

The code:

#include <avr/sleep.h> 
int wakePin = 2; // pin used for waking up 
int led = 13; 
void wakeUpNow() { 
} 
void setup() { 
 pinMode(wakePin, INPUT_PULLUP); 
 pinMode(led, OUTPUT); 
 attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function wakeUpNow when pin 2 gets LOW 
} 
void sleepNow() { 
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here 
 sleep_enable(); // enables the sleep bit in the mcucr register 
 attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function 
 digitalWrite(led,LOW);
 sleep_mode(); // here the device is actually put to sleep!! 
 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP 
 sleep_disable(); // first thing after waking from sleep: disable sleep... 
 detachInterrupt(0); // disables interrupt 0 on pin 2 so the wakeUpNow code will not be executed during normal running time. 
 digitalWrite(led,HIGH);
} 
void loop() { 
 sleepNow(); // sleep function called here 
}

Thanks in advance.

EDIT

Adapted the code to the following and seems to work now. When motion is detected by the PIR it turns on the LED on pin 13; when no motion is detected, the LED is turned off.

Two questions still remain:

1) How can I be sure that the Arduino really sleeps now?

2) When the Arduino just entered sleep, it takes a couple of seconds (+/- 6s) before it can pick up another motion. Can I get a faster detection or another 'sleep' or 'powersave' method that lets the Arduino react faster to motion?

#include <avr/sleep.h> 
const int wakePin = 2; // pin used for waking up 
const int led = 13; 
int wakeVal = 0;
int wakeState = LOW;
void wakeUpNow() {
} 
void setup() { 
 Serial.begin(9600);
 pinMode(wakePin, INPUT_PULLUP); 
 pinMode(led, OUTPUT); 
 //attachInterrupt(0, sleepNow, LOW); // use interrupt 0 (pin 2) and run function wakeUpNow when pin 2 gets LOW 
} 
void sleepNow() { 
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here 
 sleep_enable(); // enables the sleep bit in the mcucr register 
 attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function 
 sleep_mode(); // here the device is actually put to sleep!! 
} 
void disSleep(){
 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP 
 sleep_disable(); // first thing after waking from sleep: disable sleep... 
 detachInterrupt(0); // disables interrupt 0 on pin 2 so the wakeUpNow code will not be executed during normal running time. 
}
void loop() {
 wakeVal = digitalRead(wakePin);
 if (wakeVal == HIGH){
 disSleep();
 digitalWrite(led,HIGH);
 delay(1000);
 if (wakeState == LOW){
 Serial.println("Motion detected");
 wakeState = HIGH;
 }
 }
 else{
 digitalWrite(led,LOW);
 delay(1000);
 if (wakeState == HIGH){
 Serial.println("Motion stopped - Going to Sleep Mode !");
 wakeState = LOW;
 delay(1000);
 sleepNow(); // sleep function called here
 }
 } 
}
VE7JRO
2,51519 gold badges27 silver badges29 bronze badges
asked Apr 25, 2016 at 16:56
4
  • Are you assuming that your sensor gives a low output when it detects movement? Perhaps it's the other way around? Commented Apr 25, 2016 at 17:31
  • @uint128_t is right. Most PIR sensors go HIGH when they detect movement. Commented Apr 26, 2016 at 5:53
  • attachInterrupt(0,wakeUpNow, HIGH); maybe? Commented Apr 26, 2016 at 12:39
  • 1
    Yes I know movement = high & no movement should be low. I tried attachInterrupt(0,wakeUpNow,HIGH) already. Doesn't seem to resolve it. Commented Apr 26, 2016 at 17:10

1 Answer 1

2

This is a problem with the Arduino Mega board. On the Mega, D2 is not INT0 as it is on the Uno. It's INT4. There's a footnote in the spec sheet that says only level interrupt is supported. That means you can't use RISING, FALLING or CHANGE. Your only choice is to use LOW. So the Arduino will be woken up when the motion turns OFF, not on. That's why it's backward. If you use an Uno instead of a Mega, you can use RISING and it will work as you think it should.

answered Oct 12, 2019 at 6:23

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.