Введение
Как микроконтроллеры отслеживают время и дату? Обычный микроконтроллер обладает функцией таймера, который стартует от нуля при подаче напряжения питания, а затем начинает считать. В мире Arduino мы можем использовать функцию , чтобы узнать, сколько прошло миллисекунд с того времени, когда было подано напряжение питания. Когда вы снимете и снова подадите питания, она начнет отсчет с самого начала. Это не очень удобно, когда дело доходит до работы с часами и датами.
Вот здесь и будет удобно использование микросхемы RTC (Real Time Clock, часов реального времени). Эта микросхема с батарейкой 3В или каким-либо другим источником питания следит за временем и датой. Часы/календарь обеспечивают информацию о секундах, минутах, часах, дне недели, дате, месяце и годе. Микросхема корректно работает с месяцами продолжительностью 30/31 день и с високосными годами. Связь осуществляется через шину I2C (шина I2C в данной статье не обсуждается).
Если напряжение на главной шине питания Vcc падает ниже напряжения на батарее Vbat, RTC автоматически переключается в режим низкого энергопотребления от резервной батареи. Резервная батарея – это обычно миниатюрная батарея (в виде «монетки», «таблетки») напряжением 3 вольта, подключенная между выводом 3 и корпусом. Таким образом, микросхема по-прежнему будет следить за временем и датой, и когда на основную схему будет подано питание, микроконтроллер получит текущие время и дату.
В этом проекте мы будем использовать DS1307. У этой микросхемы вывод 7 является выводом SQW/OUT (выходом прямоугольных импульсов). Вы можете использовать этот вывод для мигания светодиодом и оповещения микроконтроллера о необходимости фиксации времени. Мы будем делать и то, и другое. Ниже приведено объяснение работы с выводом SQW/OUT.
Для управления работой вывода SQW/OUT используется регистр управления DS1307.
Бит 7 | Бит 6 | Бит 5 | Бит 4 | Бит 3 | Бит 2 | Бит 1 | Бит 0 |
---|---|---|---|---|---|---|---|
OUT | SQWE | RS1 | RS0 |
- Бит 7: управление выходом (OUT)
- Этот бит управляет выходным уровнем вывода SQW/OUT, когда выход прямоугольных импульсов выключен. Если SQWE = 0, логический уровень на выводе SQW/OUT равен 1, если OUT = 1, и 0, если OUT = 0. Первоначально обычно этот бит равен 0.
- Бит 4: включение прямоугольных импульсов (SQWE)
- Этот бит, когда установлен в логическую 1, включает выходной генератор. Частота прямоугольных импульсов зависит от значений битов RS0 и RS1. Когда частота прямоугольных импульсов настроена на значение 1 Гц, часовые регистры обновляются во время спада прямоугольного импульса. Первоначально обычно этот бит равен 0.
- Биты 1 и 0: выбор частоты (RS)
- Эти биты управляют частотой выходных прямоугольных импульсов, когда выход прямоугольных импульсов включен. Следующая таблица перечисляет частоты прямоугольных импульсов, которые могут быть выбраны с помощью данных битов. Первоначально обычно эти биты равны 1.
RS1 | RS0 | Частота импульсов и уровень на выходе SQW/OUT | SQWE | OUT |
---|---|---|---|---|
1 Гц | 1 | x | ||
1 | 4,096 кГц | 1 | x | |
1 | 8,192 кГц | 1 | x | |
1 | 1 | 32,768 кГц | 1 | x |
x | x | |||
x | x | 1 | 1 |
Данная таблица поможет вам с частотой:
Частота импульсов | Бит 7 | Бит 6 | Бит 5 | Бит 4 | Бит 3 | Бит 2 | Бит 1 | Бит 0 |
---|---|---|---|---|---|---|---|---|
1 Гц | 1 | |||||||
4,096 кГц | 1 | 1 | ||||||
8,192 кГц | 1 | 1 | ||||||
32,768 кГц | 1 | 1 | 1 |
Если вы подключили светодиод и резистор к выводу 7 и хотите, чтобы светодиод мигал с частотой 1 Гц, то должны записать в регистр управления значение 0b00010000. Если вам нужны импульсы 4,096 кГц, то вы должны записать 0b000100001. В этом случае, чтобы увидеть импульсы вам понадобится осциллограф, так как светодиод будет мигать так быстро, что будет казаться, что он светится постоянно. Мы будем использовать импульсы с частотой 1 Гц.
Описание регистров DS3231
Ниже в таблице представлен перечень регистров часов реального времени:
Адрес | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Функция | Пределы |
---|---|---|---|---|---|---|---|---|---|---|
0x00 | 10 секунд | Секунды | Секунды | 00-59 | ||||||
0x01 | 10 минут | Минуты | Минуты | 00-59 | ||||||
0x02 | 12/24 | AM/PM | 10 часов | Час | Часы | 1-12 + AM/PM или 00-23 | ||||
10 часов | ||||||||||
0x03 | День | День недели | 1-7 | |||||||
0x04 | 10 число | Число | Дата | 01-31 | ||||||
0x05 | Century | 10 месяц | Месяц | Месяцы/век | 01-12 + Век | |||||
0x06 | 10 лет | Год | Годы | 00-99 | ||||||
0x07 | A1M1 | 10 секунд | Секунды | Секунды, 1-й будильник | 00-59 | |||||
0x08 | A1M2 | 10 минут | Минуты | Минуты, 1-й будильник | 00-59 | |||||
0x09 | A1M3 | 12/24 | AM/PM | 10 часов | Час | Часы, 1-й будильник | 1-12 + AM/PM или 00-23 | |||
10 часов | ||||||||||
0x0A | A1M4 | DY/DT | 10 число | День | День недели, 1-й будильник | 1-7 | ||||
Число | Дата, 1-й будильник | 01-31 | ||||||||
0x0B | A2M2 | 10 минут | Минуты | Минуты, 2-й будильник | 00-59 | |||||
0x0C | A2M3 | 12/24 | AM/PM | 10 часов | Час | Часы, 2-й будильник | 1-12 + AM/PM или 00-23 | |||
10 часов | ||||||||||
0x0D | A2M4 | DY/DT | 10 число | День | День недели, 2-й будильник | 1-7 | ||||
Число | Дата, 2-й будильник | 01-31 | ||||||||
0x0E | EOSC | BBSQW | CONV | RS2 | RS1 | INTCN | A2IE | A1IE | Регистр настроек (Control) | |
0x0F | OSF | EN32kHz | BSY | A2F | A1F | Регистр статуса (Status) | ||||
0x10 | SIGN | DATA | DATA | DATA | DATA | DATA | DATA | DATA | Регистр подстройки частоты (Aging Offset) | |
0x11 | SIGN | DATA | DATA | DATA | DATA | DATA | DATA | DATA | Регистр температуры, старший байт | |
0x12 | DATA | DATA | Регистр температуры, младший байт |
Информация о времени хранится в двоично-десятичном формате, то есть каждый разряд десятичного числа (от 0 до 9) представляется группой из 4-х бит. В случае одного байта, младший полубайт отсчитывает единицы, старший десятки и т. д. Счет времени осуществляется в регистрах с адресами 0x00-0x06, для отсчета часов можно выбрать режим 12-ти или 24-х часов. Установка 6-го бита регистра часов (адрес 0x02), задает 12-ти часовой режим, в котором 5-й бит указывает на время суток, значению 1 соответствует время после полудня (PM), значению 0 до полудня (AM). Нулевое значение 6-го бита соответствует 24-х часовому режиму, здесь 5-й бит участвует в счете часов (значения 20-23).
Регистр дня недели увеличивается в полночь, счет идет от 1 до 7, регистр месяцев (адрес 0x05) содержит бит века Century (7-й бит), который переключается при переполнении регистра счета лет (адрес 0x06), от 99 к 00.
В микросхеме DS3231 реализовано два будильника, 1-й будильник настраивается с помощью регистров с адресами 0x07-0x0A, 2-й будильник регистрами 0x0B-0x0D. Битами A1Mx и A2Mx можно настроить различные режимы для будильников, установка бита исключает соответствующий регистр из операции сравнения.
Подключение RTC часы реального времени DS1302, DS1307, DS3231 к Arduino
Для подключения RTC часов реального времени DS1302, DS1307, DS3231, была разработана универсальная библиотека.
Подключение DS1307 к Arduino :
Подключение DS1302 к Arduino :
Подключение DS3231 к Arduino :
Программа:
В зависимости от того какой модуль Вы подключаете, необходимо в программе указать
Для DS1307
Для DS1302
Для DS3231
Пример установки текущего времени в RTC модуль (DS1307):
Пример считывания текущего времени с RTC модуля (DS1307) и вывод в «Последовательный порт» :
Преимущества библиотеки:
— библиотека имеет внутренние функции аппаратной обработки протоколов передачи данных I2C и SPI, а следовательно не требует подключения дополнительных библиотек, но и не конфликтует с ними, если таковые всё же подключены.
— библиотека имеет внутренние функции программой обработки протокола передачи данных 3-Wire
— для инициализации модуля необходимо вызвать функцию begin с названием модуля.
— подключение модулей осуществляется к аппаратным выводам arduino используемой шины (за исключением 3-Wire)
— простота установки и чтения времени функциями settime и gettime
функция settime может устанавливать дату и время, как полностью, так и частично (например только минуты, или только день, и т.д.)
функция gettime работает как функция date в php, возвращая строку со временем, но если её вызвать без параметра, то функция ничего не вернёт, а время можно прочитать из переменных в виде чисел.
— библиотека расширяемая, то есть для того, чтоб она работала с новым модулем, нужно указать параметры этого модуля в уже существующих массивах файла RTC.h (тип шины, частота шины в кГц, режимы работы, адреса регистров и т.д.), как всё это сделать, описано в файле extension.txt
Таким образом добавив новый модуль в библиотеку, мы лишь увеличим область занимаемой динамической памяти на
36 байт, при этом не затронув область памяти программ.
— при вызове функции begin, библиотека читает флаги регистров модуля и при необходимости устанавливает или сбрасывает их так, чтоб модуль мог работать от аккумуляторной батареи, а на программируемом выводе меандра (если таковой у модуля есть) установилась частота 1Гц, тогда этот вывод можно использовать в качестве внешнего посекундного прерывания.
— при работе с модулем DS1302 не нужны никакие резисторы на выводе GND (которые нужны для его работы с другими библиотеками этого модуля), это достигнуто тем, что для шины 3-Wire указана конкретная частота 10кГц, не зависимо от частоты CPU arduino.
— в библиотеке реализована еще одна не обязательная функция period, принимающая в качестве единственного аргумента — количество минут (от 1 до 255)
если в течении указанного времени была вызвана функция gettime несколько раз, то запрос к модулю по шине будет отправлено только в первый раз, а ответом на все остальные запросы будет сумма времени последнего ответа модуля и времени прошедшего с этого ответа.
Функцию period достаточно вызвать один раз.
Отличительные особенности DS3231
- Точность ±2 ppm в диапазоне температур от 0°C до +40°C
- Точность ±3.5 ppm в диапазоне температур от-40°C до +85°C
- Вход для подключения автономного источника питания, позволяющего обеспечить непрерывную работу
- Рабочий температурный диапазонкоммерческий: от 0°C до +70°C
- индустриальный: -от 40°C до +85°C
- Низкое потребление
- Часы реального времени, отсчитывающие секунды, минуты, часы, дни недели, дни месяца, месяц и год с коррекцией високосного года вплоть до 2100
- Два ежедневных будильника
- Выход прямоугольного сигнала с программируемой частотой
- Быстродействующие (400 кГц) I2C интерфейс
- 3.3 В питание
- Цифровой температурный датчик с точностью измерения ±3°C
- Регистр, содержащий данные о необходимой подстройке
- Вход/выход сброса nonRST
Alarm functions
The DS3232 and DS3231 have two alarms. Alarm1 can be set to seconds precision; Alarm2 can only be set to minutes precision.
setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate)
Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This function can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). When setting Alarm 2, the seconds value must be supplied but is ignored, recommend using zero. (Alarm 2 has no seconds register.)
alarmType: A value from the ALARM_TYPES_t enumeration, above. (ALARM_TYPES_t)seconds: The seconds value to set the alarm to. (byte)minutes: The minutes value to set the alarm to. (byte)hours: The hours value to set the alarm to. (byte)dayOrDate: The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. (byte)
None.
Example
//Set Alarm1 for 12:34:56 on Sunday RTC.setAlarm(ALM1_MATCH_DAY, 56, 34, 12, dowSunday);
setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate)
Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This functiuon can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). However, when using this function to set Alarm 1, the seconds value is set to zero. (Alarm 2 has no seconds register.)
alarmType: A value from the ALARM_TYPES_t enumeration, above. (ALARM_TYPES_t)minutes: The minutes value to set the alarm to. (byte)hours: The hours value to set the alarm to. (byte)dayOrDate: The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. (byte)
None.
Example
//Set Alarm2 for 12:34 on the 4th day of the month RTC.setAlarm(ALM2_MATCH_DATE, 34, 12, 4);
alarmInterrupt(byte alarmNumber, bool alarmEnabled)
Enable or disable an alarm «interrupt». Note that this «interrupt» just causes the RTC’s INT pin to be asserted. To use this signal as an actual interrupt to (for example) a microcontroller, the RTC «interrupt» pin needs to be connected to the microcontroller and the microcontroller application firmware must properly configure the interrupt and also provide for handling it.
alarmNumber: The number of the alarm to enable or disable, ALARM_1 or ALARM_2 (byte)alarmEnabled: true or false (bool)
None.
Example
RTC.alarmInterrupt(ALARM_1, true); //assert the INT pin when Alarm1 occurs. RTC.alarmInterrupt(ALARM_2, false); //disable Alarm2
alarm(byte alarmNumber)
Tests whether an alarm has been triggered. If the alarm was triggered, returns true and resets the alarm flag in the RTC, else returns false.
Value of the alarm flag bit (bool)
Example
if ( RTC.alarm(ALARM_1) ) { //has Alarm1 triggered? //yes, act on the alarm } else { //no alarm }
checkAlarm(byte alarmNumber)
Tests whether an alarm has been triggered. If the alarm was triggered, returns true, else returns false. The alarm flag is not reset.
Value of the alarm flag bit (bool)
Example
if ( RTC.checkAlarm(ALARM_1) ) { //has Alarm1 triggered? //yes, act on the alarm } else { //no alarm }
Example
if ( RTC.checkAlarm(ALARM_1) ) { //has Alarm1 triggered? //yes, act on the alarm RTC.clearAlarm(ALARM_1); //clear the alarm flag } else { //no alarm }
Пример
Остальные примеры смотри в examples!
// демо возможностей библиотеки #include <microDS3231.h> MicroDS3231 rtc; void setup() { Serial.begin(9600); // проверка наличия модуля на линии i2c // вызов rtc.begin() не обязателен для работы if (!rtc.begin()) { Serial.println("DS3231 not found"); for(;;); } // ======== УСТАНОВКА ВРЕМЕНИ АВТОМАТИЧЕСКИ ======== // rtc.setTime(COMPILE_TIME); // установить время == времени компиляции // визуально громоздкий, но более "лёгкий" с точки зрения памяти способ установить время компиляции rtc.setTime(BUILD_SEC, BUILD_MIN, BUILD_HOUR, BUILD_DAY, BUILD_MONTH, BUILD_YEAR); if (rtc.lostPower()) { // выполнится при сбросе батарейки Serial.println("lost power!"); // тут можно однократно установить время == времени компиляции } // ======== УСТАНОВКА ВРЕМЕНИ ВРУЧНУЮ ======== // установить время вручную можно двумя способами (подставить реальные числа) //rtc.setTime(SEC, MIN, HOUR, DAY, MONTH, YEAR); //rtc.setHMSDMY(HOUR, MIN, SEC, DAY, MONTH, YEAR); // также можно установить время через DateTime /* DateTime now; now.second = 0; now.minute = 10; now.hour = 50; now.date = 2; now.month = 9; now.year = 2021; rtc.setTime(now); // загружаем в RTC */ } void loop() { // получение и вывод каждой компоненты Serial.print(rtc.getHours()); Serial.print(":"); Serial.print(rtc.getMinutes()); Serial.print(":"); Serial.print(rtc.getSeconds()); Serial.print(" "); Serial.print(rtc.getDay()); Serial.print(" "); Serial.print(rtc.getDate()); Serial.print("/"); Serial.print(rtc.getMonth()); Serial.print("/"); Serial.println(rtc.getYear()); /* // можно через DateTime (более оптимально): DateTime now = rtc.getTime(); Serial.print(now.hour); Serial.print(":"); Serial.print(now.minute); Serial.print(":"); Serial.print(now.second); Serial.print(" "); Serial.print(now.day); Serial.print(" "); Serial.print(now.date); Serial.print("/"); Serial.print(now.month); Serial.print("/"); Serial.println(now.year); */ // вывод температуры чипа Serial.println(rtc.getTemperatureFloat()); //Serial.println(rtc.getTemperature()); // вывод времени готовой строкой String Serial.println(rtc.getTimeString()); // вывод даты готовой строкой String Serial.println(rtc.getDateString()); // вывод времени через char array char time; rtc.getTimeChar(time); Serial.println(time); // вывод даты через char array char date; rtc.getDateChar(date); Serial.println(date); Serial.println(); delay(500); }
Enumerations
SQWAVE_FREQS_t
Symbolic names used with the squareWave() function (described below).
- SQWAVE_NONE
- SQWAVE_1_HZ
- SQWAVE_1024_HZ
- SQWAVE_4096_HZ
- SQWAVE_8192_HZ
- ALM1_EVERY_SECOND — causes an alarm once per second.
- ALM1_MATCH_SECONDS — causes an alarm when the seconds match (i.e. once per minute).
- ALM1_MATCH_MINUTES — causes an alarm when the minutes and seconds match.
- ALM1_MATCH_HOURS — causes an alarm when the hours and minutes and seconds match.
- ALM1_MATCH_DATE — causes an alarm when the date of the month and hours and minutes and seconds match.
- ALM1_MATCH_DAY — causes an alarm when the day of the week and hours and minutes and seconds match.
- ALM2_EVERY_MINUTE — causes an alarm once per minute.
- ALM2_MATCH_MINUTES — causes an alarm when the minutes match (i.e. once per hour).
- ALM2_MATCH_HOURS — causes an alarm when the hours and minutes match.
- ALM2_MATCH_DATE — causes an alarm when the date of the month and hours and minutes match.
- ALM2_MATCH_DAY — causes an alarm when the day of the week and hours and minutes match.
Подключение и настройка
Часы реального времени общаются с управляющей электроникой по протоколу I²C / TWI. Для подключения используется два 3-проводных шлейфа. При подключении модуля к Arduino удобно использовать Troyka Shield.
Если хотите оставить минимум проводов —
воспользуйтесь Troyka Slot Shield.
Пример работы с Arduino
- testClock.ino
-
// библиотека для работы I²C #include <Wire.h> // библиотека для работы с часами реального времени #include "TroykaRTC.h" // размер массива для времени #define LEN_TIME 12 // размер массива для даты #define LEN_DATE 12 // размер массива для дня недели #define LEN_DOW 12 // создаём объект для работы с часами реального времени RTC clock; // массив для хранения текущего времени char timeLEN_TIME; // массив для хранения текущей даты char dateLEN_DATE; // массив для хранения текущего дня недели char weekDayLEN_DOW; void setup() { // открываем последовательный порт Serial.begin(9600); // инициализация часов clock.begin(); // метод установки времени и даты в модуль вручную // clock.set(10,25,45,27,07,2005,THURSDAY); // метод установки времени и даты автоматически при компиляции clock.set(__TIMESTAMP__); // что бы время менялось при прошивки или сбросе питания // закоментируйте оба метода clock.set(); } void loop() { // запрашиваем данные с часов clock.read(); // сохраняем текущее время, дату и день недели в переменные clock.getTimeStamp(time, date, weekDay); // выводим в serial порт текущее время, дату и день недели Serial.print(time); Serial.print("\t"); Serial.print(date); Serial.print("\t"); Serial.println(weekDay); // ждём одну секунду delay(1000); }
Пример работы с Iskra JS
В качестве примера выведем в «поле консоли» текущее время, дату и день недели. Для запуска примера понадобится библиотека для Iskra JS. Она обеспечивает простую работу с модулем и прячет в себе все тонкости протокола обмена данными между часами реального времени и управляющей платой.
- rtc.js
-
// Настраиваем шину I2C PrimaryI2C.setup({sda SDA, scl SCL, bitrate 100000}); // Создаем новый объект Rtc var rtc = require('@amperka/rtc').connect(PrimaryI2C); // Устанавливаем на часах текущее время контроллера rtc.setTime(); // Результат в виде строки ISO: 2016-21-1T12:1:14 print(rtc.getTime('iso'));
Обзор часов реального времени DS3231
Если вы создаете устройство, которому нужно знать точное время, вам пригодится модуль часов реального времени RTC (Real Time Clock). Данные модули отсчитывают точное время и могут сохранять его даже при отключении основного питания при использовании резервного питания (батарейка CR2032 или литий-ионный аккумулятор LIR2032-3,6 В), которого хватит на несколько лет.
Еще совсем недавно основным модулем RTC в среде Ардуинщиков являлся модуль на микросхеме DS1307. В этом модуле использовался внешний кварцевый генератор частотой 32кГц, при изменении температуры менялась частота кварца, что приводило к погрешности в подсчете времени.
Новые модули RTC (рис. 1) построены на микросхеме DS3231, внутрь которой установлен кварцевый генератор и датчик температуры, который компенсирует изменения температуры, поэтому время отсчитывается более точно. Погрешность составляет ±2 минуты за год.
Functions for setting and reading the time
get(void)
Description
Reads the current date and time from the RTC and returns it as a time_t value. Returns zero if an I2C error occurs (RTC not present, etc.).
None.
Current date and time (time_t)
Example
time_t myTime; myTime = RTC.get();
set(time_t t)
Description
Sets the RTC date and time to the given time_t value. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.
t: The date and time to set the RTC to (time_t)
Example
//this example first sets the system time (maintained by the Time library) to //a hard-coded date and time, and then sets the RTC from the system time. //the setTime() function is part of the Time library. setTime(23, 31, 30, 13, 2, 2009); //set the system time to 23h31m30s on 13Feb2009 RTC.set(now()); //set the RTC from the system time
read(tmElements_t &tm)
Description
tm: Address of a tmElements_t structure to which the date and time are returned.
I2C status (byte). Returns zero if successful. The date and time read from the RTC are returned to the tm parameter.
Example
tmElements_t tm; RTC.read(tm); Serial.print(tm.Hour, DEC); Serial.print(':'); Serial.print(tm.Minute,DEC); Serial.print(':'); Serial.println(tm.Second,DEC);
Description
Sets the RTC to the date and time given by a tmElements_t structure. Clears the oscillator stop flag (OSF) bit in the control/status register. See the function and also the DS323x datasheet for more information on the OSF bit.
Example
tmElements_t tm; tm.Hour = 23; //set the tm structure to 23h31m30s on 13Feb2009 tm.Minute = 31; tm.Second = 30; tm.Day = 13; tm.Month = 2; tm.Year = 2009 - 1970; //tmElements_t.Year is the offset from 1970 RTC.write(tm); //set the RTC from the tm structure
Programming
Once we connect the module we need to program the Arduino Board to work with the Real Time Clock. However, when it comes to programing a communication between Arduino and an I2C module the code isn’t that small and easy. Luckily, there are already several libraries for the DS3231 RTC which can be found on the internet.
For this tutorial I chose to use the Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com.
So once we download and install the library we can use its first demo example to initially activate the clock of the RTC module. In the setup section of the demo example code we can notice that there are three line that we need to uncomment in order to initially set the day of the week, the time and the data.
// Code from the Demo Example of the DS3231 Library void setup() { // Setup Serial connection Serial.begin(115200); // Uncomment the next line if you are using an Arduino Leonardo //while (!Serial) {} // Initialize the rtc object rtc.begin(); // The following lines can be uncommented to set the date and time //rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY //rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format) //rtc.setDate(1, 1, 2014); // Set the date to January 1st, 2014 }
The first line is for setting the day of the week, the second line is for setting the time in hours, minutes and seconds, and the third line is for setting the date in days, months and years.
Once we upload this code we need to comment back the three lines and re-upload the code again.
// Code from the Demo Example of the DS3231 Library void loop() { // Send Day-of-Week Serial.print(rtc.getDOWStr()); Serial.print(" "); // Send date Serial.print(rtc.getDateStr()); Serial.print(" -- "); // Send time Serial.println(rtc.getTimeStr()); // Wait one second before repeating delay (1000); }
If we take a look at the loop section of the code we can see that now using the three custom functions we get the information from the RTC and print them in the Serial Monitor. Here’s how they appear in the Serial Monitor.
Now even if we disconnect the Arduino power and then reconnect it and run the Serial Monitor again we can notice that the time keeps going without being reset.
So now we have our Real Time Clock up and running and we can use in any Arduino Project. As a second example I connected an LCD to the Arduino and printed the time and the date on it.
Here’s the source code of this example:
/* * Arduino DS3231 Real Time Clock Module Tutorial * * Crated by Dejan Nedelkovski, * www.HowToMechatronics.com * * DS3231 Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com. * */ #include <DS3231.h> #include <LiquidCrystal.h> // includes the LiquidCrystal Library DS3231 rtc(SDA, SCL); LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7) void setup() { rtc.begin(); // Initialize the rtc object lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } } void loop() { lcd.setCursor(0,0); lcd.print("Time: "); lcd.print(rtc.getTimeStr()); lcd.setCursor(0,1); lcd.print("Date: "); lcd.print(rtc.getDateStr()); delay(1000); }
That’s all for this Arduino Tutorial, feel free to ask any question in the comments section below.
Temperature Compensated Crystal Oscillator(TCXO)
Most RTC modules come with an external 32kHz crystal for time-keeping. But the problem with these crystals is that external temperature can affect their oscillation frequency. This change in frequency can be negligible but it surely adds up.
To avoid such slight drifts in crystal, DS3231 is driven by a 32kHz temperature compensated crystal oscillator (TCXO). It’s highly immune to the external temperature changes.
TCXO is packaged inside the RTC chip, making the whole package bulky. Right next to the integrated crystal is a temperature sensor.
This sensor compensates the frequency changes by adding or removing clock ticks so that the timekeeping stays on track.
That’s the reason TCXO provides a stable and accurate reference clock, and maintains the RTC to within ±2 minutes per year accuracy.
DS3231 Vs DS1307
The main difference between the DS3231 and DS1370 is the accuracy of time-keeping.
DS1307 comes with an external 32kHz crystal for time-keeping whose oscillation frequency is easily affected by external temperature. This usually results with the clock being off by around five or so minutes per month.
However, the DS3231 is much more accurate, as it comes with an internal Temperature Compensated Crystal Oscillator(TCXO) which isn’t affected by temperature, making it accurate down to a few minutes per year at the most.
DS1307 is still a great value RTC and serves you well, but for projects that require more accurate time-keeping, DS3231 is recommended.
Onboard 24C32 EEPROM
DS3231 RTC module also comes with a 32 bytes 24C32 EEPROM chip from Atmel having unlimited read-write cycles. It can be used to save settings or really anything.
The 24C32 EEPROM uses I2C interface for communication and shares the same I2C bus as DS3231.
The I2C address of the EEPROM can be changed easily with the three A0, A1 and A2 solder jumpers at the back. Each one of these is used to hardcode in the address. If a jumper is shorted with solder, that sets the address.
As per the 24C32’s datasheet, these 3 bits are placed at the end of the 7-bit I2C address, just before the Read/Write bit.
As there are 3 address inputs, which can take 2 states, either HIGH/LOW, we can therefore create 8 (23) different combinations(addresses).
TIP
By default, all the 3 address inputs are pulled HIGH using onboard pullups, giving 24C32 a default I2C address of 1010111Binary or 0x57Hex.
By shorting the solder jumpers, the address inputs are puled LOW. It allows you to set the I2C address according to below table.
Code for reading/writing onboard 24C32 EEPROM is given at the .
Other functions
temperature(void)
Description
Returns the RTC temperature.
Parameters
None.
RTC temperature as degrees Celsius times four. (int)
int t = RTC.temperature(); float celsius = t / 4.0; float fahrenheit = celsius * 9.0 / 5.0 + 32.0;
squareWave(SQWAVE_FREQS_t freq)
Description
Enables or disables the square wave output.
Parameters
freq: a value from the SQWAVE_FREQS_t enumeration above. (SQWAVE_FREQS_t)
None.
RTC.squareWave(SQWAVE_1_HZ); //1 Hz square wave RTC.squareWave(SQWAVE_NONE); //no square wave
Description
Returns the value of the oscillator stop flag (OSF) bit in the control/status register which indicates that the oscillator is or was stopped, and that the timekeeping data may be invalid. Optionally clears the OSF bit depending on the argument passed. If the argument is omitted, the OSF bit is cleared by default. Calls to and also clear the OSF bit.
Parameters
clearOSF: an optional true or false value to indicate whether the OSF bit should be cleared (reset). If not supplied, a default value of true is used, resetting the OSF bit. (bool)