Attiny10 Heart Beat
Attiny10 Heartbeat I made for the wife.. with two modes. Sleeps at .1ua after displaying for about 2 minutes in mode one (were it beats like a heartbeat with PWM at low current) then in mode 2 its about 1 minute of Morse code. Its a total mistreatment of interrupt and reset.. but it works..
/*
* PWM Heartbeat
* Sherman Stebbins
* 2021-10-23
*
* Attiny10
; +====+
; SCK -> PB0 |* | PB3 (RESET)
; GND | | Vcc
; MOSI -> PB1 | | PB2
; +====+
convert to binary sort of:
..-. ..- -.-. -.- / -- .
*/
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#include <avr/interrupt.h>
#include <util/delay.h>
#define EXT_RESET (1 << EXTRF)
#define dashT 32000
#define dotT 15000
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 bool hbDir=1;
volatile uint16_t heartBeatCount=0;
const volatile bool up=1;
const volatile bool down=0;
//volatile long dtyCycl = 0;
int main(void){
if ((RSTFLR & EXT_RESET) != 0) {
//if ((RSTFLR & 1) != EXT_RESET) {
// If External RESET then increment count and output to pins
RSTFLR = RSTFLR & ~EXT_RESET;
//MCUSR = MCUSR & ~EXT_RESET;
//PORTB = ++count;
count++;
} else {
// Else, set count to zero and output to pins
count = 0;
}
if (count>1){
count=0;
}
//DDRB = 0x01; //set pb0 output
DDRB |= (1<<0) | (1<<1);
//TCCR0A = (1<<WGM02)|(1<<WGM01); //14 1110 Fast PWM ICR0 TOP TOP
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, intrerupt //worked
sei();
TCCR0B |= (1<<CS01); //set prescaler to /8 and start
//TCCR0B |= (1<<CS02); //set prescaler to /256 and start
//TCCR0B |= (1<<CS01)|(1<<CS00); //set prescaler to /64 and start
//TCCR0B |= (1<<CS00); //set prescaler to /1 and start
while(1){
}
}
ISR(TIM0_COMPA_vect){
switch(count){
case 0:
hearBeat();
break;
case 1:
morseCode();
break;
default:
hearBeat();
break;
}
}
void morseCode(void){
// ..-. ..- -.-. -.- / -- .
dot();
dot();
dash();
dot();
my_delay_ms(600);
dot();
dot();
dash();
my_delay_ms(600);
dash();
dot();
dash();
dot();
my_delay_ms(600);
dash();
dot();
dash();
my_delay_ms(1000);
dash();
dash();
my_delay_ms(600);
dot();
my_delay_ms(3000);
loopCount++;
if(loopCount>3){
loopCount=0;
DDRB = 0;
PORTB = 0;
goToSleep();
}
}
void dot(void){
PORTB |= (1<<PB1);
my_delay_ms(150);
PORTB &= ~(1<<PB1);
my_delay_ms(200);
}
void dash(void){
PORTB |= (1<<PB1);
my_delay_ms(500);
PORTB &= ~(1<<PB1);
my_delay_ms(500);
}
void my_delay_ms(uint16_t n){
while(n--) {
_delay_ms(1);
}
}
void goToSleep(void)
{
//make all pins inputs with pullups enabled
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
__asm__ __volatile__("sleep") ; //enter sleep, waiting for interrupt -- This worked great!!!
}
void hearBeat(void){
//long beat getting brighter
if(upDown==1){
pwmCount++;
OCR0A=pwmCount;
if(pwmCount>40+(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>40+(heartBeatCount*2)){
upDown=3;
if(hbDir==down){
heartBeatCount--;
}else{
heartBeatCount++;
}
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--;
}else{
heartBeatCount++;
}
if (heartBeatCount>40){
hbDir=down;
}
if (heartBeatCount<1){
hbDir=up;
}
loopCount++; //count loops for beats to sleep
}
}
PORTB ^= (1<<PB1);
//after so many beats, go to sleep
if(loopCount>90){
loopCount=0;
DDRB = 0;
PORTB = 0;
goToSleep();
}
}