ATtiny13a Fridge Alarm

Was in the process of designing my own fridge alarm from ATtiny85 when I saw Ralph Bacon take the challenge of making one from an ATtiny13. I contacted Ralph and picked on him about mentioning "Alexa" on his channel.. Because it my Alexa kept trying to order stuff he would say :) . But  I had to try this challenge. I  had some difficulty. I then tried his and still has some difficulty and with mixing the two I got it to work but I just chose a single tone.  Its been working now since February 2021.

Update June 2022:

This has worked so well I ended up doing a PCB from Oshpark and using this on any external door for my home. It works Great!!

https://oshpark.com/profiles/shermluge

UPDATE May 2023:

Ported to Microchip Studio:

works better and lower current


/*
  • Microchip studio port :)
 * ATtiny13a-Fridge-Alarm-sleep-final-v3_2.c * * PORTED: 6/3/2022 06:52:16 * just not fully tested. so far works on test bed. But not fully * needs more testing.. But getting close.. (4/29/23) needs alot of work UPDATE.. Think I have it :) Also added TinyUSB to profile for 1.2mhz.. After That its down from 25 uA to 18 uA 
 * TONE TESTING!!! * SLEEP TESTING!!! Sherm, new fridge alarm inspired from Ralph Bacon...
for attiny13 By sherm
trying at 1.2MHzwith MiniCore/MicroCore (MCUDude / Nerd Ralph)
Serial at 19200 baud.but very poor quality..
 2021-2-26  Tested and works as of 2021-2-27 Tested again on 2022-02-27 Use this one 2022-02-12
 MAJOR OVER HAUL:  2022-03-19    1) added sleep @ 6uAmps    2) major code over haul*/#define F_CPU 1200000UL#include <avr/io.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <util/delay.h>
// constants won't change. Used here to set a pin number:#define ledPin  PB4    #define buzzer  PB3#define door    PB2#define stealth PB1#define TX      PB0 //now is output for timer#define LOW 0#define HIGH 1//need to swap these because they are BACKWARDS, but need to correct other code (swapped 3/16/22)#define doorClosed 1  //pulled high#define doorOpen 0  //pulled low

