// Solar Bling by Thomas Hudson 1/5/2014 // http://www.instructables.com/id/Solar-Bling/ // //ATTINY85 // // // +---\/---+ // RESET 1| |5 VCC // A3 PB3 2| |6 PB2 A1 (SCK) // A2 PB4 3| |7 PB1 (MISO) PWM // GND 4| |8 PB0 (MOSI) PWM // +--------+ // // // I borrowed a lot of the sleep code from the following: // Written by Pavel Mihaylov and Tatqna Mihaylova // For full instructions see: http://www.instructables.com/id/Fridge-Door-Detector-Alarm/ #include #include #ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif volatile boolean f_wdt = 1; int LED0 = 4; //red LEDs int LED2 = 0; //green LEDs int LED1 = 1; //joule thief LEDs int sensorValue = 0; //senses whether there is daylight hitting the solar cell int capVoltage = 0; //senses the voltage at the capacitor int sensorCapPin = 2; //PB2 is the digital pin reference for analog sensor A1 int sensorPvPin = 3; //PB3 is a digital pin int pulse = 0; int song = 0; extern volatile unsigned long timer0_overflow_count; //This is required to know when a rollover occurs void setup() { pinMode(sensorCapPin, INPUT); //connected at the divider between a diode and resistor pinMode(sensorPvPin, INPUT); // connected to PV via mosfet pinMode(LED0, OUTPUT); //red pinMode(LED1, OUTPUT); //joule thief pinMode(LED2, OUTPUT); //green setup_watchdog(7); // approximately 2 seconds sleep // 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec } void loop() { // if (f_wdt==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs f_wdt=0; // reset flag // /* The capVoltage is sensing the voltage between the zener diode and 100K resistor. I manually measured the voltage across the super capacitor and across the 100K resistor and calculated the ADC the Attiny85 is measuring (@ pin PB2, capVoltage) (the attiny85 does not have a Serial Monitor!). Here is an abreviated table of measurements: Capacitor(V) 100k(V) estimated capVoltage ADC 1.1v 0.26v 0.26/1.1 * 1023 => 242 2.03v 1.01v 1.01/2.03 * 1023 => 509 2.49v 1.42v 1.42/2.49 * 1023 => 583 this works because the zenner voltage drop changes slightly with forward voltaeg where the 100k resistor is completely passive. You must meditate on this for awhile. */ capVoltage = read_capacitor(); if(capVoltage > 597) //In case the voltage is too high { setup_watchdog(0); // approximately 16ms seconds sleep digitalWrite(LED0, HIGH); digitalWrite(LED2, HIGH); delay(2000); } capVoltage = read_capacitor(); if(capVoltage > 596 && capVoltage < 598) //In case the voltage is too high { setup_watchdog(6); // approximately 1 seconds sleep digitalWrite(LED0, HIGH); digitalWrite(LED2, HIGH); delay(1000); } capVoltage = read_capacitor(); if(capVoltage > 594 && capVoltage < 597) //In case the voltage is too high { setup_watchdog(6); // approximately 1 seconds sleep digitalWrite(LED0, HIGH); digitalWrite(LED2, HIGH); delay(500); } capVoltage = read_capacitor(); if(capVoltage < 595) //In case the voltage is too high { setup_watchdog(9); // approximately 8 seconds sleep. The idea here is if we're charged and the sun has not set, lets sleep more. digitalWrite(LED0, LOW); digitalWrite(LED1, LOW); digitalWrite(LED2, LOW); } //if(read_PV()) //See if it is dark out //{ //digitalWrite(LED0, HIGH); //delay(100); //digitalWrite(LED0, LOW); //delay(100); //digitalWrite(LED0, HIGH); //delay(100); //digitalWrite(LED0, LOW); //} if(read_PV()) //See if it is dark out { if(capVoltage > 575) //normal LED { setup_watchdog(7); // approximately 2 seconds sleep digitalWrite(LED0, HIGH); delay(100); digitalWrite(LED0, LOW); delay(100); digitalWrite(LED2, HIGH); delay(100); digitalWrite(LED2, LOW); delay(100); digitalWrite(LED0, HIGH); delay(100); digitalWrite(LED0, LOW); } } if(read_PV()) //See if it is dark out { if(capVoltage < 576 && capVoltage > 511) //normal LED { setup_watchdog(7); // approximately 2 seconds sleep digitalWrite(LED0, HIGH); delay(100); digitalWrite(LED0, LOW); delay(200); digitalWrite(LED0, HIGH); delay(75); digitalWrite(LED0, LOW); } } if(read_PV()) //See if it is dark out { if(capVoltage < 512 && capVoltage > 300) // Joule thief { setup_watchdog(7); // approximately 2 seconds sleep digitalWrite(LED0, LOW); digitalWrite(LED2, LOW); digitalWrite(LED1, HIGH); delay(100); digitalWrite(LED1, LOW); delay(100); digitalWrite(LED1, HIGH); delay(100); digitalWrite(LED1, LOW); } } if(read_PV()) //See if it is dark out { if(capVoltage < 301 && capVoltage > 280) // Joule thief { setup_watchdog(7); // approximately 2 seconds sleep digitalWrite(LED0, LOW); digitalWrite(LED2, LOW); digitalWrite(LED1, HIGH); delay(10); digitalWrite(LED1, LOW); delay(10); digitalWrite(LED1, HIGH); delay(10); digitalWrite(LED1, LOW); } } if(read_PV()) //See if it is dark out { if(capVoltage < 281 && capVoltage > 250) // Joule thief { setup_watchdog(7); // approximately 2 seconds sleep digitalWrite(LED0, LOW); digitalWrite(LED2, LOW); digitalWrite(LED1, HIGH); delay(20); digitalWrite(LED1, LOW); } } if(capVoltage < 260) // OK, are power is low... say around 1.1 volts, so lets shut down and wait for the sun to rise. { digitalWrite(LED0, LOW); digitalWrite(LED2, LOW); digitalWrite(LED1, LOW); setup_watchdog(9); // approximately 8 seconds sleep. Lets sleep mroe too. } //Now put the system to sleep system_sleep(); } } ////////////////////////////////////////////////////////////// int read_capacitor()// { sensorValue = analogRead(1); //use the analog pin reference here (although same as digital PB2=A1) return sensorValue; } int read_PV() //returns 1 if it is dark { sensorValue = digitalRead(3); // if(sensorValue > 0) { //this equates to the mosfet gate is closed return 1; // it is dark outside } else { return 0; // it is light outside } } // int tones = random(5,200); // if(tones>50) { // song = 100; } // else { // song = 500; } // for(int i=0; i 9 ) ii=9; bb=ii & 7; if (ii > 7) bb|= (1<<5); bb|= (1<