ATtiny10 Pumpkin guts
I've made Pumpkin guts for upcoming Halloween. Even though in the past I've made them from ATtiny85, then the ATtiny13. I wanted even smaller, so now I made one out of ATtiny10. This time I've used the hardware control for pins PB0-PB1 for the eyes and PB2 for the candle with a semi simulated candle. Put in a Skull to test out, but will be in a Pumpkin on Halloween.
Uses comparator with LDR circuit to power on and off during light and dark.
Uses sleep after being on for about 30 seconds, sleeps 4 seconds
UV resin to water proof the lights and LDR
Actual size of ATtiny10.
20220516_195751.mp4
Programed in Microchip Studio:
/* * ATtiny10-pumkin-lights-pwm-inv-non-inv.c * * Created: 5/14/2022 19:51:11 * * Great for Halloween pumpkin * the 2 eye's are hardware driven inverting/non inverting PWM * the candle is simulated by timer count offsets * * PB0 and PB1 are eyes (led's) * PB2 is Candle flicker led's * * initially Created: 5/13/2022 19:47:17 * Cleaned up code on 6/02/2022 * * Author : Sherman Stebbins */ #define F_CPU 1000000UL#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <util/delay.h>
#define UP 1#define DOWN 0#define MAX 450#define MAXLOOPS 8
volatile uint16_t count = 0; //count for hardware controled LED's PB0-PB1volatile uint16_t singleLedCount = 0; //count for PB2 candle flickervolatile uint8_t direction = UP; //default to ramping up or Counting upvolatile uint8_t sleepCount = 0; //track how many hardward ramp up and down then sleepvolatile uint8_t sleepyTime = 0; //sleep time if 1void initTimer(void); //set up timer for PB0-PB1
int main(void){ CCP=0XD8; //yawn.. unprotect CLKMSR=0x00; // 0x01 128khz tried the slower speed and it worked, but not near as smooth. //0x03 prescale 8 is default. But I chose for 0x08 prescale 256 and slowed enough yet still smooth fading CLKPSR=0x08; DDRB=7; if(RSTFLR & PORF){ PORTB |= (1<<PB2); _delay_ms(2000);
} if ((RSTFLR & (1 << EXTRF)) != 0) { RSTFLR = RSTFLR & ~(1 << EXTRF); //for attiny10 PORTB |= (1<<PB2); _delay_ms(1500); } if ((RSTFLR & (1 << WDRF)) != 0) { //initTimer(); //RSTFLR = RSTFLR & ~(1 << WDRF); //for attiny10 RSTFLR &= ~(1<<WDRF); CCP=0xD8; //NOT having this really fucked with me!! and messed up Timers on restart WDTCSR &= ~(1<<WDE); //ramp up candle flicker on wake up //DDRB = 0b00000111; //don't know why I changed it.. DDRB=7; for(uint8_t i=0; i<31;i++){ PORTB ^= (1<<PB2); for(uint8_t j=0; j<i*2;j++){ _delay_ms(1); } } } //Set up and start timer for PWM LED's initTimer(); while (1) { //update timers limits OCR0A=count; OCR0B=count; if(sleepyTime){ //if sleepy time, go to sleep sleepyTime=0; WDTCSR |= (1<<WDP3)|(1<<WDP0)|(1<<WDE);//|(1<<WDP0); //set for 8 sec (3 & 0) PORTB &= ~(1<<PB0)|(1<<PB1)|(1<<PB2); DDRB=0; sei(); sleep_enable(); sleep_cpu(); TIFR0=0; } }}
void initTimer(void){ set_sleep_mode (SLEEP_MODE_PWR_DOWN); DDRB = 7; //Output on PB0 and PB1 TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << COM0A0) | (1 << WGM01); //Toggle OC0A and OC0B on compare match TCCR0B = (1<<CS01) | (1 << WGM02)| (1 << WGM03); //Clear on compare, use unscaled clock OCR0A = 390;//(1000000L /40000 / 2) - 1; messing around with different frequency's OCR0B = 390;//(1000000L /40000 / 2) - 1; TIMSK0 |= (1<<TOIE0); //turn on over flow interrupt ICR0=MAX; sei();
}
ISR(TIM0_OVF_vect){ //controls inverting/non inverting led's if(direction==UP){ if(++count>MAX){ count=MAX-1; direction=DOWN; if(++sleepCount>MAXLOOPS){ sleepCount=0; sleepyTime=1; } } }else{ if(--count==0){ count=1; direction=UP; } } //controls candle flicker if((singleLedCount+=290)%count/7){ singleLedCount=0; PORTB ^= (1<<PB2); }}
ISR(WDT_vect){}
#define UP 1#define DOWN 0#define MAX 450#define MAXLOOPS 8
volatile uint16_t count = 0; //count for hardware controled LED's PB0-PB1volatile uint16_t singleLedCount = 0; //count for PB2 candle flickervolatile uint8_t direction = UP; //default to ramping up or Counting upvolatile uint8_t sleepCount = 0; //track how many hardward ramp up and down then sleepvolatile uint8_t sleepyTime = 0; //sleep time if 1void initTimer(void); //set up timer for PB0-PB1
int main(void){ CCP=0XD8; //yawn.. unprotect CLKMSR=0x00; // 0x01 128khz tried the slower speed and it worked, but not near as smooth. //0x03 prescale 8 is default. But I chose for 0x08 prescale 256 and slowed enough yet still smooth fading CLKPSR=0x08; DDRB=7; if(RSTFLR & PORF){ PORTB |= (1<<PB2); _delay_ms(2000);
} if ((RSTFLR & (1 << EXTRF)) != 0) { RSTFLR = RSTFLR & ~(1 << EXTRF); //for attiny10 PORTB |= (1<<PB2); _delay_ms(1500); } if ((RSTFLR & (1 << WDRF)) != 0) { //initTimer(); //RSTFLR = RSTFLR & ~(1 << WDRF); //for attiny10 RSTFLR &= ~(1<<WDRF); CCP=0xD8; //NOT having this really fucked with me!! and messed up Timers on restart WDTCSR &= ~(1<<WDE); //ramp up candle flicker on wake up //DDRB = 0b00000111; //don't know why I changed it.. DDRB=7; for(uint8_t i=0; i<31;i++){ PORTB ^= (1<<PB2); for(uint8_t j=0; j<i*2;j++){ _delay_ms(1); } } } //Set up and start timer for PWM LED's initTimer(); while (1) { //update timers limits OCR0A=count; OCR0B=count; if(sleepyTime){ //if sleepy time, go to sleep sleepyTime=0; WDTCSR |= (1<<WDP3)|(1<<WDP0)|(1<<WDE);//|(1<<WDP0); //set for 8 sec (3 & 0) PORTB &= ~(1<<PB0)|(1<<PB1)|(1<<PB2); DDRB=0; sei(); sleep_enable(); sleep_cpu(); TIFR0=0; } }}
void initTimer(void){ set_sleep_mode (SLEEP_MODE_PWR_DOWN); DDRB = 7; //Output on PB0 and PB1 TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << COM0A0) | (1 << WGM01); //Toggle OC0A and OC0B on compare match TCCR0B = (1<<CS01) | (1 << WGM02)| (1 << WGM03); //Clear on compare, use unscaled clock OCR0A = 390;//(1000000L /40000 / 2) - 1; messing around with different frequency's OCR0B = 390;//(1000000L /40000 / 2) - 1; TIMSK0 |= (1<<TOIE0); //turn on over flow interrupt ICR0=MAX; sei();
}
ISR(TIM0_OVF_vect){ //controls inverting/non inverting led's if(direction==UP){ if(++count>MAX){ count=MAX-1; direction=DOWN; if(++sleepCount>MAXLOOPS){ sleepCount=0; sleepyTime=1; } } }else{ if(--count==0){ count=1; direction=UP; } } //controls candle flicker if((singleLedCount+=290)%count/7){ singleLedCount=0; PORTB ^= (1<<PB2); }}
ISR(WDT_vect){}