/* * 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(); }}