В этом уроке мы научимся не только выводить, но и устанавливать время RTC модуля при помощи трёх кнопок.
Нам понадобится:
- Arduino х 1шт.
- RTC модуль Trema на базе чипа DS1307 х 1шт.
- LCD дисплей LCD1602 IIC/I2C(синий) или LCD1602 IIC/I2C(зелёный) х 1шт.
- Trema Shield х 1шт.
- Trema-модуль i2C Hub х 1шт.
- Trema-модуль кнопка c проводами х 3шт.
- Шлейф «мама-мама»для шины I2С х 2шт.
Для реализации проекта нам необходимо установить библиотеки:
- Библиотека 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.
Код программы:
При подключении библиотеки «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_???)){...}
- после того как кнопка была отпущена, выполняем действия связанные с её предназначением в текущем режиме



Обсуждение