Arduino wakes up from sleep without obvious reason

Hi tio all,

I’m experimenting with the “sleep” state of Arduino,as I intend to develop a very low-power application.

So to test the “sleep”, I loaded the following sketch from “https://www.gammon.com.au/forum/?id=11497”, Sketch J to my UNO:

#include <avr/sleep.h>

  
void wake ()
{
  // cancel sleep as a precaution
  sleep_disable();
  // precautionary while we do other stuff
  detachInterrupt (0);
}  // end of wake

void setup () 
  {
  Serial.begin(9600);
  Serial.println("Setup...");
  digitalWrite (2, HIGH);  // enable pull-up
  }  // end of setup

void loop () 
{
 
 Serial.println("Starting....");
 Serial.flush();
  // disable ADC
  ADCSRA = 0;  
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();

  // Do not interrupt before we go to sleep, or the
  // ISR will detach interrupts and we won't wake.
  noInterrupts ();
  
  // will be called when pin D2 goes low  
  attachInterrupt (0, wake, LOW);
  EIFR = bit (INTF0);  // clear flag for interrupt 0
 
  // turn off brown-out enable in software
  // BODS must be set to one and BODSE must be set to zero within four clock cycles
  MCUCR = bit (BODS) | bit (BODSE);
  // The BODS bit is automatically cleared after three clock cycles
  MCUCR = bit (BODS); 
  
  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
  interrupts ();  // one cycle
  sleep_cpu ();   // one cycle

  Serial.println("Awake...");
  Serial.flush();
  delay(2000);

  } // end of loop

(I just eliminated the LED-part added some output for debugging and triggered the ISR in case of “LOW” instead of “FALLING”)
Pin D2 is always high, it is open all the time, so I expect no Wake-up will occur.

But when I had run the UNO (connected to the USB-Port of my PC and the PC also running all the time),
The UNO woke up at irregular times and was NOT reset (i.e. STEUP was not invoked,only once at the beginning):

Setup...
Starting....
Awake...
Starting....
Awake...
Starting....
Awake...
Starting....
Awake...
Starting....
Awake...
Starting....
Awake...
Starting....

D2 was never touched, and as the pull-up is applied, there should be no reason for a “LOW”-state.
Does anybody have an explanation for this behavior? Do I overlook something?
I cannot check the intervals between the awakening, as the internal clock of UNO is also stopped when he sleeps,maybe there is a time which elapses?

have a nice day

piqueremy

Oh,

I forgot to mention that the above output was generated during approx. 24 hrs.

P.

Well... it's not saying "Setup..." so it's not a reset.

One thing to try is to set a global flag in wake() and report if that flag is set when the processor wakes up. That would at least tell you if it was the the external interrupt is being triggered accidentally (electrical noise?). If not, some other interrupt is not being disabled and is getting triggered.

  digitalWrite (2, HIGH);  // enable pull-up

You didn't set pinMode(2,INPUT) before this digitalWrite, so pin 2 probably hasn't been initialized properly. If it is floating it can cause random interrupts.

Delete the digitalWrite statement and replace it with this:

  pinMode(2,INPUT_PULLUP);

which will also set the pullup.

Pete

Bingo Pete,

I had the sketch modified (and a flag set in the ISR) and had it run for more than 36 hrs - and no more interrupt occured. When I put D2 to ground, the interrupt is triggered (as expected), but the rest of the time the UNO sleeps nicely.

So again an experience : never trust published sketches and never copy them without thinking (I thought, the DigitalWrite(2,HIGH) is a unknown way to set the pullup...)

Thank you for your help

PR

DigitalWrite(2,HIGH) is a unknown way to set the pullup

It sort-of is but you only have half of it. This sequence was the original way to set a pullup with Arduinos:

 pinMode(2,INPUT);
  digitalWrite(2,HIGH);

and it would still work today but the preferred way now is:

 pinMode(2,INPUT_PULLUP);

Pete

Hmmm…

I have to re-open this topic, as I build a “real” sketch (idea behind: activate a radio-sender by pressing a button)
In the attached sketch I omitted all code “around” but stuck to the bare bone:

#include <avr/sleep.h>
#include <Button.h>        //https://github.com/JChristensen/Button
#include <EEPROM.h>       
#include <avr/power.h>

#define RECEIVER 20
#define SERIAL_BAUD   9600

//This part defines  button pin
#define BUTTON_PIN      2 //Connect a tactile button switch (or something similar)
                          //from Arduino pin 2 to ground.
                          //user button on interrupt 0 (D2)
#define PULLUP true       //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true       //Since the pullup resistor will keep the pin high unless the
                          //switch is closed, this is negative logic, i.e. a high state
                          //means the button is NOT pressed. (Assuming a normally open switch.)
#define DEBOUNCE_MS 50    //A debounce time of 20 milliseconds usually works well for tactile button switches.

Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS);    //Declare the button

boolean Receiverprogram = false;
boolean Senderprogram = true;
volatile boolean buttonPressed = false;
byte sender_id;
byte NETWORKID;


