КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Урок 19. RTC часы с будильником

В предыдущем уроке 18, мы подключили Trema RTC часы реального времени с Trema кнопками и LCD I2C дисплеем к arduino Uno, написали скетч, для установки времени при помощи кнопок.

Теперь расширим функционал получившихся часов, добавив к ним функцию будильника. А код, который будет выполняться при срабатывании будильника выведем в отдельную функцию "Func_alarm_action()", чтоб Вы смогли легко его найти и изменить. Например, при срабатывании будильника, открывать жалюзи, включать свет или музыку, включить через реле тостер или кофе-машину и т.д.

Нам понадобится:

Для реализации проекта нам необходимо установить библиотеки:

  • Библиотека iarduino_RTC (для подключения RTC часов реального времени DS1302, DS1307, DS3231)
  • Библиотека LiquidCrystal_I2C_V112 (для подключения дисплеев LCD1602 по шине I2C)

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Видео:


Схема подключения:

Подключение модулей RTC и LCD, данного урока, осуществляется к аппаратным выводам SDA, и SCL.

RTC модуль Trema на базе чипа DS1307 / LCD дисплей на базе чипа LCD1602 Arduino Uno
GND GND
Vcc +5V
SDA (Serial DAta) A4
SCL (Serial CLock) A5

Подключение кнопок: кнопка «SET» к выводу 2, кнопка «UP» к выводу 3 и копка «DOWN» к выводу 4.

Зуммер подключаем к выводу 5, а светодиод к выводу 13 (дублируя встроенный в arduino).

RTC часы с будильником на Arduino Uno

Алгоритм работы кнопок следующий:

  • В режиме вывода даты/времени/будильника (обычный режим):
    • Кратковременное нажатие на кнопку SET переключает режимы вывода: даты/времени/будильника
    • Удержание кнопки SET переводит часы в режим установки даты/времени/будильника (зависит от того, каким был режим вывода)
    • Кнопки UP и DOWN, в режиме вывода будильника, активируют/деактивируют будильник.
      Если будильник активен, то в правом верхнем углу экрана появляется значок будильника.
  • В режиме установки даты/времени/будильника:
    • Кратковременное нажатие на кнопку SET - переход между устанавливаемыми параметрами (сек, мин, час, дни, мес, год, д.н.)
    • Удержание кнопки SET выводит часы из режима установки
    • Каждое нажатие на кнопку UP увеличивает значение устанавливаемого параметра даты или времени
    • Каждое нажатие на кнопку DOWN уменьшает значение устанавливаемого параметра даты или времени
  • Во время работы сигнализации будильника:
    • Удержание любой кнопки в течении 1 секунды, отключает сигнализацию (без выполнения их действий, в любом режиме)

Код программы:

Работа кнопок, вывод и установка времени, описывались в уроке 18, в этом уроке рассмотрим работу будильника:

В начале кода добавляем две константы: PIN_alarm_TONE и PIN_alarm_LED, указывающие номера выводов зуммера и светодиода.
А также добавляем четыре переменные: VAR_alarm_MIN, VAR_alarm_HOUR, VAR_alarm_FLAG1 и VAR_alarm_FLAG2.

  • VAR_alarm_MIN - переменная в которой хранится значение минут, при котором сработает будильник (по умолчанию 0 минут)
  • VAR_alarm_HOUR - переменная в которой хранится значение часов, при котором сработает будильник (по умолчанию 0 часов)
  • VAR_alarm_FLAG1 - флаг разрешения работы будильника, false - не активен, true - активен (по умолчанию true - активен)
  • VAR_alarm_FLAG2 - флаг указывающий на то, что будильник сработал "сигнализация" (по умолчанию false - не сработал)

Последняя переменная которую мы добавили - MAS_alarm_SYM, она содержит изображение символа будильника для вывода на дисплей.

В функции loop, после вывода информации на дисплей, добавляем проверку: не пора ли включить будильник?

void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
    ...
    ...
