/* Revision 1: 2024 - 01 - 18 - 14:00 ################################ General Layout ############################################## # (PCINT5/!RESET/ADC0/dW) PB5 1 | AT | 8 VCC # (PCINT3/X<10TAL1/CLKI/!OC1B/ADC3) PB3 2 | TI | 7 PB2 (SCK/USCK/SCL/ADC/T0/INT0/PCINT2) # (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 3 | NY | 6 PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1) # ________________________________ GND 4 | 85 | 5 PBO (MOSI/DI/SDA/AIN0/OC0A/!OC1A/AREF/PCINT0) +++++++++++++++++++++++++++++++ Project Layout +++++++++++++++++++++++++++++++++++++++++++++++++ +--------+ Reset - 1 --+ +-- 8 - Vcc Vcc-R-Light_Sensor-GND - ADC3/PB3 - 2 --+ +-- 7 - PB2/ADC1 - Vcc-control, U_min 3,8V - ADC1 (GND-100k-100k-Vcc) Vcc-R-LED_Vcc_Warning (red on Breadboard)-GND - PB4 - 3 --+ +-- 6 - PB1 - LED Christmas star (blue on Breadboard) --> nKanalMosfet GND - 4 --+ +-- 5 - PB0/PCINT0 - +--------+ +++++++++++++++++++++++++++++++ Project Layout +++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++ Project Calculation ++++++++++++++++++++++++++++++++++++++++++++ Battery characteristic: LiPo - LiPO_V_max >=4,2 V - Lipo_V_min =3,5 V --> to activate battery warning signal --> V_min = 0,928571429% of V_max Reference voltage: Vref = 2,56V --> voltage divider 1:1 Warning threshold: 100 kO:100 kO --> U_R2/V_Ref = 68,36% --> Threshold for ADC-input 1,75 V = 0,6836 * Vref (2,56V) = 175 to activate battery warning signal Dark threshold: V threshold light sensor = 0,4V --> 0,4/2,56 = 0,15625 --> Light_sensor_threshold = 15 +++++++++++++++++++++++++++++++ Project Calculation ++++++++++++++++++++++++++++++++++++++++++++ https://symbl.cc/de/alt-codes/ ~ = Alt 126 { = Alt 123 } = Alt 125 ° - Alt 0176 µ - Alt 0181 | = Alt 0124 kO ! logic Negation ! b */ /* Excel file to calculate variables: Weihnachtsstern-Berechnungen.xlsx */ /* -------------------- Literature ----------------- Interrupt-Taster INT0: (www.electronicwings.com) + https://www.electronicwings.com/avr-atmega/atmega1632-external-hardware-interrupts origin written for ATmega16 https://elektro.turanis.de/html/prj271/index.html http://www.technoblogy.com/show?KX0 ADC: https://www.marcelpost.com/wiki/index.php/ATtiny85_ADC Save Power: https://elektro.turanis.de/html/prj271/index.html Timer normal Mode with Interrupt https://www.gadgetronicx.com/attiny85-timer-tutorial-generating-time-delay-interrupts/ https://wolles-elektronikkiste.de/timer-und-pwm-teil-1 Timer compare Mode with Interrupt https://www.gadgetronicx.com/attiny85-compare-match-tutorial-interrupts/ */ #define F_CPU 1000000UL typedef enum { false, true} bool; #define LED_Vcc_Warning PB4 // PIN3 - PB4 - LED_Vcc_Warning red --> output #define LED_Christmas_Star PB1 // PIN6 - PB1 - LED_Light blue --> output #define ADC1_Pin7 PB2 #define ADC3_Pin2 PB3 #include #include #include const int Light_sensor_threshold=198; // compare value to detect dark threshold const int Vcc_Warning_threshold=175; // compare value to detect low LiPo voltage const int Timer0_Startvalue = 12; // set start value Timer/Counter Register tor reach 250 ms const long Timer0_Value_250ms = 40; // 4 for 1 second --> 6 h --> 4*21600 = 86400 const int LED_Christmas_Star_Blinc = 5; // pause (sec) after LED_Christmas_Star was on const long Darkness_Delay = 1000; // numbers of sec to calculate the delay time 15 min --> 900000 ms int Timer0_Counter = 0; // variable to count Timer0 interrupts, all 250 ms one interrupt int i; // common variable int n; // common variable int z; // common variable bool Flag_Vcc_Warning; // true, if LiPo voltage to low bool Flag_Dark; // true, if darkness begins --> wait for 10 min to switch ChristmasStar on bool Flag_Dark_Consist; // true, if really dark --> ChristmasStar on //bool Flag_ChristmasStar; // true, if ChristmasStar on void Init_IO_Ports(); void LED_Christmas_Star_On (); void LED_Christmas_Star_Off(); void LED_Vcc_Warnin_On(); void LED_Vcc_Warning_Off (); void Init_ADC3_8bit_256mV_prescaler16(); void Init_ADC1_8bit_256mV_prescaler16(); void read_ADC3_Light_sensor(); void read_ADC1_Vcc(); void Timer0_Setup(); void Timer0_IR_On(); void Timer0_IR_Off(); ISR (TIMER0_OVF_vect) { //Interrupt vector for Timer0 TCNT0=Timer0_Startvalue; // set start value Timer/Counter Register ++Timer0_Counter; cli(); } int main(void) { Init_IO_Ports (); LED_Christmas_Star_Off (); Timer0_Setup(); Timer0_IR_Off(); Flag_Vcc_Warning = false; Flag_Dark_Consist = false; //Flag_ChristmasStar = false; Timer0_Counter = 0; n = Timer0_Value_250ms/40; i = 0; z = 0; while(1) { read_ADC3_Light_sensor(); read_ADC1_Vcc(); if (!Flag_Dark && !Flag_Dark_Consist) { // initialize if environment is bright again Flag_Dark_Consist = false; //Flag_ChristmasStar = false; LED_Christmas_Star_Off (); Timer0_Counter = 0; n = Timer0_Value_250ms/40; i = 0; z = 0; Timer0_IR_Off(); } if (Flag_Dark) { // environment is dark, test if there light glitches for Darkness_Delay _delay_ms(Darkness_Delay); // Darkness_Delay has to be 900000 for 15 min if (Flag_Dark) { // ? is still dark Flag_Dark_Consist = true; // it's really dark } } while (Flag_Dark_Consist) { if (!Flag_Vcc_Warning) { // Vcc ok if (Timer0_Counter <= Timer0_Value_250ms) { LED_Christmas_Star_On(); Timer0_IR_On(); } else { LED_Christmas_Star_Off(); Timer0_IR_Off(); Flag_Dark_Consist = false; // new start if next light impulse occurs } } else { // Vcc to low if (Timer0_Counter%LED_Christmas_Star_Blinc == 0 ) { // to signal Vcc to low Timer0_IR_Off(); LED_Christmas_Star_Off(); _delay_ms(LED_Christmas_Star_Blinc); LED_Christmas_Star_On(); Timer0_IR_On(); } else { if (Timer0_Counter >= Timer0_Value_250ms) { LED_Christmas_Star_Off(); Timer0_IR_Off(); Flag_Dark_Consist = false; } } } } } return 0; } void Timer0_IR_On() { sei(); } void Timer0_IR_Off() { cli(); } void Timer0_Setup() { // set prescaler 010 = 8 8us), 011 = 64 (64us); 100 = 256 (256us); 101 = 1024 (1,024 ms) --> 262,144 ms TCCR0B |= (1< 8 bit resolution ADMUX |= (1 << REFS2) | (1 << REFS1) | (0 << REFS0); // Sets ref. voltage to 2.56 V without capacitor - Vcc = 000; 2.56 V = 110; 1.1V = 010 ADMUX |= (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (1 << MUX0); // ADC3 for input (PB2) = 0010; ADC2 (PB4) = 0010; ADC1 (PB2) = 0001; ADC0 (PB5) = 0000 // frequency (delivery condition) 1MHz - preferred sample frequency 50 kHz-200 kHz --> prescaler 5-20 // prescaler 2 = 001 (500 kHz); 4 = 010 (250 kHz); 8 = 011 (125 kHz); 16 = 100 (62,5 kHz); 32 = 101 (31,25 kHz); 64 = 110 (15,625 kHz); 128 = 111 (7,8125 kHz) ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); // Prescaler = 64 --> 15.625 kHz ADCSRA |= (1 << ADEN); // Enable ADC } void read_ADC3_Light_sensor(){ Init_ADC3_8bit_256mV_prescaler16(); ADCSRA |= (1< Light_sensor_threshold){ // Flag_Dark=true; } else {Flag_Dark=false; } } // ADC1 - Vcc sensor void Init_ADC1_8bit_256mV_prescaler16() { ADMUX = (1 << ADLAR); // left shift result --> 8 bit resolution ADMUX |= (1 << REFS2) | (1 << REFS1) | (0 << REFS0); // Sets ref. voltage to 2.56 V without capacitor - Vcc = 000; 2.56 V = 110; 1.1V = 010 ADMUX |= (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (1 << MUX0); // ADC3 for input (PB2) = 0010; ADC2 (PB4) = 0010; ADC1 (PB2) = 0001; ADC0 (PB5) = 0000 // frequency (delivery condition) 1MHz - preferred sample frequency 50 kHz-200 kHz --> prescaler 5-20 // prescaler 2 = 001 (500 kHz); 4 = 010 (250 kHz); 8 = 011 (125 kHz); 16 = 100 (62,5 kHz); 32 = 101 (31,25 kHz); 64 = 110 (15,625 kHz); 128 = 111 (7,8125 kHz) ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0); // Prescaler = 64 --> 15.625 kHz ADCSRA |= (1 << ADEN); // Enable ADC } void read_ADC1_Vcc(){ Init_ADC1_8bit_256mV_prescaler16(); ADCSRA |= (1<