Часы на Ардуино без модуля RTC на LCD 1602

Часы на Ардуино без модуля часов реального времени RTC с выводом информации на дисплей LCD 1602 i2c — в этом проекте предусмотрена настройка времени (часов и минут) и время включения будильника. Для этого использованы две тактовые кнопки (для переключения режимов настройки) и пьезодинамик ардуино для звукового сигнала. Проект содержит схему сборки устройства, а также рабочий код.

Для этого проекта потребуется:

  • Arduino Uno / Arduino Nano / Arduino Mega;
  • экран LCD 16×02 i2c;
  • 2 тактовые кнопки;
  • пьезодинамик;
  • макетная плата;
  • провода «папа-мама», «папа-папа».

Скетч. Часы на LCD 16×02 без модуля RTC

#include "Wire.h"                              // библиотека для протокола I2C
#include "LiquidCrystal_I2C.h"        // библиотека для LCD 16x02 
LiquidCrystal_I2C LCD(0x27, 20, 2);  // присваиваем имя дисплею

// переменные для отсчета времени и будильника
byte SEC = 0;
byte MIN = 34;
byte HOUR = 12
byte MIN_A = 35;
byte HOUR_A = 12;
unsigned long timer;

// переменные для считывания нажатия на кнопки
boolean button1WasUp = true;
boolean button2WasUp = true;
boolean button1IsUp;
boolean button2IsUp;

boolean alarm = true;
byte c1, c2, c3, w, i;

// значок будильника
byte bell [8] = {
  0b11000,
  0b11110,
  0b01100,
  0b01000,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
};

void setup() {
  pinMode(9, INPUT_PULLUP);   // подключаем тактовые кнопки
  pinMode(8, INPUT_PULLUP);
  pinMode(5, OUTPUT);               // подключаем пьезопищалку
  LCD.init();                                     // инициализация дисплея
  LCD.backlight();                           // включение подсветки
  LCD.createChar(1, bell);
  timer = millis();
}