//  проверка будильника
    if(VAR_alarm_FLAG1){                     // если будильник включён
      if(time.seconds==00){                  // если в текущем времени 0 секунд
        if(time.minutes==VAR_alarm_MIN){     // если совпали минуты
          if(time.Hours==VAR_alarm_HOUR){    // если совпали часы
            VAR_alarm_FLAG2=true;            // устанавливаем флаг разрешающий совершение действий будильника (сигнализация)
          }
        }
      }
    }else{VAR_alarm_FLAG2=false;}            // если будильник выключен, то сбрасываем флаг разрешающий совершение действий будильника (сигнализация)
    if(VAR_alarm_FLAG2){Func_alarm_action();}// запускаем действия будильника
  }
  Func_buttons_control();                    // передаём управление кнопкам
}
  • если будильник включён (установлен флаг VAR_alarm_FLAG1)
  • если в текущем времени 0 секунд (time.seconds==00)
  • если количество минут текущего времени (time.minutes) равно количеству минут установленных в будильнике (VAR_alarm_MIN)
  • если количество часов текущего времени (time.Hours) равно количеству часов установленных в будильнике (VAR_alarm_HOUR)
    то устанавливаем флаг VAR_alarm_FLAG2 (указывающий на то, что будильник сработал)
  • если установлен флаг VAR_alarm_FLAG2, то запускаем действия будильника (действия описаны в функции Func_alarm_action)
    Так как проверка будильника и запуск функции Func_alarm_action() находится внутри условия if(millis()%1000==0){...}, то действия будильника будут выполняться один раз в секунду.

Теперь всё готово для создания полного кода:

// Подключаем библиотеки:
#include <Wire.h>                            // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>               // подключаем библиотеку для работы с LCD дисплеем
#include <iarduino_RTC.h>                    // подключаем библиотеку для работы с RTC модулем
LiquidCrystal_I2C lcd(0x27,16,2);            // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
iarduino_RTC time(RTC_DS1307);               // объявляем  переменную для работы с RTC модулем,  указывая название модуля
// Объявляем переменные и константы:
const uint8_t PIN_button_SET  = 2;           // указываем номер вывода arduino, к которому подключена кнопка SET
const uint8_t PIN_button_UP   = 3;           // указываем номер вывода arduino, к которому подключена кнопка UP
const uint8_t PIN_button_DOWN = 4;           // указываем номер вывода arduino, к которому подключена кнопка DOWN
const uint8_t PIN_alarm_TONE  = 5;           // указываем номер вывода arduino, к которому подключён зуммер будильника
const uint8_t PIN_alarm_LED   = 13;          // указываем номер вывода arduino, к которому подключён светодиод
      uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата 3-время_будильника
      uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели 8-мин_будильника 9-час_будильника
      uint8_t VAR_alarm_MIN   = 0;           // будильник минуты
      uint8_t VAR_alarm_HOUR  = 0;           // будильник часы
      bool    VAR_alarm_FLAG1 = true;        // будильник разрешение работы
      bool    VAR_alarm_FLAG2 = false;       // будильник совершение действий (сигнализация)
      byte    MAS_alarm_SYM[8]={B00000,B01110,B10101,B10111,B10001,B01110,B00000,B00000};  // символ будильника для отображения на дисплее
