Часы (DS3231) с будильником (Arduino)

Часы с будильником состоят из платы Arduino Nano (Uno), LCD индикатора 1602 и модуля часов реального времени DS3231 (ZS-042). Помимо текущего времени на экране индикатора отображается дата, день недели, месяц, год и температура. Будильник в часах один, он позволяет выставить время срабатывания в минутах и часах, так же предусмотрено его отключение, а так же работа каждый день, в будние дни и по выходным. Установка времени срабатывания будильника осуществляется кнопками «К», «+» и «-«. Сигнал будильника звучит в течении одной минуты, но если нажать на одну из кнопок «+» или «-«. сигнал будильника можно прервать. Время срабатывания будильника и режим его работы сохраняются в энергонезависимой памяти.

Устанавливать время на часах не нужно, так как предусмотрена коррекция времени при прошивке микроконтроллера. Для этого необходимо раскомментировать строчку:

// clock.setDateTime(__DATE__, __TIME__);

Далее залейте скетч в плату, закомментируйте строчку и залейте скетч повторно.

#include <Wire.h>
#include <DS3231.h>//https://github.com/jarzebski/Arduino-DS3231/archive/master.zip // DS3231.zip
DS3231 clock;RTCDateTime DateTime;
#include <LiquidCrystal.h>  
#include <EEPROM.h> //#include <EEPROMex.h> 
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);// RS,E,D4,D5,D6,D7
 
int k,m,h,i,w,reg,ton;
byte rom0,rom1,rom2;
unsigned long eeprom;
 
void setup(){Serial.begin(9600);
   lcd.begin(16,2);// LCD 16X2 
   Wire.begin(); clock.begin();
   pinMode(2,INPUT);pinMode(3,INPUT);pinMode(4,INPUT);
 //  clock.setDateTime(__DATE__, __TIME__); // Устанавливаем время на часах, основываясь на времени компиляции скетча
  rom0 = EEPROM.read(0);if(rom0>59){EEPROM.update(0,0);}
  rom1 = EEPROM.read(1);if(rom1>23){EEPROM.update(1,0);}
  rom2 = EEPROM.read(2);if(rom2>3){EEPROM.update(2,0);}
  m=rom0;h=rom1;w=rom2;
}
 
void loop(){i++;if(i>4){i=0;}
 if(digitalRead(2)==HIGH){k++;reg=1;delay(300);}if(k>3){k=0;reg=0;}
 
 if(reg==1) {
 if(k==1){
 if(digitalRead(3)==HIGH){m++;}if(m>59){m=59;}
 if(digitalRead(4)==HIGH){m--;}if(m<0){m=0;}}
 if(k==2){
 if(digitalRead(3)==HIGH){h++;}if(h>23){h=23;}
 if(digitalRead(4)==HIGH){h--;}if(h<0){h=0;}}
 if(k==3){
 if(digitalRead(3)==HIGH){w++;delay(300);}if(w>3){w=0;}
 if(digitalRead(4)==HIGH){w--;delay(300);}if(w<0){w=3;}
 } 
 lcd.setCursor(0,0);lcd.print("Alarm ");
 if(i==1&&k==2){lcd.print("  ");}else{if(h < 10 ){lcd.print("0");}lcd.print(h);} lcd.print(":");
 if(i==1&&k==1){lcd.print("  ");}else{if(m < 10 ){lcd.print("0");}lcd.print(m);} 
 lcd.setCursor(0,1);
 if(i==1&&k==3){lcd.print("                 ");}
 if(w==0){lcd.print("every day");}  //каждый день 1234567
 if(w==1){lcd.print("on weekdays");}//по будням 12345
 if(w==2){lcd.print("on weekends");}//по выходным 67
 if(w==3){lcd.print("off");}
 rom0=m;rom1=h;rom2=w;
 eeprom=0;
 }
 
 if(reg==0){if(eeprom==1){EEPROM.update(0,rom0);EEPROM.update(1,rom1);EEPROM.update(2,rom2);}
 DateTime=clock.getDateTime();   // Считываем c часов текущие значения даты и времени в сущность DateTime
 lcd.setCursor(0,0);
 lcd.print(clock.dateFormat("H:i:s ",DateTime));// выводим часы, минуты и секунды
 lcd.print(clock.readTemperature(),1);lcd.print((char)223);lcd.print("C");// выводим значение температуры
 lcd.setCursor(0,1);lcd.print(clock.dateFormat("D d M Y", DateTime));// выводим день недели, дату, месяц и год
 }
if(digitalRead(3)==HIGH||digitalRead(4)==HIGH){ton=1;}
if(DateTime.hour*60+DateTime.minute!=h*60+m){ton=0;}
 
 if(w==0){pic();}
 if(w==1&&(DateTime.dayOfWeek<6)){pic();}
 if(w==2&&(DateTime.dayOfWeek>5)){pic();}
 
 eeprom++;
 delay(200);
 lcd.clear();
 
}
 
