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
    }
  }  
}
  • Are you assuming that your sensor gives a low output when it detects movement? Perhaps it's the other way around? – uint128_t Apr 25 '16 at 17:31
  • @uint128_t is right. Most PIR sensors go HIGH when they detect movement. – dinotom Apr 26 '16 at 5:53
  • attachInterrupt(0,wakeUpNow, HIGH); maybe? – Gerben Apr 26 '16 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. – Y.Terz Apr 26 '16 at 17:10
0

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.

New contributor
swmcdonnell is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.