Закрыть
Часы реального времени (RTC) и Arduino

Часы реального времени (RTC) и Arduino

Часы реального времени (Real Time Clock, RTC) — это электронная схема, специально предназначенная для учета текущего времени, даты, дня недели и прочих временных и календарных данных. Широко используются в системах регистрации данных, при создании электронных часов, будильников, таймеров, управляющих устройств, работающих по расписанию. Как правило, такая схема, помимо учитывающего устройства включает и автономный источник питания, чтобы продолжать работать даже при выключении основной системы.  Часы реального времени ведут учет в единицах измерения времени, более привычных человеку (часы, минуты, годы и пр.), в отличие от тактовых генераторов и счетчиков, которые создают и считают просто «тики». Можно сказать, что часы реального времени — это тактовый генератор, специально предназначенный для отсчета времени.

Зачастую, микроконтроллеры, включая и Arduino, имеют функции для хранения времени, такие как millis () и имеют аппаратные таймеры, которые могут отслеживать более длительные временные интервалы, например, минуты и дни. Так зачем же нужны отдельные схемы часов реального времени?

Основная причина кроется в том, что millis () отслеживает время, прошедшее с момента последнего включения Arduino, при включении таймер миллисекунд устанавливается в ноль. Arduino не знает «вторник» сегодня или «23 февраля», все что ему известно, так это то, что с момента последнего включения прошло, например, 14763 миллисекунды.

Что если мы захотим установить время на Arduino? В программе нужно было бы задать некоторую точку отсчета, относительно которой бы считать время и даты. Но при отключении питания время бы сбросилось. Именно это и  происходит в недорогих моделях будильников, когда при отключении питания начинает мигать «12:00». Для каких-то задач это вполне приемлемо, но в некоторых случаях важно продолжать отсчет времени, даже если питание пропадает. Вот в этом случае на помощь и приходят специализированные микросхемы RTC, имеющие автономный источник питания.

Большинство схем часов реального времени использует кварцевый резонатор, работающий на частоте 32768 Гц. 32768 = 215 тактов в секунду, что очень удобно для простых двоичных счётчиков.

Многие производители выпускают собственные микросхемы часов реального времени. Среди них Texas Instruments, Dallas SemocinductorSTMicroelectronicsIntersil, Maxim, Philips. Достаточно популярными являются микросхемы DS1307 от Dallas Semiconductor и ее полный, но более дешевый аналог M41T56 от STMicroelectronics. Также широко используется микросхема DS3231, которая имеет встроенный кварц и термостабилизацию, что позволяет получить повышенную точность в сравнении с DS1307. С точки зрения программиста, отличие между ними — это разные адреса и назначение битов в Control register. Так что, если изменения в программе если и придется вносить, то совсем незначительные.

Я некоторое время назад приобрел модуль MP1095 производства «Мастер Кит», основанный на микросхеме M41T56M6, поэтому я свои эксперименты буду проводить, используя именно этот модуль. Он полностью совместим с устройствами, в основе которых лежит DS1307, что позволяет использовать популярные библиотеки часов реального времени для последнего.

Принципиальная схема модуля MP1095:

Принципиальная схема модуля Masterkit 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-корпусе.

Расположение и назначение выводов

Распиновка M41T56

  • OSCI — вход кварца
  • OCSO — выход кварца
  • FT/OUT — тест частоты/выходной драйвер (с открытым стоком)
  • SDA — адресная линия вход/выход
  • SCL — выход данных
  • VBAT — питание от батареи
  • VCC — внешний источник питания
  • VSS — земля

Блок-схема MT41T56
Блок-схема MT41T56

Операции

Часы реального времени M41T56 работают как ведомое устройство на последовательной шине. Доступ получается реализацие условия запуска, за которым следует правильный адрес ведомого (D0h). К 64 байтам памяти, имеющимся в устройстве, можно получить последовательно доступ в следующем порядке:

  1. Регистр секунд
  2. Регистр минут
  3. Регистр век/часы
  4. Регистр дня недели
  5. Регистр даты
  6. Регистр месяца
  7. Регистр года
  8. Управляющий регистр
  9. ОЗУ

Микросхема постоянно отслеживает VCC на выход за допустимые пределы. Если VCC падает ниже VPFD, устройство прекращает дальнейший доступ и сбрасывает адрес счетчика. Входы устройства не будут признаны в это время, для предотвращения записи ошибочных данных на устройство с отказом от системы допуска. Когда VCC падает ниже VBAT, устройство автоматически переключается на аккумулятор в режим с пониженным энергопотреблением для экономии заряда аккумулятора. После подключения внешнего питания, устройство переключается с батарейного питания VBAT на VCC и считывает входы при превышении VCC в вольтах над VPFD.

В микросхеме имеется программируемый генератор прямоугольных импульсов, позволяющий вырабатывать одну из четырех частот (1 гц, 4096 Гц, 8192 Гц или 32768 Гц).

Полная версия datasheet на M41T56

Datasheet M41T56
Datasheet M41T56
datasheet_M41T56.pdf
478.2 KiB
480 Downloads
Детали

 

Библиотеки Arduino для работы с RTC

Для работы с часами реального времени, в основе которых лежит микросхема DS1307 или аналогичные потребуются специальные библиотеки

1. Библиотека Time (оф.сайт)

Time
Time
Time.zip
25.2 KiB
3099 Downloads
Детали

2. Библиотека DS1307RTC (оф.сайт)

DS1307RTC
DS1307RTC
DS1307RTC.zip
5.0 KiB
2982 Downloads
Детали

Для установки скачиваем файлы и переносим их в папку с библиотеками. Также можно устанавливать библиотеки, используя менеджер библоитек. Подробнее об установке библиотек в среде 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.

Подключение MP1095 к шилду DFRobot MegaSensor

  • VDD используется для питания микросхемы RTC для получения с него временных данных. Если напряжение +5 В отсутствует, микросхема переходит в спящий режим для сохранения и отсчета времени.
  • GND — земля (общий провод)
  • SCL — тактирующий вывод I2C интерфейса (нужен для коммуникации с часами реального времени)
  • SDA — вывод данных I2C интерфейса (нужен для коммуникации с RTC)
  • SQW (на некоторых аналогичных модулях RTC) — дополнительный выход прямоугольного сигнала частотой 32768 Гц. В большинстве случаев не используется.

Подключение модуля RTC к Arduino

Подключите аналоговый 20 пин Arduino Mega (аналоговый 4 пин для других плат Arduino) к выводу SDA модуля и 21 пин (5 — для других плат) к выводу SCL.
 

Тестируем часы реального времени

Первым делом посмотрим тестовый скетч, который считывает время с модуля RTC один раз в секунду. Также выясним, что произойдет, если снять батарею и заменить ее, что заставляет часы реального времени сбросится. Прежде всего, снимем батарею при отключенном питании Arduino. Подождем 3 секунды и вернем батарею на место. Это приведет к сбросу RTC.

Выберем пример скетча из меню Arduino IDE Файл → ОбразцыDS1307RTC → ReadTest и загрузим его в микроконтроллер

Отобразить/скрыть пример кода 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 бод.

У вас должно получиться что-то похожее

Результат выполнения тестового скетча ReadTest

 

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

 

Установка времени

Для установки времени воспользуемся другим примером из этой же библиотеки.

Откроем пример Файл → Образцы → DS1307RTC → SetTime и загрузим его в 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;
}

Открыв монитор порта, видим, что время теперь установлено правильно

Пример скетча SetTime для RTC

Вновь вернемся к примеру ReadTest, скомпилируем его, загрузим в микроконтроллер и посмотрим на результат.

Результат работы 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, если модуль подключен

[add_ratings]

Оставить ответ

Ваш email не будет опубликован.Обязательны поля помечены *