//////////////////////////////////volatile uint8_t doorStatus = doorClosed;volatile uint8_t prevDoorStatus = doorClosed; //changed from doorOpenvolatile uint8_t WarnCount = 0;volatile uint8_t AlarmCount = 0;
// Generally, you should use "unsigned long" for variables that hold time// The value will quickly become too large for an int to storevolatile unsigned long currentMS = 0;        // will store last time LED was updated
// constants won't change:const int Second = 1000;           // interval at which to blink (milliseconds)const int ThreeSeconds = 3000;const int WarnTimeSeconds = 15000;const uint8_t MaxWarn = 8;const uint8_t MaxAlarm = 20;  
//functionsvoid beep();void doorClosedSound();void doorOpenSound();void sleepNow(void);
ISR(PCINT0_vect){//  cli();  //GIMSK &= ~(1<<PCIE); // clear Pin change interrupts  /*  _delay_ms(50);  //doorStatus = (PINB & (1 << PB2));  if(PINB & (1 << PB2)){ PORTB |= (1<<PB1);   doorStatus=doorClosed;  }else{ PORTB &= ~(1<<PB1);   doorStatus=doorOpen;  }*/   if(PINB & (1 << PB2)){ _delay_ms(50);   PORTB |= (1<<PB1);   doorStatus=doorClosed;   }else{   PORTB &= ~(1<<PB1);   doorStatus=doorOpen;   }
}
ISR(TIM0_COMPA_vect){ TCNT0 = 0;  //reset timer currentMS++;}
void initTimer(void){ TCCR0A |= (1<<COM0A0); TIMSK0 |= (1<<OCIE0A)|(1<<TOIE0); OCR0A = 145; //with CS01 this top is at 1khz TCCR0B |= (1<<WGM01)|(1<<FOC0A)|(1<<CS01);// DDRB = 0b00001111;// sei();}//void setup() {int main(){  // set the digital pin as output:  //pinMode(ledPin, OUTPUT);  //pinMode(buzzer, OUTPUT);  DDRB |= (1 << ledPin);  //set for output  DDRB |= (1 << buzzer);  //set for output  DDRB |= (1 << PB0)|(1<<PB1);  DDRB &= ~(1<< door); //set door to input  PORTB |= (1<< door);//set pull up.
  //to enable pull up, do after DDRB:  //DDRB &= ~_BV(pin); // Set pin as input  //PORTB |= _BV(pin); // Enable pullup resistors
  //Pin Change interrupt on door //PB2  PCMSK |= (1<<PCINT2); // Sets the Pin change interrupt mask, only (PCINT3) PB3 will trigger the PCINT once it is enabled before sleep  GIMSK |= (1<<PCIE); // Activate Pin change interrupts //rem by someone else not sherm  initTimer();  // SREG |= (1<<SREG_I); //Enables Interrupts globally after setup //already included in initTimer()  sei();  //pinMode(door, INPUT);  #ifdef DEBUG    // Note that any baud rate specified is ignored on the ATtiny13. See header above.   // Serial.begin();  #endif  beep();  //beep(50);  while(1){
    if (doorStatus != prevDoorStatus){          if(doorStatus == doorOpen){ //test sherm 2-28-22 //change to doorOpen!! BACKWARDS //fixed 3/16/22        doorOpenSound();      }else{        doorClosedSound();        _delay_ms(2000);        sleepNow();        AlarmCount=0;        WarnCount=0; currentMS=0;      }          prevDoorStatus=doorStatus; // currentMS=0;    }   if(PINB & (1 << PB2)){   PORTB |= (1<<PB1);   doorStatus=doorClosed;   }else{   PORTB &= ~(1<<PB1);   doorStatus=doorOpen;   }    if(doorStatus == doorOpen){   // BACKWARDS NEED TO CHANGE TO == OR CHANGE TO doorClosed //fixed 3/16/22      //Warn door is open every so many seconds.      if(WarnCount <= MaxWarn && currentMS >= WarnTimeSeconds){         // reset timer currentMS=0;        WarnCount++;        for(uint8_t i=0;i<=WarnCount;i=i+2){          //beep(60-(2*i));            beep();          }      }//if warn      //Alarm, beep every so many seconds      if(WarnCount >MaxWarn && currentMS >= ThreeSeconds){         beep();        // save the last time you blinked the LED currentMS=0;        AlarmCount++;      }//if alarm      //Max Alarm sound after so long on normal alarm.      if(AlarmCount >MaxAlarm && currentMS >= Second){         beep();        // Reset timer currentMS=0;      }//if alarm  MAX    }else{ //door closed: doorClosedSound(); //just unremmed sleepNow();    }  } }
void sleepNow(void){ DDRB = 0; PORTB = 0b11100111;
  //PCMSK |= (1<<PCINT2); // Sets the Pin change interrupt mask, only (PCINT3) PB3 will trigger the PCINT once it is enabled before sleep  GIMSK |= (1<<PCIE); // Activate Pin change interrupts //rem by someone else not sherm  //worked:   //  ADCSRA &= ~(1<<ADEN);                   // disable ADC - must be done before PRR  //  PRR     = 1<<PRADC;                     // shut down ADC   //sei(); // Enable global interrupts   set_sleep_mode(SLEEP_MODE_PWR_DOWN);  sleep_mode();  //sleep_cpu();//does not work  sleep_disable();      initTimer();      DDRB |= (1 << ledPin);  //set for output    DDRB |= (1 << buzzer);  //set for output    DDRB |= (1 << PB0)|(1<<PB1);    DDRB &= ~(1<< door); //set door to input    PORTB |= (1<< door);}
void doorOpenSound(){//  PORTB |= (1 << buzzer);      //  _delay_ms(10);//  PORTB &= ~(1 << buzzer);    //  _delay_ms(20);  PORTB |= (1 << buzzer);        _delay_ms(10);  PORTB &= ~(1 << buzzer);      _delay_ms(20);  PORTB |= (1 << buzzer);        _delay_ms(10);  PORTB &= ~(1 << buzzer);    
  PORTB |= (1 << ledPin);        _delay_ms(80);  PORTB &= ~(1 << ledPin);    }void doorClosedSound(){  //beep  PORTB |= (1 << buzzer);        _delay_ms(20);  PORTB &= ~(1 << buzzer);      _delay_ms(200);  PORTB |= (1 << buzzer);        _delay_ms(20);  PORTB &= ~(1 << buzzer);      _delay_ms(400);  PORTB |= (1 << buzzer);        _delay_ms(20);  PORTB &= ~(1 << buzzer);      //led flash  PORTB |= (1 << ledPin);        _delay_ms(80);  PORTB &= ~(1 << ledPin);    }void beep(void){  //beep  PORTB |= (1 << buzzer);       _delay_ms(50);  PORTB &= ~(1 << buzzer);      //led  PORTB |= (1 << ledPin);       _delay_ms(40);  PORTB &= ~(1 << ledPin);    }

/*

Arduino version: 

Sherm, new fridge alarm inspired from Ralph Bacon...


for ATtiny13 


trying at 1.2MHz

with MiniCore/MicroCore (MCUDude / Nerd Ralph)


Serial at 19200 baud.


 2021-2-26 

 Tested and works as of 2021-2-27

*/

#include <avr/io.h>


#define DEBUG


// constants won't change. Used here to set a pin number:

#define ledPin PB4    

#define buzzer PB3

#define door   PB2

#define stealth     PB1

#define TX     PB0


// Variables will change:

int ledState = LOW;             // ledState used to set the LED

bool doorClosed = 0; //pulled to ground

bool doorOpen = 1; //high

bool doorStatus = doorClosed;

bool prevDoorStatus = doorOpen;

uint8_t WarnCount = 0;

uint8_t AlarmCount = 0;


// Generally, you should use "unsigned long" for variables that hold time

// The value will quickly become too large for an int to store

unsigned long previousMillis = 0;        // will store last time LED was updated



// constants won't change:

const int Second = 1000;           // interval at which to blink (milliseconds)

const int ThreeSeconds = 3000;

const int WarnTimeSeconds = 15000;

const long Minute = 60000;

const long FiveMinutes =240000;

const uint8_t MaxWarn = 8;

const uint8_t MaxAlarm = 20;  



//functions

bool isDoorOpen();

void beep();

bool stealthMode();

void doorClosedSound();

void doorOpenSound();


void setup() {

  // set the digital pin as output:

  //pinMode(ledPin, OUTPUT);

  //pinMode(buzzer, OUTPUT);

  DDRB |= (1 << ledPin);  //set for output

  DDRB |= (1 << buzzer);  //set for output

  //pinMode(door, INPUT);

  #ifdef DEBUG

    // Note that any baud rate specified is ignored on the ATtiny13. See header above.

    Serial.begin();

  #endif


  beep();

  beep();

}


void loop() {

  // here is where you'd put code that needs to be running all the time.


  // check to see if it's time to blink the LED; that is, if the difference

  // between the current time and last time you blinked the LED is bigger than

  // the interval at which you want to blink the LED.

  

  if(isDoorOpen()==doorOpen){

    unsigned long currentMillis = millis();

    #ifdef DEBUG

      if(!((currentMillis-previousMillis)%100)){

      //  Serial.print(currentMillis-previousMillis);

        Serial.println(F("  in loop"));

      }

    #endif

    //Warn door is open every so many seconds.

    if(WarnCount <= MaxWarn && currentMillis - previousMillis >= WarnTimeSeconds){ 

      #ifdef DEBUG

        Serial.println(F("Warn"));

      #endif

      

             // save the last time you blinked the LED

      previousMillis = currentMillis;

      //ledState=ledState ? HIGH:LOW;

    

      WarnCount++;

      for(uint8_t i=0;i<=WarnCount;i=i+2){

        beep();  

      }

    }//if warn

    

    //Alarm, beep every so many seconds

    if(WarnCount >MaxWarn && currentMillis - previousMillis >= ThreeSeconds){ 

      #ifdef DEBUG

        Serial.println(F("Alarm"));

      #endif

      beep();

      // save the last time you blinked the LED

      previousMillis = currentMillis;

      AlarmCount++;

      //doorIsOpen = doorStatus ? true : false;

    }//if alarm


    //Max Alarm sound after so long on normal alarm.

    if(AlarmCount >MaxAlarm && currentMillis - previousMillis >= Second){ 

      #ifdef DEBUG

        //Serial.println(F("Alarm MAX"));

      #endif

      beep();

      // save the last time you blinked the LED

      previousMillis = currentMillis;

      //doorIsOpen = doorStatus ? true : false;

    }//if alarm  MAX

  } //isDoorOpen()

}


bool isDoorOpen(){

  doorStatus=digitalRead(door);

  if (doorStatus!=prevDoorStatus){

    if(doorStatus==doorOpen){

      #ifdef DEBUG

        Serial.println(F("Door Open"));

      #endif

      doorOpenSound();

    }else{

      #ifdef DEBUG

        Serial.println(F("Door Closed"));

      #endif

      doorClosedSound();

      AlarmCount=0;

      WarnCount=0;

    }    

    prevDoorStatus=doorStatus;

    previousMillis=millis();

  }

  _delay_ms(20);

  return doorStatus;

}


bool stealthMode(){

  return digitalRead(stealth);

}


void doorOpenSound(){

  if(!stealthMode()){

    PORTB |= (1 << buzzer);      //replaces digitalWrite(buzzer, HIGH);

    delay(10);

    PORTB &= ~(1 << buzzer);    //replaces digitalWrite(buzzer, LOW);

    delay(20);

    PORTB |= (1 << buzzer);      

    delay(10);

    PORTB &= ~(1 << buzzer);    

    delay(20);

    PORTB |= (1 << buzzer);      

    delay(10);

    PORTB &= ~(1 << buzzer);    

  }

  PORTB |= (1 << ledPin);      

  delay(80);

  PORTB &= ~(1 << ledPin);    

}

void doorClosedSound(){

  if(!stealthMode()){

    PORTB |= (1 << buzzer);      

    delay(20);

    PORTB &= ~(1 << buzzer);    

    delay(150);

    PORTB |= (1 << buzzer);      

    delay(10);

    PORTB &= ~(1 << buzzer);    

  }

  PORTB |= (1 << ledPin);      

  delay(80);

  PORTB &= ~(1 << ledPin);    

}

void beep(){

  if(!stealthMode()||AlarmCount >MaxAlarm){

    PORTB |= (1 << buzzer);      

    delay(20);

    PORTB &= ~(1 << buzzer);    

  }

  PORTB |= (1 << ledPin);      

  delay(80);

  PORTB &= ~(1 << ledPin);    

}



Posted this in November so its been working solid for  over 8 months now and no issues..