Модуль используется для создания часов а также устройств, для работы которых требуется знание текущего времени.
Внешний вид модуля:
Для работы модуля требуется батарейка CR2032. Такие батарейки или аккумуляторы стоят обычно в материнских платах компьютеров.
С Arduino модуль работает по протоколу I2C. Для его использования требуется подключить контакты GND и VCC к контактам земли и 5V, а контакты SCL и SDA — к соответствующим контактам платы arduino. В зависимости от того, какую плату вы используете, контакты будут разные:
| Плата | Пин SDA | Пин SCL |
|---|---|---|
| Uno, Nano | A4 | A5 |
| Mega2560 | 20 | 21 |
| Leonardo | 2 | 3 |
| Due | 20, SDA1 | 21, SCL1 |
Подключаем модуль к Arduino Uno
После того, как мы вставили батарейку и подключили модуль, нужно установить время. Достаточно сделать это 1 раз и далее модуль будет «тикать», пока не сядет заряд батарейки. Загрузите и запустите следующий скетч (не забыв поставить все необходимые библиотеки):
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
const char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
tmElements_t tm;
void setup()
{
bool parse = false;
bool config = false;
if (getDate(__DATE__) && getTime(__TIME__)) {
parse = true;
if (RTC.write(tm)) {
config = true;
}
}
Serial.begin(9600);
while (!Serial);
delay(200);
if (parse && config) {
Serial.print("DS1307 configured Time=");
Serial.print(__TIME__);
Serial.print(", Date=");
Serial.println(__DATE__);
} else if (parse) {
Serial.println("DS1307 Communication Error :-{");
Serial.println("Please check your circuitry");
} else {
Serial.print("Could not parse info from the compiler, Time="");
Serial.print(__TIME__);
Serial.print("", Date="");
Serial.print(__DATE__);
Serial.println(""");
}
}
void loop()
{
}
bool getTime(const char *str)
{
int Hour, Min, Sec;
if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) {
return false;
}
tm.Hour = Hour;
tm.Minute = Min;
tm.Second = Sec;
return true;
}
bool getDate(const char *str)
{
char Month[12];
int Day, Year;
uint8_t monthIndex;
if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) {
return false;
}
for (monthIndex = 0; monthIndex < 12; monthIndex++) {
if (strcmp(Month, monthName[monthIndex]) == 0) {
break;
}
}
if (monthIndex >= 12) {
return false;
}
tm.Day = Day;
tm.Month = monthIndex + 1;
tm.Year = CalendarYrToTm(Year);
return true;
}
Откройте мониторинг порта и если вы увидели сообщение «DS1307 configured Time=…», значит все получилось и в модуль было прописано текущее время, в качестве которого было взято время компиляции.
Теперь можно запустить второй скетч, который запросит текущее время у модуля и выведет его в консоль:
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
void setup()
{
Serial.begin(9600);
while (!Serial);
delay(200);
}
void loop()
{
tmElements_t tm;
if (RTC.read(tm)) {
Serial.print("Ok, Time = ");
print2digits(tm.Hour);
Serial.write(':');
print2digits(tm.Minute);
Serial.write(':');
print2digits(tm.Second);
Serial.print(", Date (D/M/Y) = ");
Serial.print(tm.Day);
Serial.write('/');
Serial.print(tm.Month);
Serial.write('/');
Serial.print(tmYearToCalendar(tm.Year));
Serial.println();
} else {
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
} else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
delay(9000);
}
delay(1000);
}
void print2digits(int number) {
if (number >= 0 && number < 10) {
Serial.write('0');
}
Serial.print(number);
}
Видим строчку «Ok, Time = 18:32:49, Date (D/M/Y) = 13/2/2019» — все получилось. Ну а далее, например, добавив 7-сегментный дисплей, мы можем собрать часы.
Купить модуль часов можно здесь, здесь или здесь, но учтите, что шину контактов припаять придется самому.
Для ленивых есть шилд для Arduino uno с модулем часов, но он не такой миниатюрный.
Батарейки формата CR2032 можно купить в и магазине, но проще заказать сразу 10 или 20 штук.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <Wire.h> | |
| #include <TimeLib.h> | |
| #include <DS1307RTC.h> | |
| void setup() { | |
| Serial.begin(9600); | |
| while (!Serial) ; // wait for serial | |
| delay(200); | |
| Serial.println(«DS1307RTC Read Test«); | |
| Serial.println(«——————-«); | |
| } | |
| void loop() { | |
| tmElements_t tm; | |
| if (RTC.read(tm)) { | |
| Serial.print(«Ok, Time = «); | |
| print2digits(tm.Hour); | |
| Serial.write(‘:‘); | |
| print2digits(tm.Minute); | |
| Serial.write(‘:‘); | |
| print2digits(tm.Second); | |
| Serial.print(«, Date (D/M/Y) = «); | |
| Serial.print(tm.Day); | |
| Serial.write(‘/‘); | |
| Serial.print(tm.Month); | |
| Serial.write(‘/‘); | |
| Serial.print(tmYearToCalendar(tm.Year)); | |
| Serial.println(); | |
| } else { | |
| if (RTC.chipPresent()) { | |
| Serial.println(«The DS1307 is stopped. Please run the SetTime«); | |
| Serial.println(«example to initialize the time and begin running.«); | |
| Serial.println(); | |
| } else { | |
| Serial.println(«DS1307 read error! Please check the circuitry.«); | |
| Serial.println(); | |
| } | |
| delay(9000); | |
| } | |
| delay(1000); | |
| } | |
| void print2digits(int number) { | |
| if (number >= 0 && number < 10) { | |
| Serial.write(‘0‘); | |
| } | |
| Serial.print(number); | |
| } |
Купил на Ebay из Китая модуль часов реального времени на базе DS1307 — http://www.ebay.com/itm/130962277743.
Теперь вот пытаюсь работать с ними, но получается какой-то бред.
Вот код моей библиотеки:
#define DS1307_ADDR 0xD0
uint8_t ds1307_read(uint8_t reg) {
i2c_start(DS1307_ADDR);
i2c_write(reg);
i2c_start(DS1307_ADDR + 1);
uint8_t result = i2c_read(1);
i2c_stop();
return result;
}
void ds1307_write(uint8_t reg, uint8_t value) {
i2c_start(DS1307_ADDR);
i2c_write(reg);
i2c_write(value);
i2c_stop();
}
uint8_t bcd2bin(uint8_t value) {
return (value / 16) * 10 + (value % 16);
}
uint8_t bin2bcd(uint8_t value) {
return (value / 10) * 16 + (value % 10);
}
void ds1307_get_datetime(uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *year, uint8_t *month, uint8_t *day) {
*second = bcd2bin(ds1307_read(0));
*minute = bcd2bin(ds1307_read(1));
*hour = bcd2bin(ds1307_read(2));
*day = bcd2bin(ds1307_read(4));
*month = bcd2bin(ds1307_read(5));
*year = bcd2bin(ds1307_read(6));
}
void ds1307_set_datetime(uint8_t hour, uint8_t minute, uint8_t second, uint8_t year, uint8_t month, uint8_t day, uint8_t dow) {
ds1307_write(0, bin2bcd(second));
ds1307_write(1, bin2bcd(minute));
ds1307_write(2, bin2bcd(hour));
ds1307_write(3, bin2bcd(dow));
ds1307_write(4, bin2bcd(day));
ds1307_write(5, bin2bcd(month));
ds1307_write(6, bin2bcd(year));
}
Функции I2C точно работают нормально (я их уже использовал для общения с 3-мя разными датчиками без глюков).
А тут получается ерунда какая-то. После старта МК я вызываю ds1307_set_datetime со временем зашитым в исходник. Затем каждую секунду читаю данные с помощью ds1307_get_datetime и смотрю на них. И… часы стоят на месте на том времени, которое я выставил. Затем время сдвигается на 10 секунд. И так далее — время обновляется раз в 10 секунд. Но это ещё ладно, ко времени иногда может не прибавится, а отняться 10 секунд. И вообще ведёт себя странно. Если убрать с начала программы установку времени и переткнуть питание схемы, то часы начинают ходить нормально… но по совершенно другому времени, не тому которое я ставил. Причём оно то отображается нормально. И несмотря на все мои попытки перезаписи, если убрать перезапись при старте это время нормально считается дальше.
То есть часы считают какое-то своё время и нормально его выдают. А если я перезаписываю, то вывод времени начинает глючить, однако то время по-прежнему считается нормально (просто не выводится).
Где я ошибся?
Изменено 22 февраля, 2014 пользователем kiv.apple
Часы реального времени (Real Time Clock, RTC) — это электронная схема, специально предназначенная для учета текущего времени, даты, дня недели и прочих временных и календарных данных. Широко используются в системах регистрации данных, при создании электронных часов, будильников, таймеров, управляющих устройств, работающих по расписанию. Как правило, такая схема, помимо учитывающего устройства включает и автономный источник питания, чтобы продолжать работать даже при выключении основной системы. Часы реального времени ведут учет в единицах измерения времени, более привычных человеку (часы, минуты, годы и пр.), в отличие от тактовых генераторов и счетчиков, которые создают и считают просто «тики». Можно сказать, что часы реального времени — это тактовый генератор, специально предназначенный для отсчета времени.
Зачастую, микроконтроллеры, включая и Arduino, имеют функции для хранения времени, такие как millis () и имеют аппаратные таймеры, которые могут отслеживать более длительные временные интервалы, например, минуты и дни. Так зачем же нужны отдельные схемы часов реального времени?
Основная причина кроется в том, что millis () отслеживает время, прошедшее с момента последнего включения Arduino, при включении таймер миллисекунд устанавливается в ноль. Arduino не знает «вторник» сегодня или «23 февраля», все что ему известно, так это то, что с момента последнего включения прошло, например, 14763 миллисекунды.
Что если мы захотим установить время на Arduino? В программе нужно было бы задать некоторую точку отсчета, относительно которой бы считать время и даты. Но при отключении питания время бы сбросилось. Именно это и происходит в недорогих моделях будильников, когда при отключении питания начинает мигать «12:00». Для каких-то задач это вполне приемлемо, но в некоторых случаях важно продолжать отсчет времени, даже если питание пропадает. Вот в этом случае на помощь и приходят специализированные микросхемы RTC, имеющие автономный источник питания.
Большинство схем часов реального времени использует кварцевый резонатор, работающий на частоте 32768 Гц. 32768 = 215 тактов в секунду, что очень удобно для простых двоичных счётчиков.
Многие производители выпускают собственные микросхемы часов реального времени. Среди них Texas Instruments, Dallas Semocinductor, STMicroelectronics, Intersil, Maxim, Philips. Достаточно популярными являются микросхемы DS1307 от Dallas Semiconductor и ее полный, но более дешевый аналог M41T56 от STMicroelectronics. Также широко используется микросхема DS3231, которая имеет встроенный кварц и термостабилизацию, что позволяет получить повышенную точность в сравнении с DS1307. С точки зрения программиста, отличие между ними — это разные адреса и назначение битов в Control register. Так что, если изменения в программе если и придется вносить, то совсем незначительные.
Я некоторое время назад приобрел модуль MP1095 производства «Мастер Кит», основанный на микросхеме M41T56M6, поэтому я свои эксперименты буду проводить, используя именно этот модуль. Он полностью совместим с устройствами, в основе которых лежит DS1307, что позволяет использовать популярные библиотеки часов реального времени для последнего.
Принципиальная схема модуля MP1095:
Номиналы элементов:
- C1 — 0.1 мкФ
- R2 — 10 кОм
- R3, R4 — 4.7
- DD1 — M41T56M6
- ZQ1 — 32.768 кГц
В качестве автономного источника питания используется литиевая батарейка типа CR2032. Почта Китая запретила к пересылке литиевые элементы питания, поэтому при покупках каких-либо модулей часов реального времени в китайских интернет-магазинах вы не обнаружите их в комплекте. Но это совсем небольшая проблема. «Мастер Кит» — компания российская и батарейка в комплекте шла.
Микросхема M41T56
Микросхема M41T56 представляет собой часы реального времени, с последовательным интерфейсом I2C и низким энергопотреблением с 56 байтами энергонезависимой памяти. Встроенный генератор с частотой 32768 Гц (или же внешний стабилизированный кварцевый) и первые 8 байт ОЗУ используются для временных/календарных функций. Конфигурирование осуществляется в двоично-десятичном формате. Адреса и данные передаются последовательно по двухпроводной двунаправленной шине. Встроенный адресный регистр инкрементируется автоматически после каждой операции WRITE или READ для байта данных.
Часы реального времени M41T56 часы имеют встроенную схему контроля для обнаружения сбоев питания и автоматически переключается на питание от батарей во время сбоя внешнего питания. Энергия, необходимая для поддержания работоспособности оперативной памяти и часов может быть обеспечена при использовании небольшого литиевого элемента питания.
Типичное время хранения данных превышает 10 лет с 50 мА·ч, 3 В литиевым элементом. M41T56 поставляется в 8-выводном пластиковом SOIC-корпусе.
Расположение и назначение выводов
- OSCI — вход кварца
- OCSO — выход кварца
- FT/OUT — тест частоты/выходной драйвер (с открытым стоком)
- SDA — адресная линия вход/выход
- SCL — выход данных
- VBAT — питание от батареи
- VCC — внешний источник питания
- VSS — земля
Блок-схема MT41T56
Операции
Часы реального времени M41T56 работают как ведомое устройство на последовательной шине. Доступ получается реализацие условия запуска, за которым следует правильный адрес ведомого (D0h). К 64 байтам памяти, имеющимся в устройстве, можно получить последовательно доступ в следующем порядке:
- Регистр секунд
- Регистр минут
- Регистр век/часы
- Регистр дня недели
- Регистр даты
- Регистр месяца
- Регистр года
- Управляющий регистр
- ОЗУ
Микросхема постоянно отслеживает VCC на выход за допустимые пределы. Если VCC падает ниже VPFD, устройство прекращает дальнейший доступ и сбрасывает адрес счетчика. Входы устройства не будут признаны в это время, для предотвращения записи ошибочных данных на устройство с отказом от системы допуска. Когда VCC падает ниже VBAT, устройство автоматически переключается на аккумулятор в режим с пониженным энергопотреблением для экономии заряда аккумулятора. После подключения внешнего питания, устройство переключается с батарейного питания VBAT на VCC и считывает входы при превышении VCC в вольтах над VPFD.
В микросхеме имеется программируемый генератор прямоугольных импульсов, позволяющий вырабатывать одну из четырех частот (1 гц, 4096 Гц, 8192 Гц или 32768 Гц).
Полная версия datasheet на M41T56
478.2 KiB
480 Downloads
Детали
Библиотеки Arduino для работы с RTC
Для работы с часами реального времени, в основе которых лежит микросхема DS1307 или аналогичные потребуются специальные библиотеки
1. Библиотека Time (оф.сайт)
25.2 KiB
3099 Downloads
Детали
2. Библиотека DS1307RTC (оф.сайт)
Для установки скачиваем файлы и переносим их в папку с библиотеками. Также можно устанавливать библиотеки, используя менеджер библоитек. Подробнее об установке библиотек в среде Arduino IDE можно почитать здесь.
Подключение модуля MP1095 к Arduino
Для подключения к Arduino Mega 2560 различных устройств и датчиков я использую шилд под названием MEGA Sensor. И для использования шины I2C на нем выведены отдельные пины. Очень удобно, надо сказать.
Дешево китайский клон Arduino Mega 2560 можно купить, например, здесь. Недорогой аналог шилда, позволяющий подключать множество устройств к Arduino Mega продается здесь.
На плате Arduino Mega дополнительные пины шины I2C соответствуют аналоговым выводам 20 и 21 (тоже самое справедливо и для Arduino Due). Для Arduino Uno это выводы 4 и 5, 2 и 3 в случае Arduino Leonardo. Ориентироваться нужно на названия пинов SDA и SCL.
- VDD используется для питания микросхемы RTC для получения с него временных данных. Если напряжение +5 В отсутствует, микросхема переходит в спящий режим для сохранения и отсчета времени.
- GND — земля (общий провод)
- SCL — тактирующий вывод I2C интерфейса (нужен для коммуникации с часами реального времени)
- SDA — вывод данных I2C интерфейса (нужен для коммуникации с RTC)
- SQW (на некоторых аналогичных модулях RTC) — дополнительный выход прямоугольного сигнала частотой 32768 Гц. В большинстве случаев не используется.
Подключите аналоговый 20 пин Arduino Mega (аналоговый 4 пин для других плат Arduino) к выводу SDA модуля и 21 пин (5 — для других плат) к выводу SCL.
Тестируем часы реального времени
Первым делом посмотрим тестовый скетч, который считывает время с модуля RTC один раз в секунду. Также выясним, что произойдет, если снять батарею и заменить ее, что заставляет часы реального времени сбросится. Прежде всего, снимем батарею при отключенном питании Arduino. Подождем 3 секунды и вернем батарею на место. Это приведет к сбросу RTC.
Выберем пример скетча из меню Arduino IDE → → → и загрузим его в микроконтроллер
Отобразить/скрыть пример кода ReadTest
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
void setup()
{
Serial.begin(9600);
while (!Serial) ; // ожидаем ответа порта
delay(200);
Serial.println("DS1307RTC Read Test");
Serial.println("-------------------");
}
void loop()
{
tmElements_t tm;
if (RTC.read(tm))
{
Serial.print("Ok, Time = ");
print2digits(tm.Hour);
Serial.write(':');
print2digits(tm.Minute);
Serial.write(':');
print2digits(tm.Second);
Serial.print(", Date (D/M/Y) = ");
Serial.print(tm.Day);
Serial.write('/');
Serial.print(tm.Month);
Serial.write('/');
Serial.print(tmYearToCalendar(tm.Year));
Serial.println();
}
else
{
if (RTC.chipPresent())
{
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
}
else
{
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
delay(9000);
}
delay(1000);
}
void print2digits(int number)
{
if (number >= 0 && number < 10)
{
Serial.write('0');
}
Serial.print(number);
}
Откроем окошко монитора последовательного порта и удостоверимся, что установленная скорость передачи соответствует 9600 бод.
У вас должно получиться что-то похожее
Выдается какие-то непонятные дата и время. Всякий раз, когда микросхема RTC обесточивается, происходит обнуление счетчика времени и мы будем наблюдать похожую картину.
Установка времени
Для установки времени воспользуемся другим примером из этой же библиотеки.
Откроем пример → → → и загрузим его в Arduino.
Отобразить/скрыть пример кода SetTime
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
const char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
tmElements_t tm;
void setup()
{
bool parse=false;
bool config=false;
// получаем дату и время на момент компиляции
if (getDate(__DATE__) && getTime(__TIME__))
{
parse = true;
// и конфигурируем RTC используя эту информацию
if (RTC.write(tm))
{
config = true;
}
}
Serial.begin(9600);
while (!Serial) ; // ожидаем ответа порта
delay(200);
if (parse && config)
{
Serial.print("DS1307 configured Time=");
Serial.print(__TIME__);
Serial.print(", Date=");
Serial.println(__DATE__);
}
else if (parse)
{
Serial.println("DS1307 Communication Error :-{");
Serial.println("Please check your circuitry");
}
else
{
Serial.print("Could not parse info from the compiler, Time="");
Serial.print(__TIME__);
Serial.print("", Date="");
Serial.print(__DATE__);
Serial.println(""");
}
}
void loop()
{
}
bool getTime(const char *str)
{
int Hour, Min, Sec;
if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
tm.Hour = Hour;
tm.Minute = Min;
tm.Second = Sec;
return true;
}
bool getDate(const char *str)
{
char Month[12];
int Day, Year;
uint8_t monthIndex;
if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
for (monthIndex = 0; monthIndex < 12; monthIndex++)
{
if (strcmp(Month, monthName[monthIndex]) == 0) break;
}
if (monthIndex >= 12) return false;
tm.Day = Day;
tm.Month = monthIndex + 1;
tm.Year = CalendarYrToTm(Year);
return true;
}
Открыв монитор порта, видим, что время теперь установлено правильно
Вновь вернемся к примеру ReadTest, скомпилируем его, загрузим в микроконтроллер и посмотрим на результат.
Теперь мы видим, что время актуально и часы тикают.
Команды для работы с RTC
1. Чтение текущей даты и времени
RTC.get () — возвращает текущую дату и время в виде 32-битного числа типа time_t
RTC.read (tmElements_t tm) — чтение даты и времени как переменной типа tmElements_t
2. Установка даты и времени
RTC.set (time_t t) — установка даты и времени, используя 32-битное число типа time_t
RTC.write (tmElements_t tm) — установка даты и времени, используя переменную типа tmElements_t
3. Проверка
RTC.chipPresent () — возвращает TRUE, если модуль подключен
Вы можете пропустить чтение записи и оставить комментарий. Размещение ссылок запрещено.
26-02-2020, 16:01
0 комментариев
В статье вы познакомитесь с механизмом подключения часов реального времени DS1307 к Arduino. Этот модуль для обзора мы выбрали не случайно – он популярен, необычайно легок в сборке и использовании, доступен по цене (продается буквально в каждом магазине, онлайн в том числе). Кроме того, он может функционировать без замены батареи на протяжении нескольких лет (в зависимости от производителя микроплаты).
Да и о практичности подобных устройств забывать не стоит. На их основе можно собрать не один интересный проект. В частности, их применяют в качестве элементов для проектирования будильников, сигнализации, снятия показаний с различных датчиков (в режиме реального времени). Главная особенность именно этого RTC-модуля – работа от автономного питания (в случае, если на вашем проекте оно пропало, часы все равно будут работать и не «собьются»).
Технические параметры прибора таковы:
- напряжение питания: 5 V;
- рабочая температура: – 40℃ … + 85℃;
- память: 56 байт;
- тип интерфейса: I2C (двухпроводной);
- 24-х и 12-ти часовой режимы;
- размеры: 28мм х 25мм х 8 мм.
Подключение DS1307 к Arduino
Модуль сочетается со многими платами расширения Ардуино, на которых питание логики равно 5 В. Для реализации нашего проекта понадобится следующее «железо»:
- контроллер Arduino UNO
- USB -кабель (для подключения к персональному компьютеру)
- RTC DS1307
- соединительный провод (перемычки)

Заливаем скетч для установки и проверки времени:
/*
Тестирование производилось на Arduino IDE 1.6.12
Дата тестирования 23.11.2016г.
*/
#include <Wire.h> // Подключаем библиотеку Wire
#include <TimeLib.h> // Подключаем библиотеку TimeLib
#include <DS1307RTC.h> // Подключаем библиотеку DS1307RTC
const char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
tmElements_t tm;
void setup() {
bool parse=false;
bool config=false;
// get the date and time the compiler was run
if (getDate(__DATE__) && getTime(__TIME__)) {
parse = true;
// and configure the RTC with this info
if (RTC.write(tm)) {
config = true;
}
}
Serial.begin(9600);
while (!Serial) ; // wait for Arduino Serial Monitor
delay(200);
if (parse && config) {
Serial.print("DS1307 configured Time=");
Serial.print(__TIME__);
Serial.print(", Date=");
Serial.println(__DATE__);
} else if (parse) {
Serial.println("DS1307 Communication Error :-{");
Serial.println("Please check your circuitry");
} else {
Serial.print("Could not parse info from the compiler, Time="");
Serial.print(__TIME__);
Serial.print("", Date="");
Serial.print(__DATE__);
Serial.println(""");
}
}
void loop() {
}
bool getTime(const char *str)
{
int Hour, Min, Sec;
if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
tm.Hour = Hour;
tm.Minute = Min;
tm.Second = Sec;
return true;
}
bool getDate(const char *str)
{
char Month[12];
int Day, Year;
uint8_t monthIndex;
if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) return false;
for (monthIndex = 0; monthIndex < 12; monthIndex++) {
if (strcmp(Month, monthName[monthIndex]) == 0) break;
}
if (monthIndex >= 12) return false;
tm.Day = Day;
tm.Month = monthIndex + 1;
tm.Year = CalendarYrToTm(Year);
return true;
}
Проверяем себя — открываем монитор последовательного порта (клавиши Ctrl+Shift+M). Там должно отобразиться что-то вроде текста: configured Time=16:38:47 Это означает, что вы все сделали правильно!
В целом программ по работе с часами в сети очень много – можно установить время вручную либо через монитор порта, можно поработать с миганием цифр и в общем – с выводом их на экран. Все в ваших руках! Пробуйте, оценивайте, тестируйте!
Introduction
Sometimes it may be necessary to use a display while making a hardware project, but the size and the type of the display may vary according to the application. In a previous project, we used a 0.96″ I2C OLED display, and in this project we will have an I2C 20×4 character display.
Project Parts
This tutorial will describe how to use 20 x 4 LCD display with Arduino to print a real-time clock and date.
This liquid crystal display has 4 lines, 20 character in each line and cannot be used to display graphics. The main feature of this display that it uses I2C interface, which means that you will need only two wires to connect with Arduino. At the back side of the screen there is a small PCB soldered in the display, this circuit is a serial LCD 20 x 4 module and it also has a small trimpot to adjust the contrast of the LCD.
Display’s backlight is blue and the text is white. It is fully compatible with Arduino and has 5V input voltage. Its I2C address could be 0x27 or 0x3F. You can get it for about $7 from Bangood store.
DS3231 is a low-cost, accurate I2C real-time clock (RTC), with an integrated temperature-compensated crystal oscillator (TCXO) and crystal. The device incorporates a battery input, so that if power is disconnected it maintains accurate time.
RTC maintains seconds, minutes, hours, day, date, month, and year information. Less than 31 days of the month, the end date will be automatically adjusted, including corrections for leap year. The clock operates in either the 24 hours or band / AM / PM indication of the 12-hour format. Provides two configurable alarm clock and a calendar can be set to a square wave output. Address and data are transferred serially through an I2C bidirectional bus.
This RTC module operates at input voltage range between 3.3V and 5.5V, so it can be connected with 3.3V or 5V pins. It is available on Banggood store for about $2.
Connecting the LCD with Arduino UNO
At first we will connect the LCD with Arduino to display some text and to learn how it works.
The Circuit
Connect the GND with Arduino GND, VCC with 5V pin on Arduino, SDA with A4 pin, and finally SCL with A5 pin.

The Code
First we need to download the library of the display, which includes all required functions to configure and write on the display. You can find it here.
Unzip the library and add it to the Arduino libraries folder, then run Arduino IDE and copy the following code. The first two lines are to include both of I2C and LCD libraries.
lcd.setCursor(3,0) will set the cursor of the LCD in the specified location, the first argument for the column and the second for the row starting form 0.
lcd.print(” “) will print the given text at the current cursor position, be careful that the overflowed characters will be discarded.
//Written by Nick Koumaris
//info@educ8s.tv
//educ8s.tv
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
void setup()
{
lcd.begin(20,4); // Initialize LCD
lcd.setCursor(3,0); // Set the cursor at the 4th column and 1st row
lcd.print("Hello YouTube!");
lcd.setCursor(8,1); // Set the cursor at the 9th column and 2nd row
lcd.print("****");
lcd.setCursor(0,2); // Set the cursor at the 1st column and 3rd row
lcd.print("This is a demo text");
lcd.setCursor(8,3); // Set the cursor at the 9th column and 4th row
lcd.print("****");
}
void loop()
{
}
Printing Date & Time on The LCD
Now we will use the RTC module with the LCD to print current date and time, each of them in a line with a dashed border around them.
The Circuit
Here we will use a small breadboard to connect the RTC module and display with the Arduino’s I2C pins (A4 and A5). The SCL pins are connected with analog 5 pin and the SDA pins with analog 6 pin. The top rail of the breadboard used as I2C bus and the bottom one is power bus.
Connect both the display and the RTC module to 5 V and GND pins, and now the circuit is ready.
The Code

In addition to setup and loop function, we will create four other functions to organize the code. As the corners and vertical lines of the frame are special characters, we have to create them manually. So we will use a function to create them and another one to print them on the LCD.
Inside the loop function the time will be read from the real time clock module and the printed to the LCD using a custom function for each of time and date.
Now, let’s describe each part of code:
At first, we have to include the three libraries, I2C, LCD, and RTC and set the LCD address. Inside the setup function the display is initialized, then we will call createCustomCharacters() function and print them.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS1307RTC.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
void setup()
{
lcd.begin(20,4);
createCustomCharacters();
printFrame();
}
Each character can be 5-pixel long in width and 8-pixel in height. So to create a custom character we need to create a new byte. We need 5 characters, the vertical line and the four corners. The yellow pattern shows you how the character will be displayed on the LCD.
Inside createCustomCharacters() function, we called lcd.createChar(#, byte array) function. The LCD supports up to 8 custom characters numbered from 0 to 7. It will assign the index in the first argument to the character given by the byte array. To print this character we can use lcd.write(byte(#)) function.
byte verticalLine[8] = {
B00100,
B00100,
B00100,
B00100,
B00100,
B00100,
B00100,
B00100
};
byte char2[8] = {
B00000,
B00000,
B00000,
B11100,
B00100,
B00100,
B00100,
B00100
};
byte char1[8] = {
B00000,
B00000,
B00000,
B00111,
B00100,
B00100,
B00100,
B00100
};
byte char3[8] = {
B00100,
B00100,
B00100,
B00111,
B00000,
B00000,
B00000,
B00000
};
byte char4[8] = {
B00100,
B00100,
B00100,
B11100,
B00000,
B00000,
B00000,
B00000
};
void createCustomCharacters()
{
lcd.createChar(0, verticalLine);
lcd.createChar(1, char1);
lcd.createChar(2, char2);
lcd.createChar(3, char3);
lcd.createChar(4, char4);
}
Now after preparing our characters we can now print the frame.
This function is very simple, it uses lcd.setCursor(#,#) to move the cursor and lcd.print(“”) to print the given string. The function will print the top and bottom horizontal lines, then printing other custom characters.
void printFrame()
{
lcd.setCursor(1,0);
lcd.print("------------------");
lcd.setCursor(1,3);
lcd.print("------------------");
lcd.setCursor(0,1);
lcd.write(byte(0));
lcd.setCursor(0,2);
lcd.write(byte(0));
lcd.setCursor(19,1);
lcd.write(byte(0));
lcd.setCursor(19,2);
lcd.write(byte(0));
lcd.setCursor(0,0);
lcd.write(byte(1));
lcd.setCursor(19,0);
lcd.write(byte(2));
lcd.setCursor(0,3);
lcd.write(byte(3));
lcd.setCursor(19,3);
lcd.write(byte(4));
}
As we discussed earlier, the loop function will get the current time and date every second and refresh them on the display. First we defined a time element “tm” which has current time data, then if the time is correct and the RTC module working fine the time and date will be printed.
We can add some instructions so, if the DS1307 is stopped or there is a circuit error,we can light a LED to indicate the problem. The loop will wait for 1 second before starting the next iteration.
void loop()
{
tmElements_t tm;
if (RTC.read(tm)) {
printDate(5,1,tm);
printTime(6,2,tm);
} else {
if (RTC.chipPresent()) {
//The DS1307 is stopped. Please run the SetTime
} else {
//DS1307 read error! Please check the circuitry
}
delay(9000);
}
delay(1000);
}
PrintTime function uses three arguments, the column and line where it will print the time, and the time element. lcd.print(tm.Hour) will print the hour, then if the minutes and seconds are less than 10 we will add 0 to the left. And the same method is used to print the date.
void printTime(int character,int line, tmElements_t tm)
{
String seconds,minutes;
lcd.setCursor(character,line);
lcd.print(tm.Hour);
lcd.print(":");
if(tm.Minute<10)
{
minutes = "0"+String(tm.Minute);
lcd.print(minutes);
}else
{
lcd.print(tm.Minute);
}
lcd.print(":");
if(tm.Second<10)
{
seconds = "0"+String(tm.Second);
lcd.print(seconds);
}else
{
lcd.print(tm.Second);
}
}
void printDate(int character,int line, tmElements_t tm)
{
lcd.setCursor(character,line);
lcd.print(tm.Month);
lcd.print("/");
lcd.print(tm.Day);
lcd.print("/");
lcd.print(tmYearToCalendar(tm.Year));
}
Now everything is ready, upload the code to your Arduino and enjoy watching your new clock. You can find the full Arduino sketches and libraries in the attachment below.
This tutorial is made by educ8s.tv channel, and you can find the tutorial video below:





















