Trying to make some NeoPixels cycle through modes when the user presses a button. Then, I want it to go to sleep after 10 minutes of being idle (no one pressed a button) and wake on button press. I need to minimize power consumption because I want to power it with a CR2032 attached to an energy scavenger module (.9-4V to 5V).
I got the Pixels to cycle as desired, but ran into a snag when I tried to add a sleep mode to wake on an external interrupt only on pin 2(PCINT0).
When I added the extra code, ol' Sparky85 does nothing...visibly. My laptop starts cycling through recognizing Sparky85 & disconnecting. Tried using a USB power bank, but same results. Button does not "wake up" or cycle through the patterns. The power LED is on though (until I remove it).
The code is a the offspring of the NeoPixel buttoncycler sketch, Nick Gammon's sketches on interrupts & low power threads, an assist from a user on another board turning for loops into state machines, and a dash of stuff from different websites.
Picture of the simple setup:

The amalgam of code:
#include <avr/sleep.h> // library for sleep modes
#include <avr/power.h> // library for power management
#include <avr/wdt.h> // disable/enable WDT
#include <avr/interrupt.h> // library for interrupts NEEDED???
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define PIXEL_PIN 0 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 9
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
unsigned long idleMillis; // Measure idle time between button presses
unsigned long patternInterval = 20 ; // time between steps in the pattern
unsigned long lastUpdate = 0; // for millis() when last update occurred
unsigned long showSpeed [] = { 30, 30, 30, 10, 10, 30, 60, 60, 60 } ; // speed for each pattern - add here when adding more cases
const byte BUTTON_PIN = 2; // Pin 2 / PCINT0 / externalInturrupt
// Function to put Digispark to sleep
void goToSleep ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sets the mode for power consumption during sleep
pinMode(PIXEL_PIN, INPUT); // Change pin to input
ADCSRA = 0; // Turn off ADC if not already done in setup()
power_all_disable(); // power off ADC, Timer 0 and 1, serial interface
wdt_disable(); // Disable Watchdog Timer so only button wakes up MCU
sleep_enable(); // Enables the sleep bit so that the processor can actually be put to sleep with sleep_mode ()
sleep_bod_disable(); // Disable brown out detection to reduce power consumption in sleep mode. Auto-enables on wake
noInterrupts(); // Turn other interrupts OFF while attaching interrupt
attachInterrupt(0, awakeNow, LOW); // 0 = PCINT0 = P2 on button press, fires the ISR to wake up processor
interrupts(); // Turn interrupts ON
sleep_mode(); // Should now be sleeping like a baby
sleep_disable(); // Program returns to this point when the ISR fires
noInterrupts(); // Turn other interrupts OFF
detachInterrupt(0); // Stop MCU from registering BUTTON_PIN press to LOW
interrupts(); // Turn interrupts ON
wdt_enable(WDTO_8S); // Enable Watchdog Timer to 8S
power_all_enable(); // power everything back on
ADCSRA = 0; // Turn off ADC because I don't need it
pinMode(PIXEL_PIN, OUTPUT); // Change pin to output
}
// Interrupt Service Routine (ISR) to wake up the Digispark
void awakeNow ()
{
// ISR blank or add detachInterrupt(0);?
}
// Set unused pins to INPUT and LOW to save power
void inputsLow ()
{
digitalWrite(1, INPUT);
digitalWrite(3, INPUT);
digitalWrite(4, INPUT);
digitalWrite(4, INPUT);
digitalWrite(1, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(4, LOW);
}
void setup()
{
pinMode(PIXEL_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT);
digitalWrite(BUTTON_PIN, HIGH); // activate pull-up resistor to set pin HIGH
inputsLow(); // Set other pins to LOW
strip.begin();
strip.setBrightness(50); // dim output to conserve battery
strip.show(); // Initialize all pixels to 'off'
idleMillis = millis(); // Start idle time
// pin change interrupt
PCMSK |= bit (PCINT0); // want P2 on Digispark
GIFR |= bit (PCIF); // clear any outstanding interrupts
GIMSK |= bit (PCIE); // enable pin change interrupts
ADCSRA = 0; // Turn off ADC because I don't need it
}
void loop()
{
static byte idleTime = 1; // Sets idle time before sleep mode
if (millis() - idleMillis >= (1000UL*60*idleTime)) // 1000(unsigned long)ms * 60(sec/min) * # minutes
{
goToSleep(); // Will uncomment once sleep/wake functions correct
}
// Start with case 0
static byte showType = 0;
static bool oldState;
// Get current button state
bool newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press)
if (newState == LOW && oldState == HIGH)
{
showType++; // Move to next showType
idleMillis = millis(); // Reset idle timer
if (showType > 8) // If showType exceeds number of shows
{
showType = 0; // Reset showType to case 0
}
patternInterval = showSpeed[showType]; // Set speed for this pattern
delay(20); // Debounce delay
}
oldState = newState; // Update state
if (millis() - lastUpdate > patternInterval)
{
startShow(showType);
}
}
Function with switch/case with different patterns