Hello! I am working on a project which is going well enough, but my current roadblock has me stymied. I am trying to make a blinky conference badge (LEDs) that can turn off (and back on, but it's processor sleep really) with a button (save battery power I figure). I am using an interrupt because that seems easiest in terms of the programming (except I can't make it work yet).
The badges do stop blinking (sleep) when the button is pressed, so I am feeling confident that the interrupt and the button as it is wired do indeed work. However, I can't get the LEDs to start blinking again despite having read (and tried) many potential solutions. So either the interrupt isn't working when the CPU is sleeping, or something else (like I've coded it wrong).
I'm using the Arduino IDE 2.3.5, with an ATMEGA328PB on a custom board. For the recent try (for the code I will post here), I am using PinChangeInterrupt (but I think it was sleeping with the regular library, but that isn't really relevant I don't think). My longer code with various patterns compiles and uploads and works great (I have a second button to change the mode, I have taken all that out of the minimal code example here and made sure to test this minimal code example, which does blink the one LED and turns it off but not back on, so sleep I assume).
Some examples I have found suggest just attaching the interrupt for the wake-up, but it makes my code so much easier to just have the interrupt all the time (I mean I could make that work, and had it that way for a while, but had the same problem where the LEDs would turn off as expected but then wouldn't come back on).
I am sure there are some relevant bits I have neglected to include. The below code does indeed blink the LED, then the on/off button when pressed makes that LED stop blinking, but then pushing the button again appears to have no effect. In the code example, I use an on/off boolean as was suggested in two posts I found. I've tried over-doing the wake up but that isn't working either. (Is this a bounce problem? Doesn't "Falling" get around that? Or, something about interrupts for the 328PB when sleeping?) (Oh right, I have the button wired to a PCINT pin because, well, the board layout I ended up with LEDs on the regular interrupt pins and only later learned about PCINT vs. INT but it should work, and I say that full well knowing "but it should work" is often the sign of the newbie making the obvious mistake, because clearly there is a mistake here somewhere and I am the one making it. What I mean is, that's why I'm using the PinChangeInterrupt.h library, to make sure I can access the PCINT pin that the button is connected to as an interrupt.)
Any guidance is appreciated. (I can probably upload the schematics just that doesn't appear as easy as including the code, but the button does appear to activate sleep, so I assume it's working but hey, assumptions. I have not fully cleaned up the comments in the code but you can ignore them.)
// Minimal example of awaken not working.
// Include Libraries
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/io.h>
#include <PinChangeInterrupt.h>
// Global Variables
const int led_yellow = PD2; // ATMega328PB pin references.
// Different online schematics show different pin desginations. Beware!
const int button_onoff = 8; //12; PB0
volatile bool isSleeping = false; // volatile maybe? since it is changed in the ISR
// before setup
void changeSleep() {
if (!isSleeping) { // if awake
isSleeping = true;
digitalWrite(led_yellow, LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode(); // MCU sleeps here
sleep_disable(); // Disable sleep after waking
isSleeping = false;
}
else {
sleep_disable(); // Disable sleep after waking
isSleeping = false;
}
}
void setup() {
pinMode(led_yellow, OUTPUT);
pinMode(button_onoff, INPUT_PULLUP); // the PULLUP is probably redundant but I tested it and it doesn't hurt.
attachPCINT(digitalPinToPCINT(button_onoff), changeSleep, FALLING); // yes in setup
}
void loop() {
blink_one();
} // main loop
// If the LEDs are on turn them off and vice-versa, for the blink pattern.
void reverse_led() {
if (digitalRead(led_yellow) == HIGH) digitalWrite(led_yellow, LOW);
else digitalWrite(led_yellow, HIGH);
} // reverse_all
void blink_one() {
unsigned long start = millis();
digitalWrite(led_yellow, HIGH);
while (true) {
if (millis() - start >= 20) { // beta timing for board
reverse_led(); //
start = millis();
}
} // while
} // blink

