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

Урок 18. Подключение RTC часы реального времени с кнопками

В этом уроке мы научимся не только выводить, но и устанавливать время RTC модуля при помощи трёх кнопок.

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

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

  • Библиотека 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.

Схема подключения RTC к Arduino Uno

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

При подключении библиотеки «iarduino_RTC» нужно указать, с каким модулем ей работать, в данном случае это модуль Trema на базе чипа DS1307:

#include <iarduino_RTC.h>               // подключаем библиотеку для работы с RTC модулем
iarduino_RTC time(RTC_DS1307);          // объявляем переменную time для работы с библиотекой, указывая название модуля RTC_DS1307
void setup() {
  time.begin();                         // инициируем RTC модуль
}

Аналогичный алгоритм действий при подключении библиотеки «LiquidCrystal_I2C» для работы с LCD дисплеем LCD1602 IIC/I2C(синий) или LCD1602 IIC/I2C(зелёный):

#include <Wire.h>                       // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>          // подключаем библиотеку для работы с LCD дисплеем
LiquidCrystal_I2C lcd(0x27,16,2);       // объявляем  переменную lcd для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
void setup() {
  lcd.init();                           // инициируем LCD дисплей
  lcd.backlight();                      // включаем подсветку LCD дисплея
}

Осталось подключить 3 кнопки: «SET», «UP» и «DOWN». Для этого им нужно назначить номера выводов и указать, что эти выводы работают как вход:

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
void setup() {
  pinMode(PIN_button_SET,  INPUT);      // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_UP,   INPUT);      // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_DOWN, INPUT);      // устанавливаем режим работы вывода кнопки, как "вход"
}

В библиотеке «iarduino_RTC», для работы с датой и временем реализованы две функции: settime() - установка и gettime() - получение времени.

Установка времени:

time.settime(0,1,2,3,4,5,6);            // установить время: 00 сек, 01 мин, 02 часа, 03 день, 04 месяц, 05 год, 06 день недели - суббота
// Если указать отрицательное значение, то соответствующий параметр останется без изменений.
// Например: time.settime(10,20,-1,-1,-1,-1,-1); приведёт к изменению секунд и минут, а часы и дата останутся без изменений

Получение времени:

time.gettime("d-m-Y, H:i:s, D");        // получить время в виде строки. Получим: "03-04-2005, 02:01:00, Sat"
// Функция получает строку с символами, заменяет символы на дату и время, и возвращает строку
// Какие символы на что заменяются можно посмотреть в файле iarduino_RTC.h

В библиотеке «iarduino_RTC» доступны 9 числовых переменных: seconds, minutes, hours, Hours, midday, day, weekday, month и year, значения которых обновляются после каждого вызова функции gettime(). Эти переменные мы будим использовать для изменения даты и времени.

int i = time.month;                     // если в часах установлен месяц май, то i будет равно 5 (пятый месяц)

Еще одна функция библиотеки «iarduino_RTC», которая нам понадобится, это blinktime(), она заставляет функцию gettime(), мигать одним из параметров времени (0 - не мигать, 1 - мигать секундами, 2 - мигать минутами, 3 - мигать часами, 4 - мигать днями и т.д.).

time.blinktime(4);                      // функция gettime() будет выводить строки с "мигающими" днями

И последнее, о чем надо позаботиться перед созданием кода программы - это алгоритм работы кнопок и определение переменных

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

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

Исходя из алгоритма, нам понадобятся две переменные, назовем их: VAR_mode_SHOW и VAR_mode_SET. Первая будет указывать режим вывода (1-выводим_время, 2-выводим_дату). Вторая, будет указывать режим установки времени (0-нет, 1-сек, 2-мин, 3-час, 4-день, 5-мес, 6-год, 7-д.н.).

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

// Подключаем библиотеки:
#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
      uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата
      uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
void setup() {
  pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  delay(300);                                // ждем 300мс
  time.begin();                              // инициируем RTC модуль
  lcd.init();                                // инициируем LCD дисплей
  lcd.backlight();                           // включаем подсветку LCD дисплея
}
void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
      lcd.setCursor(0, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print("iArduino.ru");              // выводим текст "iArduino.ru"
      lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
    if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
      lcd.print(time.gettime("H:i:s"));      // выводим время
    }
    if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
      lcd.print(time.gettime("d-m-Y   D"));  // выводим дату
    }
    delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
  }
  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
      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;
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}            // ждём пока мы её не отпустим
      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;
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){                        // ждём пока мы её не отпустим
        delay(10);
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      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;}  // возвращаемся к первому устанавливаемому параметру
      }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
        VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
      }
    }
//Если часы находятся в режиме вывода даты/времени
  }else{
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){delay(10);              // ждём пока мы её не отпустим
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        lcd.clear();                                             // стираем экран
        VAR_mode_SHOW=VAR_mode_SHOW==1?2:1;                      // меняем режим вывода: дата/время
      }else{                                                     // если 
        if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени, то устанавливаемый параметр - секунды
        if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,    то устанавливаемый параметр - день
      }
    }
  }
}

Скачать

Разберемся в данном коде:

  • сначала мы подключили библиотеки Wire.h, LiquidCrystal_I2C.h и iarduino_RTC.h
  • далее объявили константы: PIN_button_SET=2, PIN_button_UP=3, PIN_button_DOWN=4, указав им номера выводов с кнопками
  • объявили две переменные: VAR_mode_SHOW=1 (режим вывода времени) и VAR_mode_SET=0 (без установки времени)
  • в функции setup(): указали выводам с кнопками работать как вход, инициировали модули LCD и RTC, включили подсветку дисплея
  • в функции loop(): циклически выполняем следующую последовательность:
    • каждую секунду выводим текст "iArduino"
    • каждую секунду, если переменная VAR_mode_SHOW равна 1, то выводим время: lcd.print(time.gettime("H:i:s"));
    • каждую секунду, если переменная VAR_mode_SHOW равна 2, то выводим дату: lcd.print(time.gettime("d-m-Y D"));
    • каждую секунду, приостанавливаем выполнение на 1мс
    • при каждом цикле вызываем функцию Func_buttons_control(); которая следит за нажатием кнопок
  • в функции Func_buttons_control(): выполняем следующую последовательность:
    • если VAR_mode_SET больше 0, то мигаем устанавливаемым параметром time.blinktime(VAR_mode_SET);
    • проверяем не находимся ли мы в режиме установки даты/времени
    • в любом случае проверяем не нажаты ли кнопки: if(digitalRead(PIN_button_???)){...}
    • если кнопки нажаты, то ждем пока они не будут отпущены: while(digitalRead(PIN_button_???)){...}
    • после того как кнопка была отпущена, выполняем действия связанные с её предназначением в текущем режиме

Ссылки:




Обсуждение

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