void loop() {
  // узнаем текущее состояние кнопки
  button1IsUp = digitalRead(9);
  button2IsUp = digitalRead(8);

  // если кнопка 1 нажата, заходим в настройки (цикл while)
  if (button1WasUp && !button1IsUp) {
    delay(10);
    button1IsUp = digitalRead(9);
    if (!button1IsUp) {
      SEC = 0; w = 1;
    }
  }
  button1WasUp = button1IsUp;

  // если кнопка 2 была нажата выключаем будильник
  if (button2WasUp && !button2IsUp) {
    delay(10);
    button2IsUp = digitalRead(8);
    if (!button2IsUp) {
      alarm = false;
    }
  }
  button2WasUp = button2IsUp;

  // если прошло 1000 мс - прибавляем одну секунду
  if (millis() - timer > 1000) {
    timer = millis();
    SEC++;
    // если прошло 59 секунд, прибавляем 1 минуту
    if (SEC > 59) { SEC = 0; MIN++; }
    // если прошло 59 минут, прибавляем 1 час
    if (MIN > 59) { MIN = 0; HOUR++; }
    if (HOUR > 23) { HOUR = 0; }
    // включение будильника в течении 1 минуты
    if (alarm == true && HOUR == HOUR_A && MIN == MIN_A && i < 60) { tone(5, 50); i++; }
    if (i >= 60) { noTone(5); alarm == false; i = 0; }

    if (HOUR < 10) { c1 = 5; }
    if (HOUR >= 10) { c1 = 4; }
    if (MIN < 10) { c2 = 8; }
    if (MIN >= 10) { c2 = 7; }
    if (SEC < 10) { c3 = 11; }
    if (SEC >= 10) { c3 = 10; }

    // выводим время на дисплей
    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("0");
    LCD.setCursor(c3, 0);
    LCD.print(SEC);
    if (alarm == true) { LCD.print(char(1)); }
    if (alarm == false) { LCD.print(" "); }
    noTone(5);
  }

  while (w == 1) {

    if (HOUR > 23) { HOUR = 0; }
    if (HOUR < 10) { c1 = 5; }
    if (HOUR >= 10) { c1 = 4; }
    if (MIN < 10) { c2 = 8; }
    if (MIN >= 10) { c2 = 7; }

    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("00");
    if (alarm == true) { LCD.print(char(1)); }
    if (alarm == false) { LCD.print(" "); }

    LCD.setCursor(2, 1);
    LCD.print("HOUR SETTING");

    button1IsUp = digitalRead(9);
    button2IsUp = digitalRead(8);

    // если кнопка 1 была нажата, заходим во 2 цикл while
    if (button1WasUp && !button1IsUp) {
      delay(10);
      button1IsUp = digitalRead(9);
      if (!button1IsUp) {
        LCD.clear(); w = 2;
      }
    }
    button1WasUp = button1IsUp;

    // если кнопка 2 была нажата, прибавляем 1 час
    if (button2WasUp && !button2IsUp) {
      delay(10);
      button2IsUp = digitalRead(8);
      if (!button2IsUp) {
        HOUR++;
      }
    }
    button2WasUp = button2IsUp;

  }

  while (w == 2) {

    if (MIN > 59) { MIN = 0;}
    if (HOUR < 10) { c1 = 5; }
    if (HOUR >= 10) { c1 = 4; }
    if (MIN < 10) { c2 = 8; }
    if (MIN >= 10) { c2 = 7; }

    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("00");
    if (alarm == true) { LCD.print(char(1)); }
    if (alarm == false) { LCD.print(" "); }

    LCD.setCursor(1, 1);
    LCD.print("MINUTE SETTING");

    button1IsUp = digitalRead(9);
    button2IsUp = digitalRead(8);

    // если кнопка 1 была нажата, заходим в 3 цикл while
    if (button1WasUp && !button1IsUp) {
      delay(10);
      button1IsUp = digitalRead(9);
      if (!button1IsUp) {
        LCD.clear(); w = 3;
      }
    }
    button1WasUp = button1IsUp;

    // если кнопка 2 была нажата, прибавляем 1 минуту
    if (button2WasUp && !button2IsUp) {
      delay(10);
      button2IsUp = digitalRead(8);
      if (!button2IsUp) {
        MIN++;
      }
    }
    button2WasUp = button2IsUp;

  }

  while (w == 3) {

    if (MIN_A > 59) { MIN_A = 0; HOUR_A++; }
    if (HOUR_A > 23) { HOUR_A = 0; }
    if (HOUR_A < 10) { c1 = 5; }
    if (HOUR_A >= 10) { c1 = 4; }
    if (MIN_A < 10) { c2 = 8; }
    if (MIN_A >= 10) { c2 = 7; }

    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR_A);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN_A);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("00");
    if (alarm == true) { LCD.print(char(1)); LCD.setCursor(4, 1); LCD.print("ALARM ON "); }
    if (alarm == false) { LCD.print(" "); LCD.setCursor(4, 1); LCD.print("ALARM OFF"); }
 
    button1IsUp = digitalRead(9);
    button2IsUp = digitalRead(8);

    // если кнопка 1 была нажата, заходим в 4 цикл while
    if (button1WasUp && !button1IsUp) {
      delay(10);
      button1IsUp = digitalRead(9);
      if (!button1IsUp) {
        LCD.clear(); w = 4;
      }
    }
    button1WasUp = button1IsUp;

    // если кнопка 2 была нажата, прибавляем 1 минуту
    if (button2WasUp && !button2IsUp) {
      delay(10);
      button2IsUp = digitalRead(8);
      if (!button2IsUp) {
        alarm = !alarm;
      }
    }
    button2WasUp = button2IsUp;

  }

  while (w == 4) {

    if (MIN_A > 59) { MIN_A = 0; HOUR_A++; }
    if (HOUR_A > 23) { HOUR_A = 0; }
    if (HOUR_A < 10) { c1 = 5; }
    if (HOUR_A >= 10) { c1 = 4; }
    if (MIN_A < 10) { c2 = 8; }
    if (MIN_A >= 10) { c2 = 7; }

    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR_A);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN_A);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("00");
    if (alarm == true) { LCD.print(char(1)); }
    if (alarm == false) { LCD.print(" "); }

    LCD.setCursor(1, 1);
    LCD.print("ALARM SET HOUR");

    button1IsUp = digitalRead(9);
    button2IsUp = digitalRead(8);

    // если кнопка 1 была нажата, заходим в 5 цикл while
    if (button1WasUp && !button1IsUp) {
      delay(10);
      button1IsUp = digitalRead(9);
      if (!button1IsUp) {
        LCD.clear(); w = 5;
      }
    }
    button1WasUp = button1IsUp;

    // если кнопка 2 была нажата, прибавляем 1 час
    if (button2WasUp && !button2IsUp) {
      delay(10);
      button2IsUp = digitalRead(8);
      if (!button2IsUp) {
        HOUR_A++;
      }
    }
    button2WasUp = button2IsUp;
  }

  while (w == 5) {

    if (MIN_A > 59) { MIN_A = 0; HOUR_A++; }
    if (HOUR_A > 23) { HOUR_A = 0; }
    if (HOUR_A < 10) { c1 = 5; }
    if (HOUR_A >= 10) { c1 = 4; }
    if (MIN_A < 10) { c2 = 8; }
    if (MIN_A >= 10) { c2 = 7; }

    LCD.setCursor(4, 0);
    LCD.print("0");
    LCD.setCursor(c1, 0);
    LCD.print(HOUR_A);
    LCD.print(":");
    LCD.setCursor(7, 0);
    LCD.print("0");
    LCD.setCursor(c2, 0);
    LCD.print(MIN_A);
    LCD.print(":");
    LCD.setCursor(10, 0);
    LCD.print("00");
    if (alarm == true) { LCD.print(char(1)); }
    if (alarm == false) { LCD.print(" "); }

    LCD.setCursor(0, 1);
    LCD.print("ALARM SET MINUTE");

    button1IsUp = digitalRead(9);
    button2IsUp = digitalRead(8);

    // если кнопка 1 была нажата, выходим из цикла
    if (button1WasUp && !button1IsUp) {
      delay(10);
      button1IsUp = digitalRead(9);
      if (!button1IsUp) {
        LCD.clear(); w = 0;
      }
    }
    button1WasUp = button1IsUp;

    // если кнопка 2 была нажата, прибавляем 1 минуту
    if (button2WasUp && !button2IsUp) {
      delay(10);
      button2IsUp = digitalRead(8);
      if (!button2IsUp) {
        MIN_A++;
      }
    }
    button2WasUp = button2IsUp;

  }

}

Пояснения к коду:

  1. переменные c1 и c2 отвечают за позицию курсора при выводе времени и минут на экране, в зависимости от того — двухзначное или однозначное число хранится в переменной (это сделано для удобства вывода информации);
  2. во время настройки часов и будильника, таймер останавливается.

Заключение. Часы без модуля RTC ds1302 будут сбрасывать время на начальные значения при отключении питания, поэтому в проект были добавлены кнопки. С помощью них можно настроить часы, без необходимости повторной загрузки скетча — получился простой проект на Ардуино для начинающих программировать. Также можно добавить датчик DHT11 или BMP180, чтобы выводить на экране температуру.

Источник