1

I want to use to use an IR sensor as an interrupt to wake up my Arduino Uno R3 from the deep sleep power mode and then go back to sleep after changing the state of the relay.

Lets say if I press a button on the remote and the relay is on LOW mode, the relay is turned to HIGH mode and vice versa.

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <IRremote.h>
/* Sleep Demo
------------
int relayPin = 8; // LED connected to digital pin 13
int irPin = 2; // active LOW, ground this pin momentary to wake up
int sleepStatus = 0; // variable to store a request for sleep
volatile byte state = LOW;
IRrecv irrecv(irPin);
decode_results results;
void setup()
{
 pinMode(relayPin, OUTPUT); // sets the digital pin as output
 pinMode(irPin, INPUT);
 irrecv.enableIRIn(); // Start the receiver
 /* Now is time to enable a interrupt. In the function call
 attachInterrupt(A, B, C)
 A can be either 0 or 1 for interrupts on pin 2 or 3.
 B Name of a function you want to execute while in interrupt A.
 C Trigger mode of the interrupt pin. can be:
 LOW a low level trigger
 CHANGE a change in level trigger
 RISING a rising edge of a level trigger
 FALLING a falling edge of a level trigger
 In all but the IDLE sleep modes only LOW can be used.
 */
 attachInterrupt(0, wakeUpNow, CHANGE); // use interrupt 0 (pin 2) and run function
 // wakeUpNow when pin 2 gets LOW
}
void sleepNow() // here we put the arduino to sleep
{
 /* Now is the time to set the sleep mode. In the Atmega8 datasheet
 http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
 there is a list of sleep modes which explains which clocks and
 wake up sources are available in which sleep modus.
 In the avr/sleep.h file, the call names of these sleep modus are to be found:
 The 5 different modes are:
 SLEEP_MODE_IDLE -the least power savings
 SLEEP_MODE_ADC
 SLEEP_MODE_PWR_SAVE
 SLEEP_MODE_STANDBY
 SLEEP_MODE_PWR_DOWN -the most power savings
 For now, we want as much power savings as possible,
 so we choose the according sleep modus: SLEEP_MODE_PWR_DOWN
 */
 set_sleep_mode(SLEEP_MODE_IDLE); // sleep mode is set here
 sleep_enable(); // enables the sleep bit in the mcucr register
 // so sleep is possible. just a safety pin
 /* Now is time to enable a interrupt. we do it here so an
 accidentally pushed interrupt button doesn't interrupt
 our running program. if you want to be able to run
 interrupt code besides the sleep function, place it in
 setup() for example.
 In the function call attachInterrupt(A, B, C)
 A can be either 0 or 1 for interrupts on pin 2 or 3.
 B Name of a function you want to execute at interrupt for A.
 C Trigger mode of the interrupt pin. can be:
 LOW a low level triggers
 CHANGE a change in level triggers
 RISING a rising edge of a level triggers
 FALLING a falling edge of a level triggers
 In all but the IDLE sleep modes only LOW can be used.
 */
 attachInterrupt(0, wakeUpNow, CHANGE); // use interrupt 0 (pin 2) and run function
 // wakeUpNow when pin 2 gets LOW
 sleep_mode(); // here the device is actually put to sleep!!
 //
 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.
 delay(1000); // wat 2 sec. so humans can notice the
 // interrupt.
 // LED to show the interrupt is handled
}
void wakeUpNow() // here the interrupt is handled after wakeup
{
 //execute code here after wake-up before returning to the loop() function
 // timers and code using timers (serial.print and more...) will not work here.
 if (irrecv.decode(&results)) {
 if (results.value == 0xff629d) {
 state = !state;
 digitalWrite(relayPin, state);
 }
 }
}
void loop()
{
 sleepNow(); // sleep function called here
}

The Arduino never seems to wake up from sleep when I use the CHANGE interrupt. But if I use with the IDLE sleep mode, it is working.

Can somebody please help me how to fix this ? Also will this code work with an Arduino Pro Mini or an ATTiny45?

asked Mar 23, 2018 at 4:07

2 Answers 2

3

You actually don't need to to worry about interrupts at all for this project. The IRremote library is itself based on a timer interrupt. As soon as you irrecv.enableIRIn(), you start receiving a continuous stream of interrupts... in addition to the timer interrupt initially set up by the Arduino core.

If you want to save some power, you can call sleep_mode() once in your loop. That's it. No need to sleep_enable() or sleep_disable(), as these are already taken care of by sleep_mode(). No need to set_sleep_mode() either, as the default sleep mode (IDLE) is the only one that is appropriate for you. No need to attachInterrupt(), as you will be waken up by these timer interrupts anyway.

Removing all the cruft, your posted code would become:

#include <avr/sleep.h>
#include <IRremote.h>
const int relayPin = 8;
const int irPin = 2;
IRrecv irrecv(irPin);
void setup()
{
 pinMode(relayPin, OUTPUT);
 pinMode(irPin, INPUT);
 irrecv.enableIRIn();
}
void loop()
{
 decode_results results;
 if (irrecv.decode(&results)) {
 if (results.value == 0xff629d) {
 static byte state = LOW;
 state = !state;
 digitalWrite(relayPin, state);
 }
 irrecv.resume();
 }
 // Sleep until next interrupt.
 sleep_mode();
}
answered Mar 23, 2018 at 10:50
0
0

The Arduino never seems to wake up from sleep when I use the CHANGE interrupt.

 attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function

That's not a CHANGE interrupt, it's a LOW interrupt. Please post code that supports what you say in the question.


void wakeUpNow() // here the interrupt is handled after wakeup
{
 //execute code here after wake-up before returning to the loop() function
 // timers and code using timers (serial.print and more...) will not work here.
 if (irrecv.decode(&results)) {
 if (results.value == 0xff629d) {
 Serial.println("UP");
 state = !state;
 digitalWrite(relayPin, state);
 }
 }
}

Don't do serial prints inside an ISR. In particular, a LOW interrupt keeps being called continuously while the interrupt pin is low.

// timers and code using timers (serial.print and more...) will not work here

You even have a comment saying that the code won't work, yet you posted it in your question.

answered Mar 23, 2018 at 5:02
1
  • I changed the code accordingly Commented Mar 23, 2018 at 9:46

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.