void setup() {
  Serial.begin(SERIAL_BAUD);
  Serial.println("Start");
  Serial.flush();
  pinMode(2, INPUT_PULLUP);  // enable pull-up
  pinMode(3, OUTPUT);        // disable INT 1
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  detachInterrupt(1);
}



void loop()
{
     if (buttonPressed)
     {
         buttonPressed = false;
         detachInterrupt(0);
         Send_info();
     }
     if (!buttonPressed)
     {
         Serial.println("Button not pressed!");
         Serial.flush();
         attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2)
         sleepNow();
     }
}

void wakeUpNow()
{
    if (!buttonPressed)
    {
        Serial.println("XXX");
        Serial.flush();
        myBtn.read();                    //Read the button
        if (myBtn.isPressed())       //If the button was pressed, change  state
        {
            Serial.println("PPPPPPP");
            Serial.flush();
            buttonPressed = true;
        }
    }
}  // end of wakeUpNow

void Send_info()
{
    Serial.println("Rise and shine!");
    delay(2000); 
    Serial.println("Info sent...");

} // end of Send_info

 
void sleepNow()         // here we put the arduino to sleep
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
 
 
  noInterrupts ();           // timed sequence follows
  attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function wakeUpNow when pin 2 gets LOW
  detachInterrupt(1);
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  sleep_enable();
 
  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);  // turn on brown-out enable select
  MCUCR = bit (BODS);        // this must be done within 4 clock cycles of above
  interrupts ();             // guarantees next instruction executed
power_adc_disable(); // ADC converter
power_spi_disable(); // SPI
power_timer0_disable();// Timer 0
power_timer1_disable();// Timer 1
power_timer2_disable();// Timer 2
power_twi_disable(); // TWI (I2C)
    sleep_cpu();                     // here the device is actually put to sleep!!
    // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
    Serial.println("YYYYYY");
 
    sleep_disable();                  // first thing after waking from sleep: disable sleep...
power_timer0_enable();                // Timer 0 - otherwise the delay in func "Send_info" will not work!
    Serial.println("Here I am...");
    detachInterrupt(0);               // disables interrupt 0 on pin 2 so the wakeUpNow code will not be executed during normal running time.
}// end of sleepNow

I observed now the program for 24 hrs (UNO connected to USB/Serial of PC) and got the following output:

Start
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
XXX
PPPPPPP
YYYYYY
Here I am...
Rise and shine!
Info sent...
Button not pressed!

This means, there is still an event waking up the Arduino shortly, but not the interrupt on pin 2 . This interrupt I triggered at the very end by putting pin 2 to ground.

Does anybody have an idea? Or did I overlook again something???
Could it be the Serial Port from the PC? (Well, I know, “Serial.println” is not very well seen in an ISR, but it worked in my case…)

Have a nice sunday

PR

I have run your code on a NANO for the last 4 hours and the only output I get is:

Start
Button not pressed!

I suspect that you have a bad contact on that button.

A few comments on the code:

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  detachInterrupt(1);
  • You have already set the pinMode for pin 2. No need to do it again.
  • There's no need to detach interrupt 1 in setup(). It hasn't been attached.
         attachInterrupt(0, wakeUpNow, LOW); // use interrupt 0 (pin 2)

You would probably be better off using FALLING instead of LOW. If you do that, there's no need to keep detaching/attaching the interrupt. Attach it once in setup with FALLING.

In SleepNow()

  detachInterrupt(1);

Again, no point detaching an interrupt you aren't using.

Pete

Pete,

thanks for the fast reply - you are right with your remarks - but the real problem is that the interrupt from pin 2 is not triggered (otherwise the "button is pressed" and "XXX" and "PPPPP"). There is another devil which causes the UNO to wake up... BTW I had it run for approx. 6 hrs until the first event happened

Regards

PR

Well,

I loaded the above sketch now to a MEGA (I had to comment out the lines with the “BODS” as it does not exist on MEGA) and after some hours I got the same result as with the UNO:

Start
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
XXX
XXX
PPPPPPP
YYYYYY
Here I am...
Rise and shine!
Info sent...
Button not pressed!

So independent of the processor there is an event which causes the Arduino to wake up - but it’s obviously not the interrupt (LOW) on pin 2 (I triggered this interrupt at the end)

Any hint/idea/solution???

Have a nice evening

PR

The "Button not pressed!" message comes from the ISR for Pin 2 so, clearly, Pin 2 is going LOW long enough to trigger the interrupt. I suspect noise on the input pin. Try an external pull-up resistor, maybe 1k.

Yes, I will do so.
But in the meantime I experimented a bit and found the following behavior

Nothing connected to pin 2 - no message from MEGA
When I connect a jumperwire (ca 20cm) to pin2, and leave the other end of this wire floating in the air, I got within ca. 12 hrs the following output:

Start
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!
YYYYYY
Here I am...
Button not pressed!

This is clealy NOT the wake-up-interrupt (when pin 2 goes to LOW), but something else…

Strange…

Will keep you informed, but after some holidays!

PR