ATtiny10 Christmas Star

On the left is watching full tree, on the right is when it sleeps for about 2 seconds each cycle to save battery.

ATtiny10 how I programmed Attiny10

/*

* ATtiny10-PWM-Christmas_Star-WDT.c

*

* UPDated: 6/2/2022 17:41:01

* Cleaned up code.

*/

/*

* PWM Star v1.1


* Sherman Stebbins

* Created: 2021-10-23

*

* Attiny10

; +====+

; SCK -> PB0 |* | PB3 (RESET)

; GND | | Vcc

LEDs MOSI -> PB1 | | PB2

; +====+

*/

#ifndef F_CPU

#define F_CPU 1000000UL

#endif

#include <avr/interrupt.h>

#include <util/delay.h>


//volatile unsigned char count __attribute__((section(".noinit"))); // Not cleared on RESET


volatile uint16_t loopCount=0;

volatile uint16_t pwmCount=0;

volatile uint8_t upDown=1;

volatile uint8_t hbDir=1;

volatile uint16_t heartBeatCount=0;

const volatile uint8_t up=1;

const volatile uint8_t down=0;


void hearBeat(void);

void my_delay_ms(uint16_t n);

void goToSleep(void);



int main(void){

//This restores the PWM properly!!!!

RSTFLR &= ~(1<<WDRF);

CCP=0xD8;

WDTCSR &= ~(1<<WDE); //must have or won't sleep

WDTCSR &= ~(1<<WDIE);



DDRB = 0b00000010;


//Sherm!! Fix!! WGM02 is not in TCCR0A!!

TCCR0A = (1<<WGM02)|(1<<WGM01)|(1<<WGM00); //15 1111 Fast PWM OCR0A TOP TOP //worked


OCR0A = 1;//976; //7812; //worked

TIMSK0 = (1<<OCIE0A);//time mask when OCR0A is matched, interrupt //worked

sei();

TCCR0B |= (1<<CS01); //set prescaler to /8 and start

while(1){

}

}


ISR(TIM0_COMPA_vect){

hearBeat();

}





void my_delay_ms(uint16_t n){

while(n--) {

_delay_ms(1);

}

}


void goToSleep(void)

{

SMCR |= (1<<2); //SMCR.SM bit 2 (010) Power-down

SMCR |= (1<<0); //SMCR.SE =1; SET JUST before Sleep starts

sei() ; //set Global Interrupt Enable - if you don't add this, it will not restart.

//__asm__ __volatile__("sleep") ; //enter sleep, waiting for interrupt -- This worked great!!!

WDTCSR = 0b01100110; //1000 4 sec 0111 2 sec -- sherm recheck this line!! why 16ms?

__asm__ __volatile__ ( "sleep" "\n\t" :: ); //Sleep instruction to put controller to sleep (found this syntax)

}


void hearBeat(void){

//long beat getting brighter

if(upDown==1){

pwmCount++;

OCR0A=pwmCount;

if(pwmCount>80+(heartBeatCount*2)){

upDown=0;

if(hbDir==down){

heartBeatCount--;

}else{

heartBeatCount++;

}

if (heartBeatCount>40){ //faster

hbDir=down;

}

if (heartBeatCount<1){ //slower

hbDir=up;

}

}

//long beat getting dimmer

}else if(upDown==0){

pwmCount--;

OCR0A=pwmCount;

if(pwmCount<=1){

upDown=2;


if(hbDir==down){

heartBeatCount--;

}else{

heartBeatCount++;

}

if (heartBeatCount>40){

hbDir=down;

}

if (heartBeatCount<1){

hbDir=up;

}

}

//short beat getting brighter

}else if(upDown==2){

pwmCount=pwmCount+4;

OCR0A=pwmCount;

if(pwmCount>80+(heartBeatCount*2)){

upDown=3;

if(hbDir==down){

heartBeatCount-=4;

}else{

heartBeatCount+=4;

}

if (heartBeatCount>40){

hbDir=down;

}

if (heartBeatCount<1){

hbDir=up;

}

}

//short beat getting dimmer

}else if(upDown==3){

pwmCount=pwmCount-3;

OCR0A=pwmCount;

if(pwmCount<=3){

upDown=1;

if(hbDir==down){

heartBeatCount-=4;

}else{

heartBeatCount+=4;

}

if (heartBeatCount>40){

hbDir=down;

}

if (heartBeatCount<1){

hbDir=up;

}

loopCount++; //count loops for beats to sleep

}

}

PORTB ^= (1<<PB1);

if(loopCount>6){ //90 //4 works best //8 locks up to bright light after restart

loopCount=0;

DDRB = 0;

goToSleep();

}

}