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
}
}
}
1 Answer 1
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.
Explore related questions
See similar questions with these tags.
attachInterrupt(0,wakeUpNow, HIGH);
maybe?