void pic(){if(ton==0&&(DateTime.hour*60+DateTime.minute==h*60+m)){tone(5,1200,500);delay(500);}}

// форум - http://forum.rcl-radio.ru/viewtopic.php?pid=927#p927

Второй вариант часов с будильником выполнен с использованием четырех разрядного семисегментного индикатора на базе драйвера TM1637 (модуль TM1637).

При нажимании кнопки «К» происходит перебор элементов меню, вывод секунд, даты и месяца, температуры, установка времени будильника, включение или отключение будильника, яркость индикатора.

#include <Wire.h>
#include <TM1637Display.h>
#include <DS3231.h>
#include <EEPROM.h>  //#include <EEPROMex.h>
DS3231 clock; // ПОДКЛЮЧЕНИЕ DS3231 SDA, SCL, SQW / A4, A5, D6
RTCDateTime DateTime;
TM1637Display display(4, 5);// ПОДКЛЮЧЕНИЕ TM1637 CLK,DIO / 4, 5
 
int k,alarm_m,alarm_h;
byte w = 1,x,y,z,menu,ton,on=1;
uint8_t date_s[]{0,0,0,0};// second
uint8_t date_t[]{0x78,0,0,0};// t
uint8_t date_on[]{0,0,0x3f,0x37};// ON
uint8_t date_off[]{0,0x3f,0x71,0x71};// OFF
 
void setup() {
  // clock.setDateTime(__DATE__, __TIME__);
   display.setBrightness(1);// яркость TM1637 0-7
   Wire.begin(); clock.begin();
   pinMode(6,INPUT);pinMode(10,INPUT);pinMode(11,INPUT);pinMode(12,INPUT);
   alarm_m = EEPROM.read(0);alarm_h = EEPROM.read(1);z = EEPROM.read(3);// ЧТЕНИЕ EEPROM
}
 
void loop() {
     DateTime = clock.getDateTime(); // ОПРОС ВРЕМЕНИ
     k = DateTime.hour*100+DateTime.minute; // ВРЕМЯ КАК ЧИСЛО ННММ
 
if(digitalRead(6) == HIGH){x = 0x40;}else{x = 0x00;} // МИГАНИЕ ДВОЕТОЧИЯ 
if(digitalRead(10) == HIGH){menu++;delay(300);if(menu > 6){menu = 0;}} // ПЕРЕБОР МЕНЮ
 
if(menu == 0){y = true;if(w == 0){EEPROM.update(0,alarm_m);EEPROM.update(1,alarm_h);EEPROM.update(3,z);}
w = 1;}  // ПРИ ВЫХОДЕ ИЗ МЕНЮ ОБНОВЛЕНИЕ EEPROM
 
if(menu == 1){k = DateTime.second;date_s[2] = display.encodeDigit((k/10)%10);
date_s[3] = display.encodeDigit((k%10)%10);display.setSegments(date_s);
} // ВЫВОД СЕКУНД
 
if(menu == 2){k = DateTime.day*100 + DateTime.month;x = 0x40;} // ВЫВОД ДАТЫ И МЕСЯЦА
 
if(menu == 3){k = clock.readTemperature();date_t[2] = display.encodeDigit((k/10)%10);
date_t[3] = display.encodeDigit((k%10)%10);display.setSegments(date_t);} // ВЫВОД ТЕМПЕРАТУРЫ
 
if(menu == 4){y = true;x = 0x40;k = alarm_h*100+alarm_m; // УСТАНОВКА БУДИЛЬНИКА
if(digitalRead(12) == HIGH){alarm_m++;delay(300);}if(alarm_m > 59){alarm_m = 0;} // МИНУТЫ БУДИЛЬНИКА
if(digitalRead(11) == HIGH){alarm_h++;delay(500);}if(alarm_h > 23){alarm_h = 0;} // ЧАСЫ БУДИЛЬНИКА
w = 0;}
 
if(menu == 5){
if(digitalRead(11) == HIGH){on=1;delay(300);}if(on==1){display.setSegments(date_on);} // БУДИЛЬНИК ВКЛЮЧЕН
if(digitalRead(12) == HIGH){on=0;delay(300);}if(on==0){display.setSegments(date_off);} // БУДИЛЬНИК ВЫКЛЮЧЕН
}
 
if(menu == 6){y = false;x = 0x00;k = z; // НАСТРОЙКА ЯРКОСТИ ИНДИКАТОРА
if(digitalRead(11) == HIGH){z++;delay(500);}if(z > 7){z = 0;}
if(digitalRead(12) == HIGH){z--;delay(500);}if(z > 8){z = 7;}
w = 0;}
 
if(digitalRead(11)==HIGH||digitalRead(12)==HIGH){ton=1;} // ПРИ НАЖАТИИ НА КНОПУ + ИЛИ - ПРЕРЫВАЕТСЯ СИГНАЛ БУДИЛНИКА
if(DateTime.hour*100+DateTime.minute!=alarm_h*100+alarm_m){ton=0;}
if(on==1){pic();}
 
display.setBrightness(z);
if(menu == 3 || menu == 5 || menu == 1){}else{display.showNumberDecEx(k,x,y);}
 
}
void pic(){if(ton==0&&(DateTime.hour*100+DateTime.minute==alarm_h*100+alarm_m)){tone(7,1000,500);delay(1000);}} // СИГНАЛ БУДИЛЬНИКА, 7 ЦИФРОВОЙ ВЫХОД

 

