Hi guys,
I have a strange phenomen I would like to hear if you had the same and if anyone has suggestions how to make the code robust.
I have an Arduino Nano (basically), I want to send it to sleep mode to save power and then wake it up again with a press of the button on D12. Usually it works, but if I make changes to the code, even someplace else not related to sleep mode, it suddenly misbeahaves. It can always go to sleep mode, but sometimes refuses to wake up from it. Problem is I have a battery operated setup and the whole system is encased, therefore if the device goes to sleep but cannot wake up, I have to disassemble the whole build to access the reset pin (it's USB charged with no switch to kill power).
I'm pretty sure the root cause is a kind of race condition/timing, because it's intermittent. But I do not understand it, please help me.
Here is what I programmed the sleep mode handler:
- I program the pin change interrupt on D12 in the setup() like this:
// pin change interrupt masks (see below list)
PCMSK0 |= bit (PCINT4); // pin 12 Main button
- Then I have a sleep mode handler latern on embedded into the loop(). If the device goes into sleep mode entry, following code is executed:
else if (SaberState == S_SLEEP) {
Serial.println("LoL");
// repeat the interupt mask again here, it is already done in the setup() function
// but for an unknown reason sometimes the device fails to wake up...
PCMSK0 |= bit (PCINT4); // pin 12 Main button
delay(300);
Serial.println("LoL");
ADCSRA = 0; // reduces another ~100uA!
SleepModeEntry();
// .. and the code will continue from here
SleepModeExit();
SaberState = S_STANDBY;
PrevSaberState = S_SLEEP;
ADCSRA = 135; // old_ADCSRA; // re-enable ADC conversion
// play boot sound
SinglePlay_Sound(11);
delay(20);
}
The 2 functions to enter and leave sleep modes are here:
void sleepNow() // here we put the arduino to sleep
{
power_all_disable (); // turn off all modules -> no measurable effect
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
// turn off brown-out enable in software -> no measurable effect
MCUCR = bit (BODS) | bit (BODSE);
MCUCR = bit (BODS);
PCIFR |= bit (PCIF0) | bit (PCIF1) | bit (PCIF2); // clear any outstanding interrupts
PCICR |= bit (PCIE0) | bit (PCIE1) | bit (PCIE2); // enable pin change interrupts
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.
}
void SleepModeEntry() {
// switch off all LS channels
for (uint8_t i = 0; i < sizeof(ledPins); i++) {
digitalWrite(ledPins[i], LOW);
}
// pin change interrupt masks (see below list)
//PCMSK2 |= bit (PCINT20); // pin 4 Aux button
PCMSK0 |= bit (PCINT4); // pin 12 Main button
mpu.setSleepEnabled(true);
Disable_MP3(true);
mpu.setSleepEnabled(true); // included as dummy, for an unknown reason if it's not here and the dfplayer.sleep() is commented out, sound is disabled
//dfplayer.sleep();
pinMode(DFPLAYER_RX, OUTPUT);
digitalWrite(DFPLAYER_RX, LOW);
pinMode(DFPLAYER_TX, OUTPUT);
digitalWrite(DFPLAYER_TX, LOW);
delay (300);
Disable_FTDI(true);
sleepNow(); // sleep function called here
}
void SleepModeExit() {
// cancel sleep as a precaution
sleep_disable();
power_all_enable (); // enable modules again
Disable_FTDI(false);
mpu.setSleepEnabled(false);
delay (300);
Disable_MP3(false);
pinMode(DFPLAYER_RX, OUTPUT);
pinMode(DFPLAYER_TX, INPUT);
delay (300);
// only wake up the device if the main button is pressed for at least 1 sec
//delay(1000);
//if (digitalRead(MAIN_BUTTON) == LOW) {
setup(); // redo all initializations
//}
//else { // Anti-Wake up Protection triggers, go back to slee mode
// SleepModeEntry();
//}
}
I followed the instructions for sleep mode setup and wake-up from here:Gammon Forum : Electronics : Microprocessors : Power saving techniques for microprocessors
The whole project and code can be found here (last stable version, whereby some users already had issue with the sleep mode):