|
#include <SevSeg.h> |
|
#include <EEPROM.h> |
|
|
|
const byte SAFELIGHT_PIN = 1; |
|
const byte BUTTON_ARRAY_PIN = A0; |
|
const byte ENCODER_A_PIN = A1; |
|
const byte ENCODER_B_PIN = A2; |
|
const byte RELAY_PIN = A3; |
|
const byte SAFELIGHT_BUTTON_PIN = A4; |
|
const byte BUZZER_PIN = A5; |
|
|
|
// Changable if EEPROM ever wears out at these addresses |
|
const int EEPROM_ADDRESSES[] = { 0, 1, 2, 3 }; |
|
|
|
const byte NUM_DIGITS = 4; |
|
const byte DIGIT_PINS[] = { 5, 4, 3, 2 }; |
|
const byte SEGMENT_PINS[] = { 11, 13, 9, 7, 6, 12, 10, 8 }; |
|
|
|
SevSeg screen; |
|
|
|
int buttonArrayValue; |
|
unsigned long lastButtonArrayTime; |
|
unsigned long lastTimerUpdate; |
|
unsigned long timerUpdate; |
|
boolean lastEncoderAValue; |
|
boolean encoderAValue; |
|
boolean encoderBValue; |
|
|
|
byte activeTimer = 0; |
|
int timers[] = { |
|
EEPROM.read(EEPROM_ADDRESSES[0]), |
|
EEPROM.read(EEPROM_ADDRESSES[1]), |
|
EEPROM.read(EEPROM_ADDRESSES[2]), |
|
EEPROM.read(EEPROM_ADDRESSES[3]) |
|
}; |
|
|
|
boolean timerRunning = false; |
|
boolean safelightOn = false; |
|
|
|
void setup() { |
|
pinMode(BUZZER_PIN, OUTPUT); |
|
pinMode(RELAY_PIN, OUTPUT); |
|
pinMode(SAFELIGHT_PIN, OUTPUT); |
|
pinMode(ENCODER_A_PIN, INPUT); |
|
pinMode(ENCODER_B_PIN, INPUT); |
|
pinMode(SAFELIGHT_BUTTON_PIN, INPUT); |
|
|
|
// Type, digits, segments, digit pins, segment pins, resistors on pins, update with delay, leading zeroes. |
|
screen.begin(COMMON_CATHODE, NUM_DIGITS, DIGIT_PINS, SEGMENT_PINS, true, false, true); |
|
screen.setBrightness(10); |
|
|
|
lastEncoderAValue = digitalRead(ENCODER_A_PIN); |
|
} |
|
|
|
void loop() { |
|
// Read rotary encoder |
|
encoderAValue = digitalRead(ENCODER_A_PIN); |
|
encoderBValue = digitalRead(ENCODER_B_PIN); |
|
if (encoderAValue != lastEncoderAValue && encoderAValue == true && timerRunning == false) { |
|
if (encoderBValue != encoderAValue) { |
|
timers[activeTimer]++; |
|
} else { |
|
timers[activeTimer]--; |
|
} |
|
// Minimum timer is 0, maximum timer is 99 minutes, 99 seconds = 6039 seconds |
|
timers[activeTimer] = min(max(0, timers[activeTimer]), 6039); |
|
} |
|
lastEncoderAValue = encoderAValue; |
|
|
|
// Button array |
|
buttonArrayValue = analogRead(BUTTON_ARRAY_PIN); |
|
if (millis() - lastButtonArrayTime > 100 && timerRunning == false) { |
|
if (buttonPressed(buttonArrayValue, 516)) { |
|
startTimer(); |
|
} else if (buttonPressed(buttonArrayValue, 344)) { |
|
startTimer(); |
|
digitalWrite(RELAY_PIN, HIGH); |
|
} else if (buttonPressed(buttonArrayValue, 257)) { |
|
activeTimer = 0; |
|
} else if (buttonPressed(buttonArrayValue, 205)) { |
|
activeTimer = 1; |
|
} else if (buttonPressed(buttonArrayValue, 171)) { |
|
activeTimer = 2; |
|
} else if (buttonPressed(buttonArrayValue, 146)) { |
|
activeTimer = 3; |
|
} |
|
lastButtonArrayTime = millis(); |
|
} |
|
|
|
timerUpdate = millis() - lastTimerUpdate; |
|
|
|
// Clear timer |
|
if (timerUpdate > 1000 && timerRunning == true && timers[activeTimer] <= 0) { |
|
timers[activeTimer] = EEPROM.read(EEPROM_ADDRESSES[activeTimer]); |
|
tone(BUZZER_PIN, 880, 1000); |
|
timerRunning = false; |
|
digitalWrite(RELAY_PIN, LOW); |
|
} |
|
|
|
// Update timer every second |
|
if (timerUpdate > 1000 && timerRunning == true) { |
|
timers[activeTimer]--; |
|
// Beep every second, with a higher beep every 30 seconds. |
|
if (timers[activeTimer] % 30 == 0) { |
|
tone(BUZZER_PIN, 880, 250); |
|
} else { |
|
tone(BUZZER_PIN, 440, 50); |
|
} |
|
lastTimerUpdate += timerUpdate; // Use the timerUpdate so average time is correct |
|
} |
|
|
|
// Update displays (safelight and screen). |
|
safelightOn = digitalRead(SAFELIGHT_BUTTON_PIN); |
|
|
|
if (safelightOn == true) { |
|
digitalWrite(SAFELIGHT_PIN, HIGH); |
|
screen.setNumber(secondsToMinutes(timers[activeTimer]), 3 - activeTimer); |
|
} else { |
|
digitalWrite(SAFELIGHT_PIN, LOW); |
|
screen.blank(); |
|
} |
|
screen.refreshDisplay(); |
|
} |
|
|
|
// Calculates if a number is within a margin of +/- 15. If so, it returns true. |
|
// This is used for the analogue buttons to see if they were pressed. |
|
boolean buttonPressed (int buttonArrayValue, int target) { |
|
if (abs(buttonArrayValue - target) < 15) { |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
// Returns a seconds value in MMSS format. |
|
int secondsToMinutes (int seconds) { |
|
if (seconds < 60) { |
|
return seconds; |
|
} else { |
|
return (floor(seconds / 60) * 100) + (seconds % 60); |
|
} |
|
} |
|
|
|
// Stores the current time if it is new, and starts the timer. |
|
void startTimer () { |
|
EEPROM.update(EEPROM_ADDRESSES[activeTimer], timers[activeTimer]); |
|
timerRunning = true; |
|
} |