#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS1307 rtc;
const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int relayPin = 7;
unsigned long previousMillis = 0;
const unsigned long interval = 1000;
unsigned long lastButtonPressTime = 0; // Час останнього натискання кнопки
enum ScreenType { MAIN_SCREEN, TIMER_SCREEN };
ScreenType currentScreen = MAIN_SCREEN;
DateTime timerStartTime; // Час початку таймера
DateTime timerEndTime; // Час завершення таймера
bool timerActive = false; // Флаг активності таймера
bool settingEndTime = false;
bool changingTimeMode = false;
int selectedParameter = 0; // 0 - години, 1 - хвилини, 2 - секунди
int blinkCounter = 0;
void setup() {
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
DateTime now = rtc.now();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
switch (currentScreen) {
case MAIN_SCREEN:
// Виведення годин у форматі ГГ:ХХ:СС
display.setCursor(0, 0);
if (now.hour() < 10)
display.print('0');
display.print(now.hour(), DEC);
display.print(':');
if (now.minute() < 10)
display.print('0');
display.print(now.minute(), DEC);
display.print(':');
if (now.second() < 10)
display.print('0');
display.print(now.second(), DEC);
break;
case TIMER_SCREEN:
if (timerActive) {
// Виведення часу ввімкнення і вимкнення реле
display.setCursor(0, 0);
display.print("T.ON= ");
display.setCursor(0, 15);
display.print(timerStartTime.hour(), DEC);
display.print(':');
if (timerStartTime.minute() < 10)
display.print('0');
display.print(timerStartTime.minute(), DEC);
display.print(':');
if (timerStartTime.second() < 10)
display.print('0');
display.print(timerStartTime.second(), DEC);
if (timerEndTime.unixtime() != 0) {
display.setCursor(0, 30);
display.print("T.OFF= ");
display.setCursor(0, 45);
display.print(timerEndTime.hour(), DEC);
display.print(':');
if (timerEndTime.minute() < 10)
display.print('0');
display.print(timerEndTime.minute(), DEC);
display.print(':');
if (timerEndTime.second() < 10)
display.print('0');
display.print(timerEndTime.second(), DEC);
}
} else {
// Таймер завершено, перехід на основний екран
currentScreen = MAIN_SCREEN;
}
if (millis() - lastButtonPressTime > 10000) {
currentScreen = MAIN_SCREEN;
}
break;
}
// Виведення екрану зміни часу таймера
if (changingTimeMode) {
if (blinkCounter < 10) {
display.setTextColor(WHITE, BLACK);
} else {
display.setTextColor(BLACK, WHITE);
}
blinkCounter = (blinkCounter + 1) % 20;
display.setCursor(0, 0);
display.print("T.ON= ");
display.setCursor(0, 15);
display.print(timerStartTime.hour(), DEC);
display.print(':');
display.print(timerStartTime.minute() < 10 ? '0' : ' ');
display.print(timerStartTime.minute(), DEC);
display.print(':');
display.print(timerStartTime.second() < 10 ? '0' : ' ');
display.print(timerStartTime.second(), DEC);
display.setCursor(0, 30);
display.print("T.OFF= ");
display.setCursor(0, 45);
display.print(timerEndTime.hour(), DEC);
display.print(':');
display.print(timerEndTime.minute() < 10 ? '0' : ' ');
display.print(timerEndTime.minute(), DEC);
display.print(':');
display.print(timerEndTime.second() < 10 ? '0' : ' ');
display.print(timerEndTime.second(), DEC);
}
display.display();
}
// Опитування стану кнопки K1
if (digitalRead(buttonPin1) == HIGH) {
// Кнопку натиснуто
unsigned long buttonPressTime = millis();
// Перевірка тривалості натискання (менше 1 сек)
while (digitalRead(buttonPin1) == HIGH && millis() - buttonPressTime < 1000) {
// Очікування
}
if (millis() - buttonPressTime < 1000) {
// Коротке натискання
lastButtonPressTime = millis(); // Оновлення часу останнього натискання кнопки
if (currentScreen == MAIN_SCREEN) {
// Перехід на "екран таймера"
currentScreen = TIMER_SCREEN;
timerStartTime = now; // Запуск таймера
timerActive = true;
digitalWrite(relayPin, HIGH);
} else if (currentScreen == TIMER_SCREEN) {
// Повернення на "основний екран"
currentScreen = MAIN_SCREEN;
timerEndTime = now;
timerActive = false; // Вимкнення таймера
digitalWrite(relayPin, LOW);
}
} else if (millis() - buttonPressTime > 1000 && millis() - buttonPressTime < 3000) {
// Тривале натискання (>1сек), перехід в режим зміни часу таймера
changingTimeMode = !changingTimeMode;
blinkCounter = 0;
} else if (millis() - buttonPressTime > 3000 && changingTimeMode) {
// Тривале натискання (>3сек) в режимі зміни часу таймера, зміна параметрів таймера
if (selectedParameter == 0) {
// Зміна годин
timerStartTime = timerStartTime + TimeSpan(0, 1, 0, 0);
} else if (selectedParameter == 1) {
// Зміна хвилин
timerStartTime = timerStartTime + TimeSpan(0, 0, 1, 0);
} else if (selectedParameter == 2) {
// Зміна секунд
timerStartTime = timerStartTime + TimeSpan(0, 0, 0, 1);
} else if (selectedParameter == 3) {
// Зміна годин
timerEndTime = timerEndTime + TimeSpan(0, 1, 0, 0);
} else if (selectedParameter == 4) {
// Зміна хвилин
timerEndTime = timerEndTime + TimeSpan(0, 0, 1, 0);
} else if (selectedParameter == 5) {
// Зміна секунд
timerEndTime = timerEndTime + TimeSpan(0, 0, 0, 1);
}
}
}
// Додано опитування стану кнопок K2 і K3 в режимі зміни часу таймера
if (changingTimeMode) {
if (digitalRead(buttonPin2) == HIGH) {
// Кнопку K2 натиснуто в режимі зміни часу таймера
selectedParameter = (selectedParameter + 1) % 6;
delay(200); // Затримка для уникнення спрацювання декількох разів при утримуванні кнопки
}
if (digitalRead(buttonPin3) == HIGH) {
// Кнопку K3 натиснуто в режимі зміни часу таймера
selectedParameter = (selectedParameter + 5) % 6;
delay(200); // Затримка для уникнення спрацювання декількох разів при утримуванні кнопки
}
}
// Додано умову для спрацювання реле згідно із заданим інтервалом
if (now >= timerStartTime && now <= timerEndTime) {
digitalWrite(relayPin, HIGH); // Спрацювання реле
} else {
digitalWrite(relayPin, LOW); // Реле вимкнено
}
}