/*Fireflies
ATTiny85
Sherman Stebbins
Modified by Sherman Stebbins 11/5/17updated 11-18-17 added sleep random to save power.updated 7-1-21 updated for tilt switchupdated 7-31-21 added pinMode(piezoPin,INPUT_PULLUP); or DDRB &= ~(1 << DDRB4); //set PB4 as inputPORTB = (1<<PB4); //activate pull-up resistor for PB4Appears to be most updated version 08-17-2022
*/
// ATMEL ATTINY 25/45/85 / ARDUINO//// +-\/-+// Ain0 (D 5) PB5 1| |8 Vcc// pinD Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1 pinC// piezoPin Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1 pinB// GND 4| |5 PB0 (D 0) pwm0 pinA// +----+
#include <avr/sleep.h> // Sleep Modes#include <avr/power.h> // Power management#include <avr/wdt.h> // Watchdog timer
int delaytime = 7; //set delay time here, 1-9 (9 is max 8 seconds, 8 is 4 seconds, 7 is 2 seconds, 6 is 1 second, 5 is .5 seconds, 4 is .25 second etc)
// Pin assignmentsconst byte pinA = 0;const byte pinB = 1;const byte pinC = 2;const byte piezoPin = 4; // analog pin 2 */
// LED variablesbyte currentLED;byte previousLED = -1;byte rampUpSpeed;byte rampDownSpeed;byte numBlinks;int counter;
// Piezo variablesconst int piezoBufferSize = 10;int piezoValues[piezoBufferSize];int piezoThreshold = 1; //originally 1int piezoCounter = 0;
int randExcitedCounter=0;int randExcited = 5;
// Behavior statesconst byte BEGIN = 0;const byte RAMP_UP = 1;const byte BLINKING = 2;const byte RAMP_DOWN = 3;const byte EXCITED = 4;byte CURRENT_ACTION = BEGIN;
void setup() { resetWatchdog (delaytime); // do this first in case WDT fires // Flush any stray current from the ports randomSeed(analogRead(2)); //Added for newer makes without external Pullup for tilt switch pinMode(piezoPin,INPUT_PULLUP); turnOffAll();}
void loop() { switch(CURRENT_ACTION) { // BEGIN ========================================= // + Set up all the variables to flash new LED case BEGIN: // Choose a new LED previousLED = currentLED; do { currentLED = (int)random(1,7); //originally 1,6 but one light would not turn on } while(currentLED == previousLED); //currentLED = 6;
//added 11-18-2017 sleep random(5,9); //changed from 8 to 9 on 7/6/21 goToSleep (delaytime); // Number of times to blink numBlinks = (int)random(1,6); // Fade in and fade out speed rampUpSpeed = random(6); //ORIGINALLY 6 rampDownSpeed = rampUpSpeed*2; counter = 0;
/////added 10-3-2019/// random excited if(randExcited == randExcitedCounter){ CURRENT_ACTION = EXCITED; randExcitedCounter=0; randExcited = (int)random(17,25);//15,25); }else{ CURRENT_ACTION = RAMP_UP; } randExcitedCounter++; //CURRENT_ACTION = RAMP_UP; /////////end random excited///// //CURRENT_ACTION = RAMP_DOWN; //counter = 255; break; // RAMP UP ======================================== // + Fade in the LED case RAMP_UP: analogOn(currentLED, counter); delay(rampUpSpeed); if(counter >= 255) { CURRENT_ACTION = BLINKING; counter = 0; } else { counter++; } break; // BLINKING ==================================== // + Blink the LED a certain number of times case BLINKING: analogOn(currentLED, 0); delay(random(10,50));//ORIGINALLY 10,50 analogOn(currentLED, 255); delay(random(30,100));//ORIGINALLY 30,100 if(numBlinks > 0) { numBlinks--; } else { CURRENT_ACTION = RAMP_DOWN; counter = 255; } break; // RAMP DOWN =========================================== // + Fade out the LED case RAMP_DOWN: analogOn(currentLED, counter); delay(rampDownSpeed); if(counter == 0) { CURRENT_ACTION = BEGIN; //delay(2000); } else { counter--; } break; // EXCITED ========================================= // + Flash each LED, one at a time, six times in a row case EXCITED: for(int j=0; j<6; j++) { for(int i=1; i<=6; i++) { turnOn(i); delay(50); turnOff(i); delay(50); } } CURRENT_ACTION = BEGIN; break; } //checkPiezo(); if (digitalRead(4)==LOW){ //LOW){ CURRENT_ACTION = EXCITED; }}
// Turn on a single LED to full brightnessvoid turnOn(byte led) { analogOn(led, 255);}
// Turn off an LED completelyvoid turnOff(byte led) { analogOn(led, 0);}
void turnOffAll() { digitalWrite(pinA, LOW); digitalWrite(pinB, LOW); digitalWrite(pinC, LOW);}
// Write an analog value to an LEDvoid analogOn(byte led, byte value) { switch(led) { case 1: pinMode(pinA, OUTPUT); pinMode(pinB, OUTPUT); pinMode(pinC, INPUT); digitalWrite(pinA, LOW); analogWrite(pinB, value); break; case 2: pinMode(pinA, OUTPUT); pinMode(pinB, OUTPUT); pinMode(pinC, INPUT); digitalWrite(pinB, LOW); analogWrite(pinA, value); break; case 3: pinMode(pinA, INPUT); pinMode(pinB, OUTPUT); pinMode(pinC, OUTPUT); digitalWrite(pinC, HIGH); analogWrite(pinB, 255-value); break; case 4: pinMode(pinA, INPUT); pinMode(pinB, OUTPUT); pinMode(pinC, OUTPUT); digitalWrite(pinC, LOW); analogWrite(pinB, value); break; case 5: pinMode(pinA, OUTPUT); pinMode(pinB, INPUT); pinMode(pinC, OUTPUT); digitalWrite(pinC, HIGH); analogWrite(pinA, 255-value); break; case 6: pinMode(pinA, OUTPUT); pinMode(pinB, INPUT); pinMode(pinC, OUTPUT); digitalWrite(pinC, LOW); analogWrite(pinA, value); break; }}
void checkPiezo() { if(piezoCounter < piezoBufferSize) { // Take a reading //pinMode(piezoPin,INPUT); int val = analogRead(piezoPin); piezoValues[piezoCounter] = val; } else { // Find average int avg = 0; for(int i=0; i<piezoBufferSize; i++) avg += piezoValues[i]; avg = avg/piezoBufferSize; if(avg >= piezoThreshold) { for(int j=0; j<6; j++) { for(int i=1; i<=6; i++) { turnOn(i); delay(50); turnOff(i); delay(50); } } } // Reset counter piezoCounter = 0; } piezoCounter++;}
void goToSleep (int dt) { set_sleep_mode (SLEEP_MODE_PWR_DOWN); ADCSRA = 0; // turn off ADC power_all_disable (); // power off ADC, Timer 0 and 1, serial interface noInterrupts (); // timed sequence coming up resetWatchdog (dt); // get watchdog ready sleep_enable (); // ready to sleep interrupts (); // interrupts are required now sleep_cpu (); // sleep sleep_disable (); // precaution //ADCSRA = 1; //hope it works -- no luck power_all_enable (); // power everything back on } // end of goToSleepvoid resetWatchdog (int dt) { // clear various "reset" flags MCUSR = 0; // allow changes, disable reset, clear existing interrupt WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF); // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
switch(dt){ case 1: WDTCR = bit (WDIE) | bit (WDP0); // 32 milli seconds break; case 2: WDTCR = bit (WDIE) | bit (WDP1); // 64 milli seconds break; case 3: WDTCR = bit (WDIE) | bit (WDP1) | bit (WDP0); // .125 second break; case 4: WDTCR = bit (WDIE) | bit (WDP2); //.25 seconds break; case 5: WDTCR = bit (WDIE) | bit (WDP2) | bit (WDP0); // .5 seconds break; case 6: WDTCR = bit (WDIE) | bit (WDP2) | bit (WDP1); // 1 second break; case 7: WDTCR = bit (WDIE) | bit (WDP2) | bit (WDP1) | bit (WDP0); // 2 seconds break; case 8: WDTCR = bit (WDIE) | bit (WDP3); // 4 seconds break; case 9: WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay break; default: break; } // pat the dog wdt_reset(); } // end of resetWatchdog
ISR (PCINT0_vect) { // do something interesting here } // end of PCINT0_vect // watchdog interruptISR (WDT_vect) { wdt_disable(); // disable watchdog} // end of WDT_vect