DS3231: подключение к ESP32 и Arduino

Модуль часов реального времени

Точные часы с батарейкой: помнят время при выключенном питании и уходят не больше чем на минуту в год. Шина I2C, библиотека RTClib.

Как работает

DS3231 — часы с термокомпенсированным кварцем внутри микросхемы, отсюда точность ±2 ppm (около минуты в год). Батарейка CR2032 держит ход годами без основного питания. Кроме времени, микросхема умеет два будильника и выдаёт температуру (её датчик нужен для компенсации кварца).

Библиотека RTClib: rtc.begin(), rtc.now() возвращает дату и время, rtc.adjust() устанавливает. Адрес на шине I2C — 0x68.

Выводы

ВыводНазначение
SCLтактовая линия I2C
SDAлиния данных I2C
SQWвыход меандра или сигнал будильника (прерывание); для часов не нужен
VCCпитание 3,3–5 В
GNDобщий провод

Подключение к ESP32

DS3231ESP32
SCLGPIO22
SDAGPIO21
VCC3V3
GNDGND

Схема из примера «Часы: поставить время и читать».

Часы: поставить время и читать

Открыть пример целиком
Код скетча
#include <RTClib.h>

RTC_DS3231 rtc;

void setup() {
  Serial.begin(115200);
  delay(200);

  if (!rtc.begin()) {
    Serial.println("часы не отвечают: проверьте SDA, SCL и питание");
    while (true) delay(1000);
  }

  // Признак «часы стояли» микросхема поднимает, когда пропадало
  // питание. Ставить время каждый запуск нельзя: тогда часы всегда
  // будут показывать время последней прошивки, а не текущее.
  if (rtc.lostPower()) {
    Serial.println("часы стояли — ставлю время сборки");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() {
  DateTime now = rtc.now();
  Serial.printf("%04d-%02d-%02d %02d:%02d:%02d\n",
                now.year(), now.month(), now.day(),
                now.hour(), now.minute(), now.second());
  delay(1000);
}

Подключение к Arduino Uno

DS3231Arduino Uno
SCLA5
SDAA4
VCC5V
GNDGND

Схема из примера «Arduino Uno: часы реального времени».

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

Открыть пример целиком
Код скетча
#include <Wire.h>
#include <RTClib.h>

// Часы DS3231 на шине I2C — у Uno это A4 и A5.
//
// Зачем отдельная микросхема, когда есть millis(). millis() считает от
// включения платы: после сброса он снова ноль, а после отключения
// питания плата не знает даже, какой сегодня год. DS3231 держит время
// сама, от батарейки, годами — и уходит примерно на минуту в год
// против нескольких минут в сутки у самодельного счётчика на кварце.
//
// Установка времени идёт один раз. Строка __DATE__ и __TIME__ — это
// момент СБОРКИ скетча, а не текущее время: после первой прошивки
// строку с adjust полагается закомментировать, иначе каждая заливка
// будет откатывать часы на момент компиляции.

RTC_DS3231 rtc;

void setup() {
  Serial.begin(9600);

  if (!rtc.begin()) {
    Serial.println(F("часы не отозвались: проверьте A4 и A5"));
    return;
  }

  // Только при первой прошивке или после замены батарейки.
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    Serial.println(F("время выставлено по моменту сборки"));
  }
}

void loop() {
  DateTime now = rtc.now();

  // Ведущие нули руками: библиотека печатает 9, а часам нужно 09.
  Serial.print(now.hour());
  Serial.print(':');
  if (now.minute() < 10) Serial.print('0');
  Serial.print(now.minute());
  Serial.print(':');
  if (now.second() < 10) Serial.print('0');
  Serial.print(now.second());

  Serial.print(F("  температура: "));
  Serial.println(rtc.getTemperature(), 1);

  delay(1000);
}

В железе

На популярном модуле ZS-042 стоит цепь зарядки батарейки (резистор 200 Ом и диод). Для обычной CR2032 это вредно: её нельзя заряжать. Либо выпаивают резистор, либо ставят аккумулятор LIR2032.

Частые ошибки

Другие детали