Comments

    1. Скорее всего неверно установлена библиотека DS3231, необходимо скачать библиотеку указанную в скетче, распаковать ее, переименовать распакованную папку в DS3231, создать архив из папки DS3231.zip.
      Файлы с расширением .ccp и .h должны находится в корне папки библиотеки.

      Перед установкой удалите старую библиотеку.

        1. Уважаемый medved323! Распиши пожалуйста для чайника пошагово где и как скачать и распаковать эту библиотеку. А проще скинь мне её. Если не трудно.

    1. В папке где у Вас сохраняются скетчи, есть папка libraries, в ней найдите нужную библиотеку и удалите ее, новую библиотеку Вы можете рапаковать в эту же папку без добавления библиотеки через Arduino IDE.

  1. Век живи — век учись! Спасибо! Всё работает как доктор прописал!
    Если есть интерес по подсветке лестницы на Ардуино, пиши на мыло.
    У меня работает более 2 лет.

      1. Если Вы про установку времени часов, то раскомментируйте строчку:
        // clock.setDateTime(__DATE__, __TIME__);
        Залейте скетч в ардуино,
        Затем закомментируйте строчку и по новой залейте скетч.

  2. Есть пример с другого кода :
    if (digitalRead(keyPL) && digitalRead(keyHor)){ // часы
    second = 0; // сбрасываем секунды
    if (hour < 23){hour++;}
    else if (hour == 23){hour = 0;}
    setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year); // пишим в модуль
    delay(200);
    }
    if (digitalRead(keyPL) && digitalRead(keyMin)){ // минуты
    second = 0;
    if (minute < 59){minute++;}
    else if (minute == 59){minute = 0;}
    setDateDs3231(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    delay(200);
    }

    1. Время можно изменить следующей командой:
      // Manual (Year, Month, Day, Hour, Minute, Second)
      clock.setDateTime(2014, 4, 25, 0, 0, 0);

      В моем коде можно добавить несколько новых разделов меню, для минут, часов, дня месяца и года, но с таким индикатором это не целесообразно, настройка часов разовая процедура, она будет только мешаться, но тем не менее при желании можно добавить следующий код:

      int set_Year=2019, set_Month, set_Day, set_h, set_min;// добавим переменные для даты и времени

      if(menu == 7){y = true;x = 0x00;k = set_Year; //выводим на индикатор год
      if(digitalRead(12) == HIGH){set_Year++;delay(300);}if(set_Year > 2100){set_Year = 2019;}
      if(digitalRead(11) == HIGH){set_Year—;delay(300);}if(set_Year < 2019){set_Year = 2019;} w = 0;} if(w==0){clock.setDateTime(set_Year, set_Month, set_Day, set_h, set_min, 0);w=1;} далее создаем menu № 8 9 10... для месяца дня часов и минут Но все же проще воспользоваться командой установки времени компиляции: // clock.setDateTime(__DATE__, __TIME__); для этого и используюся часы реального времени.

  3. if(menu == 4){y = true;x = 0x40;k = alarm_h*100+alarm_m; // УСТАНОВКА БУДИЛЬНИКА
    if(digitalRead(12) == HIGH){alarm_m++;delay(300);}if(alarm_m > 59){alarm_m = 0;} // МИНУТЫ БУДИЛЬНИКА
    if(digitalRead(11) == HIGH){alarm_h++;delay(500);}if(alarm_h > 23){alarm_h = 0;} // ЧАСЫ БУДИЛЬНИКА
    w = 0;}
    На примере этой строчки где устанавливаеться время для будильника, тока устанавливать текущее время

  4. if(menu == 7){y = true;x = 0x00;k = set_Year; //выводим на индикатор год
    if(digitalRead(12) == HIGH){set_Year++;delay(300);}if(set_Year > 2100){set_Year = 2019;}
    if(digitalRead(11) == HIGH){set_Year—;delay(300);}if(set_Year 23){set_h = 0;}
    if(digitalRead(11) == HIGH){set_h—;delay(300);}if(set_h 59){set_min = 0;}
    if(digitalRead(11) == HIGH){set_min—;delay(300);}if(set_min < 0){set_min = 59;} w = 0;}
    if(w==0)
    после 4 пункта меню перестает листать, походу что то не так сделал, как будто виснет

  5. if(menu == 7){y = true;x = 0x00;k = set_Year; //выводим на индикатор год
    if(digitalRead(12) == HIGH){set_Year++;delay(300);}if(set_Year > 2100){set_Year = 2019;}
    if(digitalRead(11) == HIGH){set_Year—;delay(300);}if(set_Year 23){set_h = 0;}
    if(digitalRead(11) == HIGH){set_h—;delay(300);}if(set_h 59){set_min = 0;}
    if(digitalRead(11) == HIGH){set_min—;delay(300);}if(set_min < 0){set_min = 59;} w = 0;}
    if(w==0)
    точнее вот, там ошибочно скопировал

    1. Так работать не будет, лучше вывести настройку времени из меню и добавить еще одну кнопку:
      в setup() добавить кнопку заменив строку:
      pinMode(6,INPUT);pinMode(10,INPUT);pinMode(11,INPUT);pinMode(12,INPUT);
      на
      pinMode(6,INPUT);pinMode(10,INPUT);pinMode(11,INPUT);pinMode(12,INPUT);pinMode(9,INPUT);// добавим кнопку на вход 9

      далее добавим отработку новой кнопки в раздел loop() (в начало раздела)
      if(digitalRead(9) == HIGH){menu1++;delay(300);if(menu1 > 3){menu1 = 0;}} // ПЕРЕБОР настроек редактирования времени
      // menu1 = 1 — установка года
      // menu1 = 2 — установка месяца и даты
      // menu1 = 3 — установка часов и минут
      // menu1 = 0 — корректировка времени не активна

      // корректировка года

      if(menu1 == 1){y = true;x = 0x00;k = set_y; //выводим на индикатор год
      if(digitalRead(12) == HIGH){set_y++;delay(300);}if(set_y > 2100){set_y = 2019;}
      if(digitalRead(11) == HIGH){set_y—;delay(300);}if(set_y < 2019){set_y= 2019;} w1 = 0;}

      // корректировка месяца и даты

      if(menu1 == 2){y = true;x = 0x00;k = set_mon*100+set_d; //выводим на индикатор месяц и день
      if(digitalRead(12) == HIGH){set_mon++;delay(300);}if(set_mon > 12){set_mon = 1;}// прибавляет месяц
      if(digitalRead(11) == HIGH){set_d++;delay(300);}if(set_d > 31){set_d= 1;} // прибавляем дату
      w1 = 0;}

      // корректировка часов и минут

      if(menu1 == 3){y = true;x = 0x40;k = set_h*100+set_m; //выводим на индикатор часы и минуты
      if(digitalRead(12) == HIGH){set_h++;delay(300);}if(set_h > 24){set_h = 0;}// прибавляет часы
      if(digitalRead(11) == HIGH){set_m++;delay(300);}if(set_m > 59){set_m= 0;} // прибавляем минуты
      w1 = 0;}

      // записываем в память часов новые значения времени

      if(w1==0){clock.setDateTime(set_y, set_mon, set_d, set_h, set_m, 0);w1=1;}

      // разграничение menu1 и menu
      // заменяем строку
      if(menu == 3 || menu == 5 || menu == 1){}else{display.showNumberDecEx(k,x,y);}
      на новую
      if(menu1>0){display.showNumberDecEx(k,x,y);}
      if(menu1==0){if(menu == 3 || menu == 5 || menu == 1){}else{display.showNumberDecEx(k,x,y);}}

      перед разделом setup() добавим новые переменные:

      int set_y,set_mon,set_d,set_h,set_m;// год, месяц, дата, часы и минуты
      int menu1,w1;

      Должно вроде как все работать, но надо тестировать.

  6. спасибо получилось, работает, тока единственное при заливке скетча часы не идут пока не установишь время и после отключения питания все по новой приходиться настраивать время и дату

Добавить комментарий

Войти с помощью: