#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
// Определение пинов для подключения компонентов
#define ENCODER_CLK_PIN A1 // Пин CLK энкодера
#define ENCODER_DT_PIN A2 // Пин DT энкодера
#define ENCODER_SW_PIN A3 // Пин кнопки энкодера
// Настройки LCD дисплея
#define LCD_ADDRESS 0x27 // I2C адрес LCD дисплея
#define LCD_COLS 20 // Количество столбцов дисплея
#define LCD_ROWS 4 // Количество строк дисплея
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLS, LCD_ROWS);
// Параметры таймера
volatile uint8_t current_day = 0; // день (обновляется каждый день)
volatile uint8_t current_hour = 0; // час (обновляется каждый час)
volatile uint8_t current_minute = 0; // минуты
volatile uint8_t current_second = 0; // секунды
// Функция установки даты и времени
void set_date_and_time() {
// Переменные для хранения позиции курсора и значений
int cursor_pos = 0;
int values[3] = {current_day, current_hour, current_minute};
int limits[3] = {21, 23, 59}; // Максимальные значения
bool editing = false;
lcd.clear();
while(true) {
// Отображаем текущие значения
lcd.setCursor(0, 0);
lcd.print("Set Date / Time:");
lcd.setCursor(0, 1);
lcd.print("Day: %02d");
lcd.print(values[0]);
lcd.setCursor(0, 2);
lcd.print("Hour: %02d");
lcd.print(values[1]);
lcd.setCursor(0, 3);
lcd.print("Minute: %02d");
lcd.print(values[2]);
// Мигающий курсор на редактируемой позиции
lcd.setCursor(8, cursor_pos + 1);
lcd.blink();
// Обработка энкодера
if (digitalRead(ENCODER_SW_PIN) == LOW) {
delay(50);
if (!editing) {
editing = true;
} else {
editing = false;
cursor_pos++;
if (cursor_pos > 2) {
// Сохраняем значения и выходим
current_day = values[0];
current_hour = values[1];
current_minute = values[2];
break;
}
}
while(digitalRead(ENCODER_SW_PIN) == LOW);
}
if (editing) {
// Изменение значения энкодером
if (digitalRead(ENCODER_CLK_PIN) != digitalRead(ENCODER_DT_PIN)) {
if (digitalRead(ENCODER_CLK_PIN) == LOW) {
values[cursor_pos]++;
if (values[cursor_pos] > limits[cursor_pos]) values[cursor_pos] = 0;
} else {
values[cursor_pos]--;
if (values[cursor_pos] < 0) values[cursor_pos] = limits[cursor_pos];
}
delay(2);
}
}
}
lcd.noBlink();
lcd.clear();
}
/* -------------------- Таймер: день, часы, минуты, секунды --------------------
*/
ISR(TIMER1_OVF_vect) {
if (++current_second >=
60) // Увеличеваем счетчик секунд пока не достигнет 60
{
current_second = 0; // Обнуляем сукунды
if (++current_minute >=
60) // Увеличеваем счетчик минут пока не достигнет 60
{
current_minute = 0; // Обнуляем минуты
if (++current_hour >=
24) // Увеличеваем часов секунд пока не достигнет 24
{
current_hour = 0; // Обнуляем часы
++current_day; // Увеличеваем счетчик дней
}
}
}
}
void setup()
{
lcd.init(); // Инициируем работу с LCD дисплеем
lcd.backlight(); // Turn on the LCD backlight
lcd.print(F("=< EGG INCUBATOR >=")); // Приветственный экран
delay(500);
lcd.setCursor(0, 3);
lcd.print(F("Starting"));
for (int i = 0; i < 12; ++i) {
lcd.print('.');
delay(300);
}
/* -------------------- Настройка таймера -------------------- */
cli(); // отключить глобальные прерывания
TCCR1A = 0; // установить TCCR1A регистр в 0
TCCR1B = 0; // установить TCCR1B регистр в 0
TCCR1A = (1 << WGM11); // режим 14 FAST PWM
TCCR1B = (1 << CS12) | (1 << WGM13) | (1 << WGM12); // делить частоту CPU на 256
ICR1 = 62499; // (16000000MHz / div 256) - 1 = 1 раз в секунду
TIMSK1 = (1 << TOIE1); // разрешить прерывание
sei(); // включить глобальные прерывания
lcd.clear(); // очищаем экран
set_date_and_time();
}
/* Основной цикл программы */
void loop()
{
}