void setup() {
  pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода PIN_button_SET,  как "вход"
  pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода PIN_button_UP,   как "вход"
  pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода PIN_button_DOWN, как "вход"
  pinMode(PIN_alarm_TONE, OUTPUT);           // устанавливаем режим работы вывода PIN_alarm_TONE,  как "выход"
  pinMode(PIN_alarm_LED,  OUTPUT);           // устанавливаем режим работы вывода PIN_alarm_LED,   как "выход"
  digitalWrite(PIN_alarm_TONE, LOW);         // устанавливаем уровень логического «0» на выводе PIN_alarm_TONE
  digitalWrite(PIN_alarm_LED,  LOW);         // устанавливаем уровень логического «0» на выводе PIN_alarm_LED
  delay(300);                                // ждем 300мс
  time.begin();                              // инициируем RTC модуль
  lcd.init();                                // инициируем LCD дисплей
  lcd.backlight();                           // включаем подсветку LCD дисплея
  lcd.createChar(1, MAS_alarm_SYM);          // загружаем символ будильника под номером 1
}
void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
    if(VAR_mode_SET==0){                     // если дата/время/будильник выводятся, а не устанавливаются
      lcd.setCursor(0, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print("iArduino.ru");              // выводим текст "iArduino.ru"
      lcd.setCursor(15, 0);                  // устанавливаем курсор в позицию: столбец 15, строка 0
      lcd.print(VAR_alarm_FLAG1?"\1":" ");   // выводим значёк будильника
    }else{                                   // если дата/время/будильник устанавливаются, а не выводятся
      lcd.setCursor(0, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      if(VAR_mode_SHOW==1){lcd.print("Set time:" );}
      if(VAR_mode_SHOW==2){lcd.print("Set date:" );}
      if(VAR_mode_SHOW==3){lcd.print("Set alarm:");}
    }
    if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
      lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
      lcd.print(time.gettime("H:i:s"));      // выводим время
    }
    if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
      lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
      lcd.print(time.gettime("d-m-Y   D"));  // выводим дату
    }
    if(VAR_mode_SHOW==3){                    // если установлен режим вывода будильника
      lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
      if(VAR_mode_SET==0){lcd.print("Alarm ");}
      time.gettime();                        // обновляем значение переменной time.seconds, для "мигания" устанавливаемым параметром будильника
      if(VAR_mode_SET==9&&time.seconds%2){lcd.print("  ");}else{if(VAR_alarm_HOUR<10){lcd.print("0");} lcd.print(VAR_alarm_HOUR);}
      lcd.print(":");
      if(VAR_mode_SET==8&&time.seconds%2){lcd.print("  ");}else{if(VAR_alarm_MIN<10){ lcd.print("0");} lcd.print(VAR_alarm_MIN);}
    }
    delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
//  проверка будильника
    if(VAR_alarm_FLAG1){                     // если будильник включён
      if(time.seconds==00){                  // если в текущем времени 0 секунд
        if(time.minutes==VAR_alarm_MIN){     // если совпали минуты
          if(time.Hours==VAR_alarm_HOUR){    // если совпали часы
            VAR_alarm_FLAG2=true;            // устанавливаем флаг разрешающий совершение действий будильника (сигнализация)
          }
        }
      }
    }else{VAR_alarm_FLAG2=false;}            // если будильник выключен, то сбрасываем флаг разрешающий совершение действий будильника (сигнализация)
    if(VAR_alarm_FLAG2){Func_alarm_action();}// запускаем действия будильника
  }
  Func_buttons_control();                    // передаём управление кнопкам
}
// Функция управления кнопками:
void Func_buttons_control(){
  uint8_t i=0;
  time.blinktime(VAR_mode_SET);                                    // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
//Если часы находятся в режиме установки даты/времени
  if(VAR_mode_SET){
//  Если нажата кнопка UP
    if(digitalRead(PIN_button_UP  )){
      while(digitalRead(PIN_button_UP)){delay(50);}                // ждём пока мы не отпустим кнопку UP
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
        /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
        /* мин */ case 2: time.settime(-1, (time.minutes==59?0:time.minutes+1), -1, -1, -1, -1, -1); break;
        /* час */ case 3: time.settime(-1, -1, (time.Hours==23?0:time.Hours+1),     -1, -1, -1, -1); break;
        /* дни */ case 4: time.settime(-1, -1, -1, (time.day==31?1:time.day+1),         -1, -1, -1); break;
        /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==12?1:time.month+1),     -1, -1); break;
        /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==99?0:time.year+1),       -1); break;
        /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==6?0:time.weekday+1) ); break;
        /* м.б.*/ case 8: VAR_alarm_MIN =VAR_alarm_MIN ==59?0:VAR_alarm_MIN +1;                      break;
        /* ч.б.*/ case 9: VAR_alarm_HOUR=VAR_alarm_HOUR==23?0:VAR_alarm_HOUR+1;                      break;
        }
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}              // ждём пока мы её не отпустим
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        switch (VAR_mode_SET){                                     // декремент (уменьшение) устанавливаемого значения
        /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
        /* мин */ case 2: time.settime(-1, (time.minutes==0?59:time.minutes-1), -1, -1, -1, -1, -1); break;
        /* час */ case 3: time.settime(-1, -1, (time.Hours==0?23:time.Hours-1),     -1, -1, -1, -1); break;
        /* дни */ case 4: time.settime(-1, -1, -1, (time.day==1?31:time.day-1),         -1, -1, -1); break;
        /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==1?12:time.month-1),     -1, -1); break;
        /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==0?99:time.year-1),       -1); break;
        /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==0?6:time.weekday-1) ); break;
        /* м.б.*/ case 8: VAR_alarm_MIN =VAR_alarm_MIN ==0?59:VAR_alarm_MIN -1;                      break;
        /* ч.б.*/ case 9: VAR_alarm_HOUR=VAR_alarm_HOUR==0?23:VAR_alarm_HOUR-1;                      break;
        }
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){                          // ждём пока мы её не отпустим
        delay(10);
        if(i<200){i++;}else{lcd.clear();}                          // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
          VAR_mode_SET++;                                          // переходим к следующему устанавливаемому параметру
          if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;}  // возвращаемся к первому устанавливаемому параметру
          if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;}  // возвращаемся к первому устанавливаемому параметру
          if(VAR_mode_SHOW==3 && VAR_mode_SET>9){VAR_mode_SET=8;}  // возвращаемся к первому устанавливаемому параметру
        }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
          VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
        }
      }
    }
//Если часы находятся в режиме вывода даты/времени
  }else{
//  Если нажата кнопка UP
    if(digitalRead(PIN_button_UP  )){
      while(digitalRead(PIN_button_UP)){delay(50);}                // ждём пока мы её не отпустим
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        if(VAR_mode_SHOW==3){VAR_alarm_FLAG1=VAR_alarm_FLAG1?0:1;} // если установлен режим вывода будильника, то включаем/выключаем будильник
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}              // ждём пока мы её не отпустим
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        if(VAR_mode_SHOW==3){VAR_alarm_FLAG1=VAR_alarm_FLAG1?0:1;} // если установлен режим вывода будильника, то включаем/выключаем будильник
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){delay(10);                // ждём пока мы её не отпустим
        if(i<200){i++;}else{lcd.clear();}                          // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(VAR_alarm_FLAG2){VAR_alarm_FLAG2=false;}else{             // если будильник сработал, то выключаем его
        if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
          lcd.clear();                                             // стираем экран
          VAR_mode_SHOW++; if(VAR_mode_SHOW>3){VAR_mode_SHOW=1;}   // меняем режим вывода: дата/время/будильник
        }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется перейти в режим установки даты/времени
          if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени,    то устанавливаемый параметр - секунды
          if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,       то устанавливаемый параметр - день
          if(VAR_mode_SHOW==3){VAR_mode_SET=8;}                    // если установлен режим вывода будильника, то устанавливаемый параметр - минуты_будильника
        }
      }
    }
  }
}
// Функция выполняющая действия будильника:
void Func_alarm_action(){
    digitalWrite(PIN_alarm_LED, HIGH);
    tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE); delay(100);
    tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE); delay(100);
    tone(PIN_alarm_TONE, 2000); delay(100); noTone(PIN_alarm_TONE);
    digitalWrite(PIN_alarm_LED, LOW);
}

Скачать

Разберемся в коде действий будильника:

Действия будильника описаны в функции Func_alarm_action().

В этой функции мы включаем светодиод, далее подаём три коротких звуковых сигнала (с частотой 2000Гц, длительностью и паузой 100мс), после чего выключаем светодиод.

Если Вам необходимо выполнить действие будильника однократно, а не каждую секунду после его срабатывания, то начните выполнение действий со сброса флага VAR_alarm_FLAG2, присвоив ему значение false.

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями