ATtiny402-202 Blow out candle

Blow on the Candle and it lights. Blow on the candle and it goes out.. Sleeps at about 4uA (.2uA for ATtiny402, .6uA for MCP6546  Comparator, .5uA for NCV8170  LDO 2.8v, the rest is the microphone)

Grains of Salt next to the LDO which looks triny compaired to ATtiny10 and grain of rice.

ATtiny10 looks huge, along with the grain of rice on a dime.. AND the grains of salt next to the LDO chip.. which I hand soldered..

video.mp4
/* * ATtiny402-Blow-out-candle-w-flicker.c *(Combined with ATtiny402-candle-flicker.c and * ATtiny402-Blow-out-candle-comparator.c) * * With Comparator for blow out circuit, Works Great!! * Sleeps at 190nA. With Comparator its .7uA, with LDO its 1.3uA * with microphone its about 4-6 uA * * Created: 2/24/2023 07:58:34 * Author : Sherman Stebbins */ 

#define F_CPU 10000000UL#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <util/delay.h>#include <stdlib.h> //for rand(); works
static uint16_t randNum = 0;static uint16_t randTime = 0;static uint16_t flickerCount =0;
#define MAX 200
volatile uint8_t state = 0;volatile uint16_t count = 0;volatile uint8_t stateChange = 0;volatile uint8_t sleepState = 0;volatile uint16_t sleepCount = 0;volatile uint8_t timerACount = 0;
void delay(uint16_t delay_time);void gotosleep(void);

// Init timer/counter B (TCB) //for flicker of candlevoid TCB_init(void) { TCB0.CTRLA   = TCB_CLKSEL_CLKDIV1_gc          // set prescaler | TCB_ENABLE_bm;                 // enable timer TCB0.CTRLB   = TCB_CNTMODE_INT_gc;            // set timer to periodic interrupt mode TCB0.CCMP    = 0x025C;                   // set TOP value TCB0.INTCTRL = TCB_CAPT_bm;                   // enable interrupt sei();
}
// Init timer/counter A (TCA) for //loop count to shut off candle if on over an hourvoid TCA0_init(void){ TCA0.SINGLE.INTCTRL = (1 << TCA_SINGLE_OVF_bp); /* set PWM frequency and duty cycle (50%) */ TCA0.SINGLE.PER  = 0x01A0;// TCA0.SINGLE.CMP0BUF = 0x00D0; TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1024_gc        /* set clock source (sys_clk/4) */ | TCA_SINGLE_ENABLE_bm;           /* start timer */}
int main(void){ // SLPCTRL.CTRLA = 0b00000101; //power down and sleep enable bits PORTA.DIR =  0b00000010; //set pin 6 as input and pin 1 as output
//flash candle on power up: PORTA.OUT |= PIN1_bm; _delay_ms(500); PORTA.OUTCLR = PIN1_bm;
//pull up pin 2 and set it to trigger int on falling edge: PORTA.PIN6CTRL = PORT_ISC_FALLING_gc; //this was my fix for changing current draw sei(); //Set enable interrupt //set sleep to power down //SLPCTRL.CTRLA = 0b00000101; //sherms way SLPCTRL.CTRLA = SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm; //Microchip studio showed this gotosleep(); //sleep
while (1) { if(stateChange){ stateChange=0; //debug: //if(state){ // _delay_ms(500); // PORTA.OUT |= PIN1_bm; //}else{ // PORTA.OUT &= ~PIN1_bm; // _delay_ms(500); // gotosleep(); //} } }}
void delay(uint16_t delay_time){ for(uint16_t i=0;i<= delay_time;i++){ _delay_us(800); }}
void gotosleep(void){ sleepCount=0;
PORTA.OUTCLR = PIN1_bm; PORTA.OUTCLR = PIN2_bm; PORTA.DIRSET = 0b00000000;
PORTA.PIN3CTRL = PORT_PULLUPEN_bm; PORTA.PIN1CTRL = PORT_PULLUPEN_bm; PORTA.PIN7CTRL = PORT_PULLUPEN_bm; // PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
sei(); SLPCTRL.CTRLA = 0b00000101; //set power down and sleep enable asm("sleep"); //sleep //turn off pull ups after sleep // PORTA.PIN3CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN1CTRL &= ~(PORT_PULLUPEN_bm); // PORTA.PIN7CTRL &= ~(PORT_PULLUPEN_bm); // PORTA.PIN6CTRL &= ~(PORT_PULLUPEN_bm);
PORTA.DIR =  0b00000010; //set pin 7 as input and pin 1 as output TCB_init(); TCA0_init();
}
//loop count to shut off candle if on over an hourISR(TCA0_OVF_vect){ TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; timerACount++; if(timerACount>7){ timerACount=0;// PORTA.OUTTGL = PIN2_bm; //for debug sleepCount++; if(sleepCount> 3600){ //3600 is 1 hour sleepCount=0; gotosleep(); } }}
//flicker CandleISR(TCB0_INT_vect){ TCB0.INTFLAGS = TCB_CAPT_bm; /* Clear the interrupt flag */ PORTA.OUTTGL = PIN1_bm; /* Toggle Pa1 GPIO */ flickerCount++; if (flickerCount > randTime){ flickerCount=0; randNum = (rand() % 1000 )+1; randTime = (rand() % 440) +1; } TCB0.CCMP = randNum; //randomize top value }
//Wake or go to sleep, read pin6 from ComparatorISR(PORTA_PORT_vect){ // PORTA.INTFLAGS &= PIN7_bm ; PORTA.INTFLAGS = PORT_INT6_bm; // tested, works, got from iotn402.h // PORTA.OUTTGL = PIN1_bm; count++; if(count >= MAX){ // cli(); stateChange=1; count=0; if(!state){     //wake up: state=1; }else{     //go to sleep: state=0; PORTA.OUT &= ~PIN1_bm; _delay_ms(500); gotosleep(); } } if (!state){ gotosleep(); }}