Ds1307 — часы реального времени arduino
Содержание
Проблемы
Да, этот код рабочий, и часы будут идти. Однако, если отключить питание, а через несколько минут включить, то после включения время время вновь станет тем, которое было при компиляции.
Это происходит потому что после включения питания, вновь исполняется код, находящийся в функции . А он записывает в часы реального времени старое значение времени.
Чтобы этого избежать, нам необходимо еще чуть-чуть модифицировать код. Каждый раз в функции будет происходить подсчет «хэша» времени компиляции — будет рассчитываться количество секунд, прошедшее с 00:00:00 до времени компиляции. И этот хэш будет сравниваться с хэшем в EEPROM. Напомним EEPROM — память, которая не обнуляется при отключении питания.
Если значения посчитанного и сохранённого ранее хэша совпадают, то это значит, что перезаписывать время в модуль часов нет необходимости: это уже было сделано. А вот если эта проверка не проходит, то происходит перезапись времени в RTC.
Для записи/чтения числа типа в/из EEPROM написаны две дополнительные функции и . Они добавлены потому что функции и могуть читать и писать только данные типа .
- rtc-eeprom.ino
-
#include <Wire.h> #include <EEPROM.h> #include "TM1637.h" #include "DS1307.h" //Массив, содержащий время компиляции char compileTime = __TIME__; //Номера пинов Arduino, к которым подключается индикатор #define DISPLAY_CLK_PIN 12 #define DISPLAY_DIO_PIN 13 //Для работы с микросхемой часов и индикатором мы используем библиотеки TM1637 display(DISPLAY_CLK_PIN, DISPLAY_DIO_PIN); DS1307 clock; void setup() { //Включаем и настраиваем индикатор display.set(); display.init(); //Запускаем часы реального времени clock.begin(); //Получаем число из строки, зная номер первого символа byte hour = getInt(compileTime, ); byte minute = getInt(compileTime, 3); byte second = getInt(compileTime, 6); //Импровизированный хэш времени //Содержит в себе количество секунд с начала дня unsigned int hash = hour * 60 * 60 + minute * 60 + second; //Проверяем несовпадение нового хэша с хэшем в EEPROM if (EEPROMReadInt() != hash) { //Сохраняем новый хэш EEPROMWriteInt(, hash); //Готовим для записи в RTC часы, минуты, секунды clock.fillByHMS(hour, minute, second); //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock.setTime(); } } void loop() { //Значения для отображения на каждом из 4 разрядов int8_t timeDisp4; //Запрашиваем время с часов clock.getTime(); //Получаем десятки часов с помощью целочисленного деления timeDisp = clock.hour 10; //Получаем единицы часов с помощью остатка от деления timeDisp1 = clock.hour % 10; //Проделываем то же самое с минутами timeDisp2 = clock.minute 10; timeDisp3 = clock.minute % 10; //... а затем выводим его на экран display.display(timeDisp); //у нас нет отдельных разрядов для секунд, поэтому //будем включать и выключать двоеточие каждую секунду display.point(clock.second % 2 ? POINT_ON POINT_OFF); } char getInt(const char* string, int startIndex) { return int(stringstartIndex - '0') * 10 + int(stringstartIndex+1) - '0'; } //Запись двухбайтового числа в память void EEPROMWriteInt(int address, int value) { EEPROM.write(address, lowByte(value)); EEPROM.write(address + 1, highByte(value)); } //Чтение числа из памяти unsigned int EEPROMReadInt(int address) { byte lowByte = EEPROM.read(address); byte highByte = EEPROM.read(address + 1); return (highByte << 8) | lowByte; }
Описание компонентов
В нашем проекте мы используем:
- Arduino Uno
- Troyka Shield
-
Четырёхразрядный цифровой индикатор
- Часы реального времени
- Батарейку CR1225
Часы реального времени
Мы используем модуль с часами реального времени от Seeed Studio. Они построены на базе микросхемы DS1307 от Maxim Integrated. Из элементов обвязки она требует три резистора, часовой кварц и батарейку, которые уже имеются на данном модуле. Модуль обладает следующими свойствами:
- Подсчет времени (секунды, минуты, часы), даты (год, месяц, число), дня недели
- Двухпроводной интерфейс I²C
Суть часов реального времени в том, что при наличии батарейки, они могут идти даже если основное устройство обесточено. Мы с такими часами сталкиваемся постоянно в ноутбуках или цифровых фотоаппаратах. Если достать из этих устройств аккумулятор, а через некоторое время вернуть их обратно, то время не сбросится. В этом заслуга часов реального времени, Real Time Clock (RTC).
Индикатор
Мы используем четырёхразрядный индикатор от Seeed Studio. Основное в индикаторе — микросхема TM1637, представляющая собой драйвер для отдельных 7-сегментных разрядов. В данном модуле используется 4 разряда. Модуль обладает следующими свойствами:
- 8 градаций яркости
- Двухпроводной интерфейс работы (CLK, DIO)
Данный модуль мы используем для показа времени: часов и минут. Удобство модуля в том, что подключается он всего по двум проводам и не требует программной реализации динамической индикации, поскольку все уже реализовано внутри модуля.
Динамическая индикация — это процесс, при котором индикаторы в нашем модуле загораются последовательно. Но мерцания мы не видим, поскольку человеческой глаз обладает большой инертностью. Данный метод позволяет очень хорошо экономить количество соединений между индикаторами и контроллером:
- Статическая индикация: 4 цифры × 7 сегментов = 28 соединений.
- Динамическая индикация: 7 сегментов + 4 общих анода или катода = 11 соединений.
- Микросхема TM1637: 2 соединения.
Выгода очевидна.
Сборка модуля часов реального времени
Сборка часов реального времени DS1307 компании Adafruit
Фото
Пояснения
Подготовьтесь к сборке. Проверьте наличие всех необходимых деталей и инструментов. Установите монтажную плату в тисках.
Нанесите немного припоя на отрицательный контакт батареи.
Установите два резистора 2.2 КОм и керамический конденсатор
Как именно вы их расположите — неважно. Полярность не имеет значения.
После этого установите кристалл (также симметрично), держатель (холдер) для батарейки и чип часов реального времени.
Чип модуля реального времени надо установить таким образом, чтобы отметка (паз) на чипе располагалась в соответствии с обозначением на монтажной плате
Внимательно посмотрите на фото слева, там чип установлен верно.
Чтобы холдер для батарейки не выпадал, лучше его припаять сверху.
После этого переверните плату и и припаяйте оставшиеся контакты.
Удалите остатки контактов от резисторов, кристалла и конденсатора.
Если вы хотите использовать контакты для установки модуля на беспаечную монтажную плату, установите рельсу контактов на макетку, модуль часов реального времени сверху и припаяйте контакты.
Установите батарейку. Плоская часть батареи должна быть сверху. В среднем батарейка будет служить около 5 лет.
Даже если батарейка села, не оставляйте слот для нее пустым.
Написание прошивки
Функция должна инициализировать часы реального времени и индикатор, а также записывать время компиляции во внутреннюю память часов реального времени. Все действие, а точнее, чтение времени из RTC и вывод его на индикатор, будет производиться в функции .
Код для этого выглядит следующим образом:
- rtc.ino
-
#include <Wire.h> #include <EEPROM.h> #include "TM1637.h" #include "DS1307.h" //Массив, содержащий время компиляции char compileTime = __TIME__; //Номера пинов Arduino, к которым подключается индикатор #define DISPLAY_CLK_PIN 12 #define DISPLAY_DIO_PIN 13 //Для работы с микросхемой часов и индикатором мы используем библиотеки //Классы TM1637 и DS1307 объявлены именно в них TM1637 display(DISPLAY_CLK_PIN, DISPLAY_DIO_PIN); DS1307 clock; void setup() { //Включаем и настраиваем индикатор display.set(); display.init(); //Запускаем часы реального времени clock.begin(); //Получаем число из строки, зная номер первого символа byte hour = getInt(compileTime, ); byte minute = getInt(compileTime, 3); byte second = getInt(compileTime, 6); //Готовим для записи в RTC часы, минуты, секунды clock.fillByHMS(hour, minute, second); //Записываем эти данные во внутреннюю память часов. //С этого момента они начинают считать нужное для нас время clock.setTime(); } void loop() { //Значения для отображения на каждом из 4 разрядов int8_t timeDisp4; //Запрашиваем время с часов clock.getTime(); //Получаем десятки часов с помощью целочисленного деления timeDisp = clock.hour 10; //Получаем единицы часов с помощью остатка от деления timeDisp1 = clock.hour % 10; //Проделываем то же самое с минутами timeDisp2 = clock.minute 10; timeDisp3 = clock.minute % 10; //... а затем выводим его на экран display.display(timeDisp); //у нас нет отдельных разрядов для секунд, поэтому //будем включать и выключать двоеточие каждую секунду display.point(clock.second % 2 ? POINT_ON POINT_OFF); } //Содержимое функции объяснено ниже char getInt(const char* string, int startIndex) { return int(stringstartIndex - '0') * 10 + int(stringstartIndex+1) - '0'; }
Теперь загружаем этот код в среду разработки, компилируем и заливаем. Смотрим на дисплей — бинго! Время на дисплее — время компиляции.
Объяснение функции getInt
Для начала необходимо понять, откуда же в массиве появляется время.
Оно появляется в этой строчке:
Компилятор вместо подставляет строку, содержащую время компиляции в виде , где hh — часы, mm — минуты, ss — секунды.
Вернемся к коду, который необходимо объяснить:
char getInt(const char* string, int startIndex) { return int(stringstartIndex - '0') * 10 + int(stringstartIndex+1) - '0'; }
В массиве , передаваемом в качестве параметра в функцию , мы получаем символ с индексом и следующий за ним, чтобы в итоге получить двухзначное целое число. Однако, изначально это не число, а пара символов. Чтобы получить число по символу, нам необходимо вычесть из этого символа символ нуля (‘): ведь в таблице ASCII все символы цифр идут одна за другой, начиная с символа нуля. Поэтому код , дословно, делает следующее: «Берем символ номер , вычитаем из него символ нуля и переводим в целочисленный тип».
Подключение DS1307 к Arduino
В статье рассмотрен пример часов реального времени от Adafruit, но вы можете с тем же успехом использовать китайские аналоги. Принцип работы и подключения не отличается.
Ссылки для заказа оборудования, которое использовалось в проекте из Китая
На часах реального премени 5 пинов: 5V, GND, SCL, SDA и SQW.
- 5V используется для питания чипа модуля часов реального времени, когда вы делаете к нему запрос для получения данных о времени. Если сигнал 5 В не поступает, чип переходит в «спящий» режим.
- GND — общая земля. Обязательно подключается в схему.
- SCL — контакт i2c часов — необходим для обмена данными с часами реального времени.
- SDA — контакт, по которому через i2c передаются данные с часов реального времени.
- SQW дает возможность настроить вывод данных в виде square-wave. В большинстве случаев этот контакт не используется.
Если вы настроили аналоговый пин 3 (цифровой 17) в режим OUTPUT и HIGH, а аналоговый пин 2 (цифровой 16) в режим OUTPUT и LOW, вы можете запитывать часы реального времени непосредственно от этих контактов!
Подключите аналоговый пин 4 на Arduino к SDA. Аналоговый пин 5 на Arduino подключите к SCL.
Подключение
Модуль часов реального времени необходимо подключить к выводам SCL/SDA, относящимся к шине I²C. Также необходимо подключить линии питания (Vcc) и земли (GND).
Линии SDA/SCL имеют собственные отдельные пины на Arduino, однако внутри они так или иначе подключены к пинам общего назначения. Если рассмотреть Arduino Uno, линии SDA соответствует пин A4, а SCL — A5.
В комплекте с модулем поставляется шлейф с мама-контактами, которые удобнее подключать к Troyka Shield. Однако отдельные пины SDA и SCL на ней не выведены, поэтому мы осуществили подключение прямо через пины A5 и A4.
В плане подключения индикатора — все гораздо проще. Выводы CLK и DIO можно подключить к любым цифровым выводам. В данном случае используются 12-й и 11-й выводы соответственно.
DS1307
описание библиотеки для использования в Arduino модуля реального времени DS3107 на русском языке
Скачать: на официальном сайте зеркало1 зеркало2
Введение:
Эта библиотека была написана для легкого взаимодействия и использования модуля на микросхеме DS1307 с Arduino или chipKit без необходимости использования библиотеки Wire. Данная библиотека использует по умолчанию режим Fast Mode (400 кГц) аппаратного интерфейса I2C. Работа этой библиотека не гарантируется в режиме одновременной работы с библиотекой Wire и совместного использования контактов.
Структура:
Time;Структура управления данными времени и даты.Переменные: hour, min, sec: Для определения данных времениdate, mon, year: Для определения данных датыdow: День недели, начиная с понедельникаПример: Time t; // Определяем структуру с именем t класса «время»DS1307_RAM;Буфер для использования совместно с ReadBuffer () и WriteBuffer ().Переменные: Cell : Байт-массив для хранения данных, с возможностью чтения или записи в ОЗУ микросхемы.Пример: DS1307_RAM ramBuffer; // Объявляем буфер для использования
Определенные литералы:
Дни неделиИспользуется совместно с setDOW() и Time.dowMONDAY: 1TUESDAY: 2WEDNESDAY: 3THURSDAY: 4FRIDAY: 5SATURDAY: 6SUNDAY: 7Длина названияИспользуется совместно с getTimeStr(), getDateStr(), getDOWStr() and getMonthStr()FORMAT_SHORT: 1 (полное название)FORMAT_LONG: 2 (сокращенное (3 буквенное) название)Формат датыИспользуется совместно с getDateStr()FORMAT_LITTLEENDIAN: 1 (дд.мм.гггг)FORMAT_BIGENDIAN: 2 (гггг.мм.дд)FORMAT_MIDDLEENDIAN: 3 (мм.дд.гггг)
Частота на выходе SQW
Используется совместно с setSQWRate()
SQW_RATE_1: 1 (1 Гц)
SQW_RATE_4K: 2 (4096 Гц)
SQW_RATE_8K: 3 (8192 Гц)
SQW_RATE_32K: 4 (32768 Гц)
Функции:
DS1307(SDA, SCL);Инициализация библиотеки с помощью интерфейса I2CПараметры:SDA: Вывод подключения SDA-пина DS1307 (Вывод 5, данные)SCL: Вывод подключения SCL-пина DS1307 (вывод 6, тактирование)Пример: DS1307 rtc(SDA, SCL); // Инициализация библиотеки DS13071 с помощью интерфейса I2CПримечание: DS1307 можно подключать с любым свободным выводам Arduino. Если в схеме уже используется шина I2C и Вы попытаетесь подключиться к тем же выводам, то данная библиотека работать не будет, т.к. любой TWI-совместимый протокол требует исключительного доступа к пинам.
begin();Инициализация подключения к DS1307Параметры: НетВозврат: НетПример: rtc.begin(); //Инициализация подключения к DS1307
getTime();Считать текущие данные из DS3231.Параметры: НетВозврат: формат Time-structureПример: t = rtc.getTime(); // Считать текущую дату и время.
Элементы платы
Микросхема DS1307
Микросхема, занимающаяся подсчетом времени. Связь с микросхемой происходит по протоколу I2C. Её I2C-адрес 0b1101000.
Кварцевый резонатор
Для точной работы часов используется кварцевый резонатор на частоте 32768 Гц. Та же частота используется в кварцевых часах. Такая частота обеспечивает 215 циклов в секунду, что очень удобно для простых двоичных счётчиков
Гнездо для батарейки
Батарейка CR1225 обеспечивает работу часов реального времени при выключенном питании. Без батарейки модуль не может работать, даже если подключено внешнее питание.
Контакты подключения 3-проводных шлейфов
Контакты питания:
- Земля (G) — чёрный провод. Соедините с пином Arduino.
- Питание (V) — красный провод. Соедините с пином Arduino.
- Не используется.
Контакты шины I²C:
- Сигнальный (D) — Подключите к пину Arduino.
- Сигнальный (С) — Подключите к пину Arduino.
- Не используется.
Часы реального времени DS3231SN (ZS-042). Подключение к Arduino
22.12.16 14:16
Многие устройства требуют постоянного учёта хронометрических данных (дата, время), эту функцию выполняют специальные электронные схемы, которые называются часами реального времени. Часы реального времени, в нынешнее время, реализованы в виде отдельной микросхемы, к которой нужно добавить кварцевый резонатор и автономный источник питания. В некоторых микросхемах, кварцевый резонатор встроен внутри. Одни из таких часов на микросхеме DS3231SN я купил для своих проектов. В примере буду подключать часы реального времени к китайскому аналогу Arduino UNO.
Представляют из себя законченный модуль ZS-042, который можно подключать к различным устройствам, не только к платформе Arduino.
Модуль построен на микросхеме DS3231SN, которая по сути и является часами реального времени. В отличии от старой модели часов, например на микросхеме DS1307, эти часы содержат внутренний кварцевый резонатор, благодаря чему часы имеют точный ход.
Реализовать часы на Arduino можно и без DS3231SN, но тогда при пропадании питания, значения таймера сбрасываются. Эти же часы имеют резервное питание, поэтому при пропадании питания, они продолжают дальше работать.
Часы умеют производить подсчёт часов, минут, секунд, дат, месяцев, лет (високосные года учитываются до 2100 года). Работают в 12 или 24 часовом режиме, содержат два будильника, а так же имеют внутренний термометр, с диапазоном от -40 ° C до + 85 ° C. Для подключения к различным устройствам, часы подключаются по I2C интерфейсу.
Расположение и назначение пинов на модуле ZS-042:
32К —
SQW — Программируемый выход Square-Wave сигнала.
SCL – Через этот пин по интерфейсу I2C происходит обмен данными с часами.
SDA – Через этот пин передаются данные с часов.
VCC – Питание часов реального времени, нужно 5 вольт. Если на этот пин не поступает напряжение, часы переходят в спящий режим.
GND — Земля.
Для подключения к Arduino UNO, пин SDA часов подключаем к пину A4, а пин SCL к A5. Для питания используются пины GND(-) и VCC(+5v).
Пины SDA и SCL на разных платах Arduino:
SDA | SCL | |
UNO | A4 | A5 |
Mini | A4 | A5 |
Nano | A4 | A5 |
Mega2560 | 20 | 21 |
Leonardo | 2 | 3 |
Установим батарейку CR2032 в часы, такие элементы используются для питания BIOS в компьютерах.
При подключении USB кабеля к Arduino, на часах должен загореться светодиод «POWER» (красный светодиод).
Для того что бы запрограммировать часы через Arduino IDE нужно установить библиотеки.
Скачать библиотеку Time и DS1307RTC.
Последняя библиотека была написана для часов на микросхеме DS1307, но её протоколы взаимодействия совместимы с DS3231, поэтому библиотека подойдёт к нашим часам.
Библиотеки нужно скачать, распаковать и поместить в папку «libraries». При запуске Arduino IDE, они с примерами должны появится в «Образцах».
Устанавливаем Дату и время.
Для этого скопируем данный код в Arduino IDE.
//Подключаем библиотеки:#include <Time.h> #include <Wire.h> #include <DS1307RTC.h>void setup() {setSyncProvider(RTC.get);//Устанавливаем время в формате://Часы, минуты, секунды, день, месяц, годsetTime(13,35,0,22,12,2016);//Применяем:RTC.set(now());}void loop(){delay(100);} |
Для корректной настройки нужно изменить данные в строке
setTime(13,35,0,22,12,2016);
В скобках через запятую устанавливаем правильные: часы, минуты, секунды, число, месяц, год. У меня в примере установлено 13 часов 35 минут 0 секунд, 22 декабря 2016 год. Вгружаем скетч в Arduino.
Теперь для того что бы прочитать показания из часов, можно воспользоваться примером: «Файл» — «Образцы» — «DS1307RTC» — «ReadTest» и загрузить его в Arduino.
Далее открываем монитор последовательного порта, нажав на соответствующую кнопку.
В открывшемся окне будет отображаться текущие дата и время. Если отключить питание модуля часов от Arduino, Arduino не сможет отслеживать значения и в мониторе через какое то время появится надпись «…read error!» (выделил красным). После возобновления питания, показания даты и времени будут отсчитываться далее. Показания даты и времени не сбросились, поскольку часы питались от своей батарейки CR2032.