Fire Flys ATtiny85

(update 8-17-2022) This project made 10 ten list for 2022 best ATtiny85 projects :)

https://all3dp.com/2/best-attiny85-projects/


I love making these and have been making them for years..

They are a simulated fire flys, Which I've put in a jar or have outside on strands in bushes and/or trees that have lasted for years.

  • The basic Jar of fire fly's

Parts:

  • (3) 220 Ohm resistors (or close to that value)

  • (6) Led's (SMD, or through hole)

  • proto board or similar

  • attiny85 (or similar uController

  • LM358 ( or similar Op Amp)

  • (2) .1uF caps

  • TP4056 module

  • 6v solar panel small

  • in this case a Jar

  • and some container on top (3d printed in my case) for panel and electronics (although in the very first one I made I put the electronics at the top of the Jar).

jar-fire-flys-tilt to flash.mp4

ATtiny85 with OpAmp (for turning on circuit depending on how much light is hitting Solar Panel.

Circuit hooked to TP4056 to 6v solar panel.

LED's soldered to wire, then glued to 3d printed fire fly's with UV resin mixed with luminescent powder.

Just updated code on 8-17-22 (accidentally had older test cod in there prior).

/*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