//######### ATtiny25 #########//
// ===================================================================================
// Project: AirWick-Attiny25 - Air Freshener with Light Sensor and pre-configurable
// Work Period Settings
// Version: v1.2
// Year: 2023
// Author: Jurko-S
// Github: https://github.com/...
// EasyEDA: https://easyeda.com/...
// License: http://creativecommons.org/licenses/by-sa/3.0/
// ===================================================================================
//
// Description:
// ------------
// ###
// Wiring:7
// -------
// +-\/-+
// --- A0 (D5) PB5 1|° |8 Vcc
// DC Motor+-- A3 (D3) PB3 2| |7 PB2 (D2) A1 --- Button 1
// Button 3--- A2 (D4) PB4 3| |6 PB1 (D1) ------ Button 2
// GND 4| |5 PB0 (D0) ------ Button 4
// +----+
//
// Compilation Settings:
// ---------------------
// Controller: ATtiny 25, ATtiny45 or ATtiny85
// Core: ATTinyCore
// Clockspeed: 1 MHz internal
//
// Don't forget to "Burn bootloader"!
// ### Libraries for Power Saving ### //
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off)
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC
// ### Pin Definitions ### //
#define MOTOR_PIN 3
#define BTN1_PIN 2 // !!!!For testing purposes use #define BTN1_PIN 0
#define BTN2_PIN 1
#define BTN3_PIN 4
#define BTN4_PIN 0
// ### Mode Interval Settings ### //
uint32_t mainTimer, myTimer;
// In Seconds
#define MODE1_INT 30 // 30min 30 * 60; 1800
#define MODE2_INT 60 // 60min 60 * 60; 3600
#define MODE3_INT 120 // 90min 90 * 60; 5400
int mode = 0;
bool button1Pressed = false;
bool button2Pressed = false;
bool button3Pressed = false;
bool button4Pressed = false;
void setup() {
pinMode(MOTOR_PIN, OUTPUT);
pinMode(BTN1_PIN, INPUT_PULLUP);
pinMode(BTN2_PIN, INPUT_PULLUP);
pinMode(BTN3_PIN, INPUT_PULLUP);
pinMode(BTN4_PIN, INPUT_PULLUP);
// ### Power Saving ### //
adc_disable();
wdt_reset(); // Watchdog initialization
wdt_enable(WDTO_1S); // Enable Watchdog
// Watchdog Period // 15MS, 30MS, 60MS, 120MS, 250MS, 500MS, 1S, 2S, 4S, 8S
WDTCR |= _BV(WDIE); // Enable Watchdog Interrupts. Reset will be otherwise
sei(); // Enable Interrupts
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Max Sleep
}
void loop() {
mainTimer++;
// ### Check buttons' states ### //
if (digitalRead(BTN1_PIN) == HIGH && digitalRead(BTN2_PIN) == HIGH && digitalRead(BTN3_PIN) == HIGH) {
mode = 0;
button1Pressed = false; // Buttons are inverse!!!
button2Pressed = false;
button3Pressed = false;
} else if (digitalRead(BTN1_PIN) == LOW && digitalRead(BTN2_PIN) == HIGH && digitalRead(BTN3_PIN) == HIGH) {
mode = 1;
button1Pressed = true;
button2Pressed = false;
button3Pressed = false;
} else if (digitalRead(BTN1_PIN) == HIGH && digitalRead(BTN2_PIN) == LOW && digitalRead(BTN3_PIN) == HIGH) {
mode = 2;
button1Pressed = false;
button2Pressed = true;
button3Pressed = false;
} else if (digitalRead(BTN1_PIN) == HIGH && digitalRead(BTN2_PIN) == HIGH && digitalRead(BTN3_PIN) == LOW) {
mode = 3;
button1Pressed = false;
button2Pressed = false;
button3Pressed = true;
}
// ### Enable motor based on mode and light sensor value ### //
adc_enable(); // Enable ADC to read value from Light Sensor
// At first: check button position and check if it's day time
if (mode != 0) {
if ((long)mainTimer - myTimer > getInterval()) { // Then check for period
delay(5000);
// Very useful delay, especially at nigt time
// Without it motor starts immediately when light is turned on
digitalWrite(MOTOR_PIN, HIGH);
delay(1000); // Motor work period
digitalWrite(MOTOR_PIN, LOW);
myTimer = mainTimer;
}
}
else if (digitalRead(BTN4_PIN) == LOW && mode == 0 ){
digitalWrite(MOTOR_PIN, HIGH);
delay(1000); // Motor work period
digitalWrite(MOTOR_PIN, LOW);
}
// ### Power Saving ### //
adc_disable(); // // Disable ADC to save some power
sleep_enable(); // Enable Sleep Mode
sleep_cpu(); // Go to sleep!
}
// ### Switching intervals by button position function ### //
unsigned long getInterval() {
switch (mode) {
case 1:
return MODE1_INT;
case 2:
return MODE2_INT;
case 3:
return MODE3_INT;
default:
return 0;
}
}
ISR (WDT_vect) {
WDTCR |= _BV(WDIE); // Enable Watchdog Interrupts. Reset will be otherwise
}