цифровая электроника
вычислительная техника
встраиваемые системы

 

Arduino и точные часы реального времени DS3231

Автор: Mike(admin) от 25-05-2020, 23:55

Все мы знаем, что большинство микроконтроллеров, которые мы используем для наших проектов, не знают о текущем времени. Это нормально для большинства наших проектов, но время от времени, когда вы сталкиваетесь с идеей, в которой основное внимание уделяется получению точного значения времени, модуль часов реального времени DS3231 является спасителем. Он идеально подходит для проектов, предполагающих регистрацию данных, создание часов, таймеров и сигналов тревоги.


Arduino и точные часы реального времени DS3231

В основе модуля лежит недорогая, чрезвычайно точная микросхема часов реального времени (RTC) от Maxim – DS3231. Она управляет всеми функциями хронометража и имеет простой двухпроводной интерфейс I2C, который можно легко подключить к любому микроконтроллеру по вашему выбору.


DS3231

Чип хранит информацию о секундах, минутах, часах, днях, месяце и годе. Дата в конце месяца автоматически корректируется для месяцев, в которых менее 31 дня, включая поправки для високосного года (действует до 2100). Часы работают в 24-часовом или 12-часовом формате с индикатором AM/PM. Они также обеспечивают два программируемых времени суток.


Еще одна интересная особенность этой платы – вывод SQW, который выводит хороший прямоугольный сигнал на частотах 1 Гц, 4 кГц, 8 кГц или 32 кГц и может обрабатываться программно. Это может также использоваться как прерывание во многих основанных на времени приложениях.


Большинство модулей RTC поставляются с внешним резонатором 32 кГц для сохранения времени. Но проблема с этими резонаторами в том, что внешняя температура может влиять на частоту их колебаний. Это изменение частоты может быть незначительным, но они, безусловно, складываются. Чтобы избежать таких небольших дрейфов, DS3231 приводится в действие кварцевым генератором с температурной компенсацией 32 кГц (TCXO). Он очень невосприимчив к внешним изменениям температуры. TCXO имеется внутри чипа RTC, что делает весь корпус немаленьким. Прямо рядом со встроенным кристаллом находится датчик температуры. Этот датчик компенсирует изменения частоты, добавляя или удаляя такты часов, так что хронометраж остается актуальным. Вот почему TCXO обеспечивает стабильные и точные эталонные значения времени и поддерживает работу RTC с точностью до ±2 минуты в год.


Основное различие между DS3231 и DS1370, который довольно популярен в связи с дешевизной, заключается в точности учета времени. DS1307 поставляется с внешним резонатором 32 кГц для хронометража, частота колебаний которого легко зависит от внешней температуры. Обычно это приводит к тому, что часы отстают примерно на пять минут в месяц. Тем не менее, DS3231 гораздо точнее, поскольку поставляется с внутренним кварцевым генератором с температурной компенсацией (TCXO), который не зависит от температуры, что делает его точным до нескольких минут в год в среднем.


DS3231 питается от батареи и обеспечивает точное хронометраж при отключении основного питания устройства. Встроенная чувствительная цепь непрерывно контролирует состояние VCC для обнаружения сбоев питания и автоматически переключается на резервный источник питания. Таким образом, вам не нужно беспокоиться о перебоях в питании, ваш микроконтроллер может спокойно отслеживать время.


DS3231

На нижней стороне платы находится держатель для 20-миллиметровых 3V литиевых батареек. Любая батарея CR2032 может поместиться в этот разъем. Предполагая, что используется полностью заряженная батарея CR2032 емкостью 220 мАч, а чип потребляет минимум 3 мкА, батарея может поддерживать RTC в течение минимум 8 лет без внешнего источника питания 5 В (220 мАч / 3 мкА = 73333,34 часа = 3055,56 дня = 8,37 года).


Модуль DS3231 RTC также поставляется с 32-байтовым EEPROM чипом 24C32 от Atmel с неограниченным циклом чтения-записи. Он может быть использован для сохранения настроек или чего угодно. 24C32 EEPROM использует интерфейс I2C для связи и использует ту же шину I2C, что и DS3231. Адрес I2C EEPROM можно легко изменить с помощью трех перемычек припоя A0, A1 и A2 на задней панели.


DS3231

Согласно спецификации 24C32, эти 3 бита размещаются в конце 7-битного адреса I2C, непосредственно перед битом чтения/записи. За счет короткого замыкания паяных перемычек адресные входы обнуляются. Это позволяет вам установить адрес I2C в соответствии с таблицей ниже.


DS3231

Модуль DS3231 RTC имеет всего 6 контактов, которые связывают его с внешним миром. Соединения следующие:


DS3231

Давайте подключим DS3231 к Arduino. Связь довольно проста. Начните с подключения контакта VCC к выходу 5V на Arduino и заземления. Теперь мы остаемся с выводами, которые используются для связи I2C. Обратите внимание, что каждая плата Arduino имеет разные контакты I2C, которые должны быть подключены соответствующим образом. На платах Arduino с разметкой R3 SDA (линия передачи данных) и SCL (линия синхронизации) находятся на разъемах выводов рядом с выводом AREF. Они также известны как A5 (SCL) и A4 (SDA). Если у вас есть Arduino Mega, контакты будут другие. Вы будете использовать цифровые 21 (SCL) и 20 (SDA). Принципиальная схема подключения DS3231 и Arduino Uno следующая:


Arduino и точные часы реального времени DS3231

Общение с модулем RTC – это куча работы. К счастью, была написана библиотека RTClib, чтобы скрыть все сложности, и мы могли выполнять простые команды для чтения данных RTC. Чтобы установить библиотеку, перейдите в раздел Sketch (Скетч) – Include Library (Включить библиотеку) – Manage Libraries (Управление библиотеками). Подождите, пока менеджер библиотеки загрузит индекс библиотек и обновит список установленных библиотек.


Arduino и точные часы реального времени DS3231

Отфильтруйте результаты поиска, набрав «rtclib». Там должны выйти пара записей. Ищите RTClib от Adafruit. Нажмите на эту запись, а затем выберите Install (Установить).


Arduino и точные часы реального времени DS3231

Следующий код программы даст вам полное понимание того, как установить/прочитать дату и время на модуле DS3231 RTC, этот скетч может послужить основой для более практических экспериментов и проектов.



#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () 
{
  Serial.begin(9600);
  delay(3000); // ждать открытия консоли

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
	
	// Закомментируйте ниже строки, как только вы установите дату и время
    // Следующая строка устанавливает RTC на дату и время компилирования этого скетча
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
	
    // Следующая строка устанавливает RTC с явной датой и временем
    // например, чтобы установить 27 января 2017 года в 12:56:
    // rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
  }
}

void loop () 
{
    DateTime now = rtc.now();
    
    Serial.println("Current Date & Time: ");
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.println("Unix Time: ");
    Serial.print("elapsed ");
    Serial.print(now.unixtime());
    Serial.print(" seconds/");
    Serial.print(now.unixtime() / 86400L);
    Serial.println(" days since 1/1/1970");
    
    // рассчитать дату, которая будет через 7 дней и 30 секунд
    DateTime future (now + TimeSpan(7,0,0,30));
    
    Serial.println("Future Date & Time (Now + 7days & 30s): ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(1000);
}

Вот как выглядит вывод данных в последовательном мониторе.


Arduino и точные часы реального времени DS3231

С модулем DS3231 RTC в качестве бонуса вы получаете 32 байта электрически стираемого ПЗУ. Его содержимое не будет удалено, даже если основное питание устройства будет прервано. Следующая программа пишет, а затем читает сообщение из 24C32 EEPROM. Вы можете использовать эту программу для сохранения настроек или паролей или чего угодно.



#include <Wire.h>

void setup()
{
    char somedata[] = "digitrode.ru"; // данные для записи
    Wire.begin();
    Serial.begin(9600);
    Serial.println("Writing into memory...");
	
	// записать в EEPROM
    i2c_eeprom_write_page(0x57, 0, (byte *)somedata, sizeof(somedata));

    delay(100); // добавить небольшую задержку
    Serial.println("Memory written");
}

void loop()
{
    Serial.print("Reading memory: ");
    int addr=0; // первый адрес
	
	// получить доступ к первому адресу из памяти
    byte b = i2c_eeprom_read_byte(0x57, 0);

    while (b!=0)
    {
        Serial.print((char)b); // вывести содержимое в последовательный порт
        addr++; // увеличить адрес
        b = i2c_eeprom_read_byte(0x57, addr); // получить доступ к адресу из памяти
    }
    Serial.println(" ");
    delay(2000);
}

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
    int rdata = data;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB (старший бит)
    Wire.write((int)(eeaddress & 0xFF)); // LSB (младший бит)
    Wire.write(rdata);
    Wire.endTransmission();
}

// ВНИМАНИЕ: адрес - это адрес страницы, 6-битный конец будет присутствовать
// Кроме того, данные могут быть максимум около 30 байтов, потому что библиотека Wire имеет буфер 32 байта
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddresspage >> 8)); // MSB
    Wire.write((int)(eeaddresspage & 0xFF)); // LSB
    byte c;
    for ( c = 0; c < length; c++)
        Wire.write(data[c]);
    Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
    byte rdata = 0xFF;
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,1);
    if (Wire.available()) rdata = Wire.read();
    return rdata;
}

// не будем читать больше 30 или 32 байта за раз
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
    Wire.beginTransmission(deviceaddress);
    Wire.write((int)(eeaddress >> 8)); // MSB
    Wire.write((int)(eeaddress & 0xFF)); // LSB
    Wire.endTransmission();
    Wire.requestFrom(deviceaddress,length);
    int c = 0;
    for ( c = 0; c < length; c++ )
        if (Wire.available()) buffer[c] = Wire.read();
}



© digitrode.ru


Теги: Arduino, часы реального времени, DS3231




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий