Содержание
- Обзор
- Технические характеристики
- Назначение контактов
- Подключение к Arduino
- Пример использования
- Часто задаваемые вопросы
Обзор часов реального времени DS3231
Если вы создаете устройство, которому нужно знать точное время, вам пригодится модуль часов реального времени RTC (Real Time Clock). Данные модули отсчитывают точное время и могут сохранять его даже при отключении основного питания при использовании резервного питания (батарейка CR2032 или литий-ионный аккумулятор LIR2032-3,6 В), которого хватит на несколько лет.
Еще совсем недавно основным модулем RTC в среде Ардуинщиков являлся модуль на микросхеме DS1307. В этом модуле использовался внешний кварцевый генератор частотой 32кГц, при изменении температуры менялась частота кварца, что приводило к погрешности в подсчете времени.
Новые модули RTC (рис. 1) построены на микросхеме DS3231, внутрь которой установлен кварцевый генератор и датчик температуры, который компенсирует изменения температуры, поэтому время отсчитывается более точно. Погрешность составляет ±2 минуты за год.
Рисунок 1.
Технические характеристики
- календарь до 2100 года
- погрешность : +/- 4ppm
- два будильника
- выход стабильной частоты : 1-32768 Гц
- напряжение питания : 2,7 - 5,3 В
- напряжение батарейки : 2,3 - 5,3 В
- ток потребления : 250 мкA
- ток потребления от батарейки : 3 мкA
- порог переключения на батарейку : 2,6 В
- интерфейс : I2C
- размеры : 40х22 мм
Назначение контактов
Модуль имеет 6 выводов:
- GND – общий
- VCC – питание 2,7 - 5,3 В
- SDA – вход/выход данных интерфейса I2C
- SCL – синхронизация интерфейса I2C
- SQW – прерывание от будильников или выход импульсов 1-8192 Гц
- 32K – выход импульсов 32768 Гц
Подключение к плате Arduino
Модуль DS3231 подключается к плате Arduino по интерфейсу I2C, используются выводы SDA и SCL. Схема подключения показана на рис. 2.
Рисунок 2.
Для программирования будем использовать библиотеки DS1307 и Time. Скетч получения данных с DS3231 и вывода в последовательный порт показан в листинге 1.
Листинг 1
#include <Wire.h>
#include <DS1307RTC.h>
#include <Time.h>
tmElements_t datetime;
void setup() {
Serial.begin(9600);
}
void loop() {
// получение данных из ds3231
if (RTC.read(dt)) {
print2(datetime.Hour, ":");
print2(datetime.Minute, ":");
print2(datetime.Second, " ");
print2(datetime.Day, "/");
print2(datetime.Month, "/");
print2(tmYearToCalendar(datetime.Year) ,"");
Serial.println();
}
else {
Serial.println("error");
delay(5000);
}
delay(1000);
}
void print2(int nn,String str) {
if (nn >= 0 && nn < 10)
{ Serial.print("0");}
Serial.print(nn);
Serial.print(str);
}
Открываем монитор последовательного порта (рис. 3).
Рисунок 3.
Результат работы – правильный отсчет, но неверное значение времени и даты. При отсутствии питания значение времени в микросхеме DS3231 сбрасывается на 00:00:00 01/01/2000.
Добавим функционал скетчу – установка времени отправкой строки вида "dd/mm/ YYYY hh:mm:ss" в последовательный порт.
Листинг 2
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
String inSer = "";
boolean strFull = false;
tmElements_t datetime;
void setup() {
Serial.begin(9600);
}
void loop() {
// пришли данные по serial
if (strFull) {
datetime.Hour=(int(inSer[11])-48)*10+(int(inSer[12])-48);
datetime.Minute=(int(inSer[14])-48)*10+(int(inSer[15])-48);
datetime.Second=(int(inSer[17])-48)*10+(int(inSer[18])-48);
datetime.Day=(int(inSer[0])-48)*10+(int(inSer[1])-48);
datetime.Month=(int(inSer[3])-48)*10+(int(inSer[4])-48);
datetime.Year=CalendarYrToTm((int(inSer[6])-48)*1000+(int(inSer[7])-48)*100+(int(inSer[8])-48)*10+(int(inSer[9])-48));
RTC.write(datetime); // записать данные в DS3231
// очистить строку
inSer = "";
strFull = false;
}
// получение данных из ds3231
if (RTC.read(datetime)) {
print2(datetime.Hour, ":");
print2(datetime.Minute, ":");
print2(datetime.Second, " ");
print2(datetime.Day, "/");
print2(datetime.Month, "/");
print2(tmYearToCalendar(datetime.Year) ,"");
Serial.println();
}
else {
Serial.print("error");
delay(5000);
}
delay(1000);
}
void print2(int nn,String str) {
if (nn >= 0 && nn < 10)
{ Serial.print("0");}
Serial.print(nn);
Serial.print(str);
}
void serialEvent() {
while (Serial.available()) {
// получить очередной байт:
char c = (char)Serial.read();
// добавить в строку
inSer += c;
// /n - конец передачи
if (c == '\n')
{ strFull = true;}
}
}
После загрузки скетча на плату Arduino, открываем монитор последовательного порта и отправляем в Arduino строку «dd/mm/ YYYY hh:mm:ss» для установки текущей даты и точного времени (рис. 4,5).
Рисунок 4,5.
Теперь DS3231 будет отсчитывать точное время. И если установлена батарейка, время не собъется после отключения питания.
Пример использования
Создадим проект часов с выводом данных на 4-х разрядный семисегментный дисплей на базе драйвера TM1637.
Нам потребуются следующие компоненты:
- Плата Arduino Uno – 1
- Плата прототипирования – 1
- Модуль DS3231 – 1
- 4digit display на базе TM1637 – 1
- Провода
Схема соединения элементов показана на рис. 6.
Рисунок 6.
Для программирования вывода данных на 4-х разрядный семисегментный дисплей на базе драйвера TM1637 установим в Arduino IDE библиотеку TM1637. Каждые 5 секунд меняем на дисплее отображение:
текущее время;
день и месяц.
При отображении показаний текущего времени каждые 0.5 секунды мигаем разделителем типа "двоеточие" между вторым и третьим разрядом. Содержимое скетча показано в листинге 3.
Листинг 3
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include "TM1637.h"
#define CLK 3
#define DIO 2
TM1637 4dig_display(CLK,DIO);
// для данных времени
int8_t ListTime[4]={0,0,0,0};
// для данных dd/mm
int8_t ListDay[4]={0,0,0,0};
// разделитель
boolean point=true;
// для смены время / день-месяц
unsigned long millist=0;
tmElements_t datetime;
void setup() {
Serial.begin(9600); // запустить последовательный порт
// запуск дисплея
4dig_display.init();
// яркость дисплея
tm1637.set(7);
}
void loop() {
// получение времени
if (RTC.read(datetime)) {
ListTime[0]= datetime.Hour/10;
ListTime[1]= datetime.Hour%10;
ListTime[2]= datetime.Minute/10;
ListTime[3]= datetime.Minute%10;
ListDay[0]= datetime.Day/10;
ListDay[1]= datetime.Day%10;
ListDay[2]= datetime.Month/10;
ListDay[3]= datetime.Month%10;
}
else {
// ошибка
4dig_display.display(0,ListDay[0]);
4dig_display.display(1,ListDay[1]);
4dig_display.display(2,ListDay[2]);
4dig_display.display(3,ListDay[3]);
4dig_display.point(false);
}
if(millis()-millist>=10000) {
millist=millis();
}
else if(millis()-millist>=5000) {
// вывод день - месяц
4dig_display.display(0,ListDay[0]);
4dig_display.display(1,ListDay[1]);
4dig_display.display(2,ListDay[2]);
4dig_display.display(3,ListDay[3]);
4dig_display.point(false);
}
else {
// вывод времени
4dig_display.display(0,ListTime[0]);
4dig_display.display(1,ListTime[1]);
4dig_display.display(2,ListTime[2]);
4dig_display.display(3,ListTime[3]);
4dig_display.point(point);
}
delay(500);
// поменять индикацию точек
point=!point;
}
Загружаем скетч на плату Arduino и проверяем работу часов.
Рисунок 7,8.
Часто задаваемые вопросы
1. Отсутствует получение данных времени с модуля DS3231.
- Проверьте правильность подключения модуля DS3231 к плате Arduino.
2. Данные, получаемые с модуля DS3231, неверные.
- Установите правильную дату и время, загрузив код из листинга 2 и отправив из последовательного порт правильные данные.
3. При отключении питания сбивается время и дата.
Установите резервное питание модуля (батарейка CR2032 или литий-ионный аккумулятор LIR2032-3,6 В).
Проверьте напряжение резервного питания (должно быть не менее 2,3 В).