#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#define UP_PIN 3
#define DOWN_PIN 4
#define LEFT_PIN 5
#define RIGHT_PIN 6
#define START_PIN 7
#define STOP_PIN 8
#define BUZZER_PIN 12
typedef struct {
int hours;
int minutes;
int seconds;
float setTemperature;
} Settings;
LiquidCrystal_I2C lcd(0x27, 16, 2);
OneWire oneWire(2);
DallasTemperature sensor(&oneWire);
Settings settings;
float currentTemp = 0.0;
int cursorPos = 0;
enum State { SETTING, WAIT_TEMP, COUNTDOWN, WAIT_STOP };
State currentState = SETTING;
unsigned long countdownStartTime;
unsigned long countdownDuration;
void loadSettings()
{
EEPROM.get(0, settings);
if (settings.hours < 0 || settings.hours >= 24) settings.hours = 0;
if (settings.minutes < 0 || settings.minutes >= 60) settings.minutes = 0;
if (settings.seconds < 0 || settings.seconds >= 60) settings.seconds = 0;
if (settings.setTemperature < 0.0f || settings.setTemperature > 120.0f || isnan(settings.setTemperature))
{
settings.setTemperature = 100.0f;
}
EEPROM.put(0, settings);
}
float getTemperature()
{
static bool requestSent = false;
static unsigned long lastRequestTime = 0;
static float lastTemperature = 0.0f;
if (!requestSent && (millis() - lastRequestTime >= 500UL))
{
sensor.requestTemperatures();
requestSent = true;
lastRequestTime = millis();
}
if(!sensor.isConversionComplete())
{
return lastTemperature;
}
requestSent = false;
float t = sensor.getTempCByIndex(0);
lastTemperature = (t == DEVICE_DISCONNECTED_C ? lastTemperature : t);
return lastTemperature;
}
void setup()
{
lcd.init();
lcd.backlight();
sensor.begin();
sensor.setWaitForConversion(false);
loadSettings();
pinMode(UP_PIN, INPUT_PULLUP);
pinMode(DOWN_PIN, INPUT_PULLUP);
pinMode(LEFT_PIN, INPUT_PULLUP);
pinMode(RIGHT_PIN, INPUT_PULLUP);
pinMode(START_PIN, INPUT_PULLUP);
pinMode(STOP_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
drawScreen();
}
void loop()
{
currentTemp = getTemperature();
handleButtons();
if (currentState == WAIT_TEMP)
{
if (currentTemp >= settings.setTemperature)
{
currentState = COUNTDOWN;
countdownStartTime = millis();
countdownDuration = 1000UL * ((3600UL * settings.hours) + (60UL * settings.minutes) + settings.seconds);
}
}
else if (currentState == COUNTDOWN)
{
unsigned long elapsed = millis() - countdownStartTime;
if (elapsed >= countdownDuration)
{
currentState = WAIT_STOP;
digitalWrite(BUZZER_PIN, HIGH);
}
}
drawScreen();
}
int getButtonPressed()
{
if (digitalRead(UP_PIN) == LOW) return UP_PIN;
if (digitalRead(DOWN_PIN) == LOW) return DOWN_PIN;
if (digitalRead(LEFT_PIN) == LOW) return LEFT_PIN;
if (digitalRead(RIGHT_PIN) == LOW) return RIGHT_PIN;
if (digitalRead(START_PIN) == LOW) return START_PIN;
if (digitalRead(STOP_PIN) == LOW) return STOP_PIN;
return -1;
}
void handleButtons()
{
static int lastButton = -1;
static unsigned long lastButtonPressedTime = 0;
static unsigned long holdStartTime = 0;
int buttonPressed = getButtonPressed();
if (buttonPressed == lastButton)
{
if (buttonPressed != -1 && millis() - holdStartTime >= 1000)
{
if (millis() - lastButtonPressedTime < 50)
{
return;
}
}
else
{
return;
}
}
else if (buttonPressed != -1)
{
holdStartTime = millis();
delay(20);
}
lastButtonPressedTime = millis();
lastButton = buttonPressed;
if (currentState == SETTING)
{
if (buttonPressed == UP_PIN)
{
adjustValue(1);
}
else if (buttonPressed == DOWN_PIN)
{
adjustValue(-1);
}
else if (buttonPressed == LEFT_PIN)
{
cursorPos = (cursorPos + 3) % 4;
}
else if (buttonPressed == RIGHT_PIN)
{
cursorPos = (cursorPos + 1) % 4;
}
else if (buttonPressed == START_PIN)
{
currentState = WAIT_TEMP;
EEPROM.put(0, settings);
}
}
else if (currentState == WAIT_TEMP || currentState == COUNTDOWN || currentState == WAIT_STOP)
{
if (buttonPressed == STOP_PIN)
{
digitalWrite(BUZZER_PIN, LOW);
currentState = SETTING;
cursorPos = 0;
}
}
}
void adjustValue(int change)
{
if (cursorPos == 0)
{
settings.hours += change;
if (settings.hours < 0) settings.hours = 24 + settings.hours;
if (settings.hours >= 24) settings.hours = settings.hours % 24;
}
else if (cursorPos == 1)
{
settings.minutes += change;
if (settings.minutes < 0) settings.minutes = 60 + settings.minutes;
if (settings.minutes >= 60) settings.minutes = settings.minutes % 60;
}
else if (cursorPos == 2)
{
settings.seconds += change;
if (settings.seconds < 0) settings.seconds = 60 + settings.seconds;
if (settings.seconds >= 60) settings.seconds = settings.seconds % 60;
}
else if (cursorPos == 3)
{
settings.setTemperature += change;
if (settings.setTemperature < 0.0f) settings.setTemperature = 121.0f + settings.setTemperature;
if (settings.setTemperature > 120.0f) settings.setTemperature = fmod(settings.setTemperature, 120.0f);
}
}
void drawScreen()
{
static char lastLine1[17] = "";
static char lastLine2[17] = "";
static int lastCursorPos = -1;
char line1[17], line2[17];
char tempBuf[6];
float tempToDisplay = currentTemp;
if (currentState == SETTING && cursorPos == 3)
{
tempToDisplay = settings.setTemperature;
}
dtostrf(tempToDisplay, 3, 1, tempBuf);
if (currentState == SETTING || currentState == WAIT_TEMP)
{
sprintf(line1, "%02d:%02d:%02d%7sC", settings.hours, settings.minutes, settings.seconds, tempBuf);
}
else if (currentState == WAIT_STOP)
{
sprintf(line1, "00:00:00%7sC", tempBuf);
}
else if (currentState == COUNTDOWN)
{
unsigned long timeLeft = countdownDuration - (millis() - countdownStartTime);
timeLeft /= 1000;
int hours = timeLeft / 3600;
int minutes = (timeLeft % 3600) / 60;
int seconds = timeLeft % 60;
sprintf(line1, "%02d:%02d:%02d%7sC", hours, minutes, seconds, tempBuf);
}
if (currentState == SETTING)
{
sprintf(line2, " STOP ");
}
else
{
sprintf(line2, " UZBROJONY ");
}
if (strcmp(line1, lastLine1) != 0 || strcmp(line2, lastLine2) != 0 || lastCursorPos != cursorPos)
{
lcd.noCursor();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
switch (cursorPos)
{
case 0: lcd.setCursor(1, 0); break;
case 1: lcd.setCursor(4, 0); break;
case 2: lcd.setCursor(7, 0); break;
case 3: lcd.setCursor(15, 0); break;
}
if (currentState == SETTING)
{
lcd.cursor();
}
strcpy(lastLine1, line1);
strcpy(lastLine2, line2);
lastCursorPos = cursorPos;
}
}