Last active
March 22, 2020 17:42
-
-
Save nerdralph/1b99c1b683024e8f305dc06838200208 to your computer and use it in GitHub Desktop.
cleaned up fridge door alarm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Fridge Door Alarm for the ATTiny13[A] | |
* | |
* Functionality: | |
* | |
* Door opens, door open chime. | |
* After 60 seconds, door-open warning beep. | |
* If door still open, warning beeps every 30 seconds. | |
* After 5 minutes, continous alarm signal. | |
* Door closes, door close chime. | |
* If Silent Running pressed, no door chimes for ONE operation. | |
* | |
* Using MiniCore (MCUDude / Nerd Ralph) 1.05 | |
* | |
* Ralph Bacon January 2020 | |
* optimized & cleaned up by Ralph Doncaster March 2020 | |
*/ | |
/* | |
* ATTiny13A pins used as follows | |
* | |
* - pin 8 VCC | |
* - pin 4 GND | |
* PB5 pin 1 Reset | |
* PB0 pin 5 Buzzer | |
* PB1 pin 6 Tx Serial Output | |
* PB2 pin 7 door contact | |
* PB3 pin 2 Touch Sensor | |
* PB4 pin 3 Silent Running LED | |
* | |
*/ | |
// Makes digitalWrite/Read smaller (but less safe. eg PWM) | |
#ifdef SAFEMODE | |
#undef SAFEMODE | |
#warning SAFEMODE undefined here | |
#endif | |
// Allows some limited debugging statements | |
#undef ISDEBUG | |
#include "Arduino.h" | |
#include <avr/io.h> | |
//#include <CapacitiveSensor.h> | |
#include <avr/wdt.h> | |
//#ifdef ISDEBUG | |
//#include <BasicSerial.h> | |
//#endif | |
// Prevents the expectation of a fixed value delay | |
//#define __DELAY_BACKWARD_COMPATIBLE__ | |
#include <util/delay.h> | |
// Silent running - no door open/close beeps | |
//bool noNoise = false; | |
#define BUZZER_PIN PB0 | |
#define TOUCH_PAD 3 | |
// Inintially (on power up) we assume door is closed | |
//bool doorIsOpen = false; | |
//bool doorWasClosed = true; | |
bool doorWasClosed; // initialized to true in main | |
// The opposite of above but easier to read | |
#define doorIsClosed !doorIsOpen | |
#define doorWasOpen !doorWasClosed | |
// Door reed switch on interrupt capable pin | |
#define doorRelayPin PB2 | |
#define LEDpin PB4 | |
// General Serial Print class (type independent) for debugging | |
//#ifdef ISDEBUG | |
//template<typename T> | |
//void debugPrint(T printMe) { | |
// Serial.println(printMe); | |
//} | |
//#endif | |
//Forward declarations not needed - Arduino auto generates | |
void doBeep(uint16_t duration); | |
static void tone(uint8_t note); | |
static void killTone(); | |
// void doorOpenSound(); | |
//void doorClose(); | |
//void readTouchPad(); | |
// returns true for open | |
inline bool doorStatus() | |
{ | |
return !!(PINB & _BV(doorRelayPin)); | |
} | |
// ------------------------------------------------------------- | |
// SETUP SETUP SETUP SETUP SETUP | |
// ------------------------------------------------------------- | |
int main(void) { | |
// Because we might be starting here due to WD TimeOut | |
// reset and disable the WDT | |
wdt_reset(); | |
MCUSR = 0; | |
wdt_disable(); | |
#ifdef ISDEBUG | |
Serial.println(F("Go")); | |
#endif | |
bool doorWasClosed = true; | |
// set Data Direction Register | |
//pinMode(BUZZER_PIN, OUTPUT); | |
DDRB |= _BV(BUZZER_PIN); | |
// Set Buzzer Pin PB0 LOW - already 0 on reset | |
// PORTB = 0b00000000; // all pins LOW | |
//digitalWrite(BUZZER_PIN, LOW); - already 0 | |
// PORTB = ~_BV(BUZZER_PIN); | |
// LED pin | |
DDRB |= _BV(LEDpin); // OUTPUT | |
// PORTB &= ~_BV(LEDpin); // LOW on reset | |
// Touch Pad INPUT PULLUP | |
// pinMode(TOUCH_PAD, INPUT_PULLUP); | |
// DDRB &= ~_BV(TOUCH_PAD); //INPUT... | |
PORTB |= _BV(TOUCH_PAD); // ...PULLUP | |
// Door relay must be held high (brought to ground when opened) | |
// pinMode(doorRelayPin, INPUT_PULLUP); | |
//DDRB &= ~_BV(doorRelayPin); // Set pin as input - reset state | |
PORTB |= _BV(doorRelayPin); // Enable pullup resistors | |
//Timer/Counter Control Register TCCR0A | |
//TCCR0A |= (1 << WGM01); // set timer mode to Fast PWM | |
//TCCR0A |= (1 << COM0A0); // connect PWM pin to Channel A of Timer0 | |
TCCR0A = (1 << WGM01) |(1 << COM0A0); | |
// Set up the door interrupt, on pin change (takes 250 bytes) | |
//attachInterrupt(digitalPinToInterrupt(doorRelayPin), getDoorState, CHANGE); | |
bool noNoise = false; | |
// All OK | |
if (!noNoise) doorOpenSound(); | |
// Start the WatchDog Timer WDT for 8 second interval, | |
// The WDT uses a separate, internal 128KHz oscillator | |
// and will give an interrupt or reset the system. An | |
// interrupt is usually used to wake from sleep mode, but | |
// we want a system reset here. | |
wdt_enable(WDTO_8S); // Note: this is all assembler code | |
// For reset (not interrupt) clear bit 6, enable bit 3 | |
WDTCR |= ~_BV(WDTIE) | _BV(WDE); | |
// initialize variables used in loop | |
bool doorIsOpen = false; | |
//------------------------------------------------------------- | |
// LOOP LOOP LOOP LOOP LOOP | |
// ------------------------------------------------------------- | |
while (1) { | |
wdt_reset(); | |
// Check door | |
doorIsOpen = doorStatus(); | |
// Silent running? | |
noNoise = readTouchPad(noNoise); | |
// When the door opens (ISR triggered) things happen. Until hten, nothing. | |
if (doorIsOpen && doorWasClosed) { | |
#ifdef ISDEBUG | |
Serial.println("Open"); | |
#endif | |
// Reset this flag ready for door to be closed | |
doorWasClosed = false; | |
// Sound door opening chime | |
if (!noNoise) doorOpenSound(); | |
// Beep every X seconds (eg 30 seconds) | |
// If door is closed during this time, exit. | |
unsigned char beepCnt = 0; | |
for (auto cnt = 255; cnt; cnt--) { | |
wdt_reset(); | |
// Break out of this loop if door is now shut | |
doorIsOpen = doorStatus(); | |
if (doorIsClosed) | |
break; | |
// Every X seconds beep a warning | |
// first warn is silent allowing 60 seconds initially | |
// before beep then at 30 secs thereafter | |
// if (cnt % 30 == 0) { | |
// cnt mod 32 instead of 30 | |
if ((cnt & 0xE0) == 0) { | |
#ifdef ISDEBUG | |
Serial.println("Warn"); | |
#endif | |
for (uint8_t cnt2 = 0; cnt2 < beepCnt; cnt2++) { | |
doBeep(300); | |
delay(50); | |
} | |
// Exit if door now closed | |
doorIsOpen = doorStatus(); | |
if (doorIsClosed) | |
break; | |
// Increment number of beeps per warning | |
beepCnt++; | |
} | |
// Delay for 1 second but break out as soon as door is closed | |
for (uint8_t cnt1s = 10; cnt1s; cnt1s--) { | |
delay(100); // Saves 2 bytes | |
doorIsOpen = doorStatus(); | |
if (doorIsClosed) | |
break; | |
} | |
} | |
// We're still here! Door is still open! Alarm! Alarm! | |
while (doorIsOpen) { | |
#ifdef ISDEBUG | |
Serial.println("Alarm"); | |
#endif | |
doBeep(500); | |
delay(250); | |
doorIsOpen = doorStatus(); | |
} | |
} | |
// When the door closes do some different stuff | |
if (doorIsClosed && doorWasOpen) { | |
#ifdef ISDEBUG | |
Serial.println("Shut"); | |
#endif | |
// Reset this flag ready for door to be closed | |
doorWasClosed = true; | |
// Sound door closing chime | |
if (!noNoise) doorCloseSound(); | |
// Turn off Silent Door LED | |
PORTB &= ~_BV(LEDpin); | |
// digitalWrite(ledPin, LOW); | |
// Reset everything ready for the next door opening event | |
doorIsOpen = false; | |
noNoise = false; | |
} | |
} | |
} | |
// Get touch signal if we haven't already touched | |
// return noNoise new state | |
bool readTouchPad(bool silent) { | |
// stop all tones | |
killTone(); | |
if (silent == false) { | |
if (digitalRead(TOUCH_PAD) == LOW) { | |
#ifdef ISDEBUG | |
Serial.println("Touch"); | |
#endif | |
// Set the flag so that no door beeps happen | |
silent = true; | |
// Light the LED | |
//digitalWrite(pinLED, HIGH); | |
PORTB |= _BV(LEDpin); | |
} | |
} | |
return silent; | |
} | |
// Is door open or closed? | |
/* | |
void | |
doorStatus() | |
{ | |
// As we poll the door status often, reset WDT here | |
wdt_reset(); | |
//return (digitalRead(doorRelayPin)); | |
uint8_t doorStatus = !!(PINB & _BV(doorRelayPin)); | |
doorIsOpen = doorStatus ? true : false; | |
} | |
*/ | |
// Single reminder beep | |
void doBeep(uint16_t duration) { | |
tone(23); | |
delay(duration); | |
killTone(); | |
} | |
// Door Open Sound | |
void doorOpenSound() { | |
// Door opening sound | |
//if (!noNoise) { | |
for (uint8_t j = 24; j > 17; j--) { | |
tone(j); | |
delay(30); | |
} | |
//} | |
killTone(); | |
} | |
// Door Closing sound | |
void doorCloseSound() { | |
//if (!noNoise) { | |
for (uint8_t j = 17; j < 25; j++) { | |
tone(j); | |
delay(30); | |
//} | |
} | |
killTone(); | |
} | |
// simple PWM tone generator - thanks to Lucasz | |
static void tone(uint8_t note) { | |
// Fixed octave | |
TCCR0B = (TCCR0B & ~((1 << CS02) | (1 << CS01) | (1 << CS00))) | _BV(CS01); | |
// Use notes from 24 to 18 (highest) | |
OCR0A = note - 1; | |
} | |
// Stop any sound | |
static void killTone(void) { | |
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00)); // stop the timer | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment