Not sure if I ask really good questions or really bad questions since I never received any replies. Pretty sure it's the latter.
Phase 1 = Get buttoncycler example/circuit to work and customize showTypes (complete)
Phase 2 = Have current showType stop (even in the middle of running) when button pressed and advance to next showType (case)
Phase 3a = Have current showType repeat until button pressed (complete)
Phase 3b = Have current showType repeat until uC goes to sleep from 5-min idle timer
Phase 4 = Add a sleep mode to wake on external interrupt (button on P2)
Phase 5 = Optimize to reduce uAh and mAh
Made some changes to the code that got me some progress after 2-3 days of reading/editing. Any suggestions on how to stop a "for loop" or "for loops" nested together when I press a button? I've tried while, do/while, goto, if, break, return, continue.... but nothing seems to work as intended (although I'm sure it's working as written). I attached screencaps of a function (showType) that I wanted to interrupt. The examples/references in the IDE and on the website do not normally involve "for loops." I'm hesitant to try an interrupt because I want to use the button pin as an external interrupt when Sparky is asleep. Can I have 1 pin do 2 interrupts??
/* Cycle NeoPixels with button using Digispark ATtiny85 (microUSB version)
* Button on P2 (PCINT0) cycles through different modes (cases). Mode stops and switches to the
* next mode when button is pressed. Current mode plays until button is pressed or goes into
* low power mode after 5 minutes. uC wakes on button press on P2 (PCINT0) and continues program.
* User can turn off circuit with switched attached to VIN. User needs to press the
* button once to start the first animation!
* Momentary push button is wired to connect P2 to ground. P2 kept high by internal pullup.
* NeoPixel data in connected in series with a 330 ohm resistor to P0.
* Neopixel 5V and GND pins connected to Digispark ATtiny85 power rail 5V and GND pins, respectively.
* Program will eventually include SLEEP_MODE_PWR_DOWN & wdt_disable so it only awakens with PCINT0
*
* ISSUE LOG:
* 1. Button press does not stop showType in middle of function
* 2. showType runs until button pressed nut NOT 5-min sleep timer
* 3. Minimize power draw when awake
* 4. Remove delay() in showType functions
*/
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define BUTTON_PIN 2 // Digital IO pin connected to the button.
#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);
bool buttonPressed = false;
bool oldState = HIGH;
bool newState = HIGH;
int showType = 0;
unsigned long startMillis;
unsigned long currentMillis;
const int debouncePeriod = 20;
unsigned long debounceStartMillis;
// Neopixel color test
void testPixels()
{
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 0, 255), 50); // Blue
colorWipe(strip.Color(0, 255, 0), 50); // Green
}
// Check state of button
void checkButton()
{
// Get current button state
newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press)
if (newState != oldState)
{
if (currentMillis - debounceStartMillis >= debouncePeriod)
{
if (digitalRead(BUTTON_PIN) == LOW) // if button still pressed
{
newState = LOW;
oldState += newState; // Update oldState to last button state (newState)
buttonPressed = true; // trying to set flag that button is pressed
}
}
}
else
{
newState = HIGH;
oldState += newState;
buttonPressed = false;
}
}
void setup()
{
/* // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
*/
pinMode(PIXEL_PIN, OUTPUT);
digitalWrite(BUTTON_PIN, HIGH); // activate pull-up resistor to set pin HIGH
strip.begin();
strip.setBrightness(50); // dim output to conserve battery
strip.show(); // Initialize all pixels to 'off'
testPixels();
startMillis = millis(); //initial start time
}
void loop()
{
//get the current "time"
currentMillis = millis();
// Call to checkButton function
checkButton();
if (buttonPressed == true)
{
showType++;
if (showType > 8)
{
showType = 0;
}
}
startShow(showType);
// oldState = newState;
}
void startShow(int i) {
switch(i) {
case 0: checkButton();
colorWipe(strip.Color(0, 0, 0), 50); // Black/off
break;
case 1: checkButton();
colorWipe(strip.Color(153, 0, 255), 200); // Purple: Signifies pain, suffering, grief, and mourning
colorWipe(strip.Color(255, 0, 153), 200); // Pink: Celebration
colorWipe(strip.Color(127, 127, 127), 200); // White: Purity and hope
colorWipe(strip.Color(200, 51, 0), 200); // Orange: Sun
colorWipe(strip.Color(255, 0, 0), 200); // Red: The blood of life
colorWipe(strip.Color(255, 200, 0), 200); // Yellow: Cempazuchitl are marigolds that symbolize death.
break;
case 2: checkButton();
theaterChase(strip.Color(153, 0, 255), 200); // Purple
theaterChase(strip.Color(255, 0, 153), 200); // Pink
theaterChase(strip.Color(127, 127, 127), 200); // White
theaterChase(strip.Color(200, 51, 0), 200); // Orange
theaterChase(strip.Color(255, 0, 0), 200); // Red
theaterChase(strip.Color(255, 200, 0), 200); // Yellow
break;
case 3: checkButton();
rainbow(10);
break;
case 4: checkButton();
rainbowCycle(20);
break;
case 5: checkButton();
theaterChaseRainbow(50);
break;
case 6: checkButton();
rainbow(50);
break;
case 7: checkButton();
rainbowCycle(50);
break;
case 8: checkButton();
theaterChaseRainbow(100);
break;
}
}
void colorWipe(uint32_t c, uint8_t showSpeed)
{
for(uint16_t i=0; i<strip.numPixels(); i++)
{
strip.setPixelColor(i, c);
strip.show();
delay(showSpeed);
}
}
void theaterChase(uint32_t c, uint8_t showSpeed)
{
for (int j=0; j<10; j++) //do 10 cycles of chasing
{
for (int q=0; q < 3; q++)
{
for (int i=0; i < strip.numPixels(); i=i+3)
{
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(showSpeed);
for (int i=0; i < strip.numPixels(); i=i+3)
{
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
void rainbow(uint8_t showSpeed) {
uint16_t i, j;
for(j=0; j<256; j++)
{
for(i=0; i<strip.numPixels(); i++)
{
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(showSpeed);
}
}
void rainbowCycle(uint8_t showSpeed) {
uint16_t i, j;
for(j=0; j<256*5; j++) // 5 cycles of all colors on wheel
{
for(i=0; i< strip.numPixels(); i++)
{
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(showSpeed);
}
}
void theaterChaseRainbow(uint8_t showSpeed) {
for (int j=0; j < 256; j++) // cycle all 256 colors in the wheel
{
for (int q=0; q < 3; q++)
{
for (int i=0; i < strip.numPixels(); i=i+3)
{
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(showSpeed);
for (int i=0; i < strip.numPixels(); i=i+3)
{
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85)
{
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170)
{
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}