#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <Arduino.h>
#include <GyverOLED.h>
/*ALARM_COOLDOWN - время, которое должно пройти после выключения
последнего будильника, чтобы сработал следующий будильник*/
#define ALARM_COOLDOWN 60000
GyverOLED<SSD1306_128x64, OLED_NO_BUFFER> oled;
#include <EncButton.h>
EncButton eb(10, 11, 12);
void setup() {
pinMode(7, INPUT_PULLUP);
oled.init(); // инициализация
oled.clear(); // очистка
oled.setScale(3); // масштаб текста (1..4)
oled.home(); // курсор в 0,0
Serial.begin(9600);
// показаны значения по умолчанию
eb.setBtnLevel(LOW);
eb.setClickTimeout(500);
eb.setDebTimeout(50);
eb.setHoldTimeout(600);
eb.setStepTimeout(200);
eb.setEncReverse(0);
eb.setEncType(EB_STEP4_LOW);
eb.setFastTimeout(30);
// сбросить счётчик энкодера
eb.counter = 0;
Serial.println("Чтобы начать настройку будильника нажмите кнопку энкодера(крутилки). С помощью поворотов настройте время срабатывания будильника. По завершению настройки зажмите кнопку энкодера");
}
// last_alarm_tm - время, когда был выключен последний будильник
int last_time = 0, last_alarm_tm = 0;
short int alarm_hour = 0, alarm_minutes = 0;
// button_7 - состояние кнопки
bool button_7 = 0;
// alarm_set = 0 - будильник не был установлен 1 - был установлен
/* alarming_once = 0 - будильник ни разу не срабатывал до этого.
1 - будильник срабатывал ранее хотябы один раз*/
/* alarming_once нужен для исключения случаев когда будильник не сработал
из-за сброса millis, или из-за того что система была включена менее чем минуту назад*/
bool alarm_set = 0, alarming_once = 0;
void loop() {
button_7 = !digitalRead(7);
eb.tick();
// проверяем время и будильник каждую секунду
if (millis() - last_time > 1000){
// вывод текущего времени
tmElements_t tm;
short int curr_tm_hours = 0, curr_tm_minutes = 0;
if (RTC.read(tm)) {
curr_tm_hours = tm.Hour;
curr_tm_minutes = tm.Minute;
oled.home();
oled.setScale(2);
oled.println("Time:");
oled.setCursorXY(0, 20);
print_time(curr_tm_hours, curr_tm_minutes);
} else {
// сообщение об ощибки если модуль времени не работает
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
} else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
}
if (button_7){
alarm_hour = 0;
alarm_minutes = 0;
alarm_set = 0;
Serial.println("Будильник отключен");
}
if (alarm_set && curr_tm_hours == alarm_hour && curr_tm_minutes == alarm_minutes && (millis() - last_alarm_tm > ALARM_COOLDOWN || !alarming_once)){
oled.home();
oled.clear();
oled.print("ALARM!");
while (1){
eb.clear();
eb.tick();
if (eb.press()){
noTone(3); // не пищать
oled.clear();
eb.clear();
last_alarm_tm = millis();
alarming_once = 1;
break;
}
if (millis() - last_time > 1000){
tone(3, 200); // пищать на пине 3, 1 кГц
last_time = millis();
} else if (millis() - last_time > 500) {
noTone(3); // не пищать
}
}
}
last_time = millis();
}
// если нажата кнопка энкодера, то переходим в режим установки будильника
if (eb.press()){
// вывод текущего времени будильника
oled.clear();
oled.home();
oled.setScale(2);
oled.println("Alarm at:");
oled.setCursorXY(0, 20);
print_time(alarm_hour, alarm_minutes);
while(1){
eb.clear();
eb.tick();
if (eb.turn()){
if (eb.left()){
alarm_minutes++;
if (alarm_minutes == 60){
alarm_hour++;
alarm_minutes = 0;
}
if (alarm_hour == 24){
alarm_hour = 0;
alarm_minutes = 0;
}
}
if (eb.right()){
alarm_minutes--;
if (alarm_minutes == -1){
alarm_hour--;
alarm_minutes == 0;
}
if (alarm_hour == -1){
alarm_hour = 23;
alarm_minutes = 59;
}
}
oled.setScale(2);
// вывод текущего времени будильника
oled.setCursorXY(0, 20);
print_time(alarm_hour, alarm_minutes);
}
if (eb.hold()){
alarm_set = 1;
oled.clear();
Serial.println("Будильник установлен");
break;
}
}
}
}
void print_time(short int hours, short int minutes) {
oled.setScale(3);
if (hours < 10){
oled.print(0);
oled.print(hours);
} else {
oled.print(hours);
}
oled.print(':');
if (minutes < 10){
oled.print(0);
oled.print(minutes);
} else {
oled.print(minutes);
}
}