Модуль RTC для Arduino: DS3231, DS1307 и DS1302, часы и будильники
Модуль RTC для Arduino: чем отличаются DS3231, DS1307 и DS1302, как установить время через RTClib, часы на LCD, автополив по расписанию, ловушка с зарядкой CR2032 и NTP на ESP32.
Модуль RTC для Arduino — это небольшая плата часов, которая продолжает отсчитывать дату и время, даже когда основная плата обесточена. RTC расшифровывается как «Real Time Clock», то есть часы реального времени. Собственный счётчик millis() у Arduino при каждом включении начинает с нуля и за несколько дней может уйти на минуты, а модуль RTC благодаря батарейке-таблетке (CR2032) годами идёт с точностью до секунды. Этот модуль встречается в настольных часах, системах автополива, кормушках для питомцев, регистраторах данных с метками времени и проектах с освещением по таймеру.
В этом руководстве сравниваются три самые распространённые микросхемы — DS1307, DS3231 и DS1302: какую выбрать и почему. Затем шаг за шагом установим и прочитаем время с библиотекой RTClib, выведем время и дату на I2C LCD, соберём таймер, который каждый день в заданное время включает насос, и задействуем аппаратный будильник DS3231. В последних разделах — ловушка со схемой зарядки CR2032, которая губит многие модули, получение времени из интернета по NTP на ESP32 и встроенный RTC у Raspberry Pi Pico.

Что такое модуль RTC и как он работает?
Сердце микросхемы RTC — часовой кварц на 32,768 kHz. Это число выбрано не случайно: 32 768 — это 2 в 15-й степени, поэтому микросхема 15 раз делит частоту пополам и получает ровно один тик в 1 секунду. С каждым тиком обновляются регистры секунд, минут, часов, дня, месяца и года; длина месяцев и високосные годы учитываются автоматически вплоть до 2100 года. Arduino читает эти регистры по I2C или записывает в них новое время. Значения хранятся в формате BCD (например, 59 секунд хранятся как 0x59); это преобразование библиотеки выполняют за тебя.
Главная хитрость RTC — два входа питания. Когда VCC пропадает, микросхема автоматически переключается на вход батарейки (VBAT) и потребляет ровно столько, сколько нужно для отсчёта времени: меньше микроампера или несколько микроампер. При этом DS1307 отключает доступ по I2C, а DS3231 можно читать и от батарейки; в обоих случаях часы не останавливаются. Когда питание возвращается, Arduino запускается, считывает из RTC точное время и продолжает с того места, где остановилась. Из-за допуска керамического резонатора на Arduino Uno часы на millis() могут уходить на минуты в сутки и сбрасываются при каждом перезапуске, поэтому любому проекту, завязанному на время, нужен отдельный RTC.
DS1307, DS3231 и DS1302: в чём разница
| Характеристика | DS1307 | DS3231 | DS1302 |
|---|---|---|---|
| Интерфейс | I2C (100 kHz), адрес 0x68 | I2C (до 400 kHz), адрес 0x68 | 3-проводной последовательный: CE (RST), I/O (DAT), SCLK (CLK) |
| Напряжение питания | 4,5–5,5 V | 2,3–5,5 V | 2,0–5,5 V |
| Кварц | Внешний, 32,768 kHz (12,5 pF) | Встроен в микросхему, с термокомпенсацией (TCXO) | Внешний, 32,768 kHz (6 pF) |
| Точность | Зависит от кварца; при ±20 ppm около 1,7 с в сутки, около 1 мин в месяц | ±2 ppm (0–40 °C): около 5 с в месяц, около 1 мин в год | Зависит от кварца; как у DS1307 или хуже |
| Дополнительно | 56 байт ОЗУ с питанием от батарейки, выход меандра (SQW) | 2 будильника, выход INT/SQW, датчик температуры (±3 °C), подстройка старения | 31 байт ОЗУ, встроенная схема подзарядки (trickle charger) |
| Ток от батарейки | Около 300–500 nA | Около 1–3 µA | Меньше 300 nA при 2 V |
| Библиотека Arduino | RTClib (Adafruit) | RTClib (Adafruit) | Rtc by Makuna (библиотека Makuna) |
| Для чего лучше | Простые часы на 5 V | Почти любой проект; идеален и для ESP32, и для Pico | Старые наборы и учебные проекты |
Сделаем разницу в точности наглядной: 1 ppm — это одна миллионная доля, а в сутках 86 400 секунд. Обычный кварц с ±20 ppm может уходить до 1,7 секунды в сутки, около 52 секунд в месяц, и чем дальше от комнатной температуры, тем сильнее меняется частота кварца и тем больше ошибка. DS3231 же держит кварц внутри микросхемы, каждые 64 секунды измеряет температуру и корректирует частоту. Так получается ±2 ppm в диапазоне 0–40 °C, примерно минута в год, и даже от -40 до +85 °C точность остаётся в пределах ±3,5 ppm.
Какой модуль RTC выбрать?
- Новый проект, ESP32 или Pico: бери DS3231. Он работает и от 3,3 V, и от 5 V, умеет будильники и точнее всех держит время. Разница в цене совсем небольшая.
- Уже есть DS1307 и Arduino Uno: смело используй его; просто учитывай уход около минуты в месяц и время от времени подводи часы.
- В стартовом наборе оказался DS1302: он подходит, чтобы понять, как работает RTC, но не жди от него часов, которые месяцами идут точно.
- ESP32 с постоянным подключением к интернету: начни с NTP без модуля; добавь DS3231, если время должно быть известно после отключения питания ещё до того, как появится интернет.
Чаще всего встречаются две готовые платы: ZS-042 на микросхеме DS3231 и Tiny RTC на DS1307. На обеих есть ещё EEPROM AT24C32 на 4 КБ для хранения данных. Поэтому при запуске I2C-сканера рядом с 0x68 нормально увидеть второй адрес (обычно 0x57 у ZS-042 и 0x50 у Tiny RTC); этот адрес принадлежит EEPROM, а не часам. DS1302 вообще не использует I2C: он общается по собственному 3-проводному протоколу и занимает три цифровых пина.
Подключение модуля RTC: Arduino Uno, ESP32 и Pico
| Пин RTC | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 (DS3231) | 3V3(OUT), физический пин 36 (DS3231) |
| GND | GND | GND | GND |
| SDA | A4 | GPIO 21 | GP4 (I2C0) |
| SCL | A5 | GPIO 22 | GP5 (I2C0) |
| SQW / INT (по желанию) | D2 (пин прерывания) | Любой GPIO (например, GPIO 4) | Любой пин GP (например, GP15) |
На Uno R3 выводы SDA и SCL рядом с пином AREF тоже соединены с A4 и A5, так что неважно, какие из них использовать. RTC может делить те же два провода с I2C LCD или OLED-дисплеем: у каждого устройства свой адрес, поэтому конфликта нет. Провода короче 20–30 см избавляют от случайных ошибок чтения, особенно на макетной плате. Пин SQW/INT нужно подключать, только если планируешь пользоваться аппаратным будильником.
Установка RTClib и настройка времени
- Открой в Arduino IDE «Менеджер библиотек» (Library Manager), введи RTClib и установи библиотеку от Adafruit. Когда появится вопрос о зависимостях, выбери Install all («Установить все»), чтобы заодно установилась Adafruit BusIO. Если библиотеки раньше не добавлялись, всё пошагово описано в статье Как добавить библиотеку в Arduino.
- Подключи модуль по таблице выше и вставь батарейку в держатель.
- Загрузи код ниже. При первом запуске модуль не знает времени, поэтому код записывает в RTC время компиляции с твоего компьютера.
- Открой монитор порта на скорости 9600 бод с окончанием строки «Newline» (новая строка). Чтобы выставить время с точностью до секунды, введи его в виде 2026-11-03 14:30:00 и нажми Enter.
- Отключи USB-кабель, подожди несколько минут и подключи снова. Если часы правильно продолжают идти с того места, где остановились, резервное питание от батарейки работает.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc; // DS1307 kullanıyorsan: RTC_DS1307 rtc; / for a DS1307: RTC_DS1307 rtc;
5
6void setup() {
7 Serial.begin(9600);
8 if (!rtc.begin()) { // modül I2C hattında yok / module not found on the I2C bus
9 Serial.println(F("RTC bulunamadi / RTC not found"));
10 while (true);
11 }
12 if (rtc.lostPower()) { // ilk çalıştırma ya da pil bitmiş / first run or dead battery
13 rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // derleme saatini yaz / write the compile time
14 Serial.println(F("Saat derleme zamanina ayarlandi / Clock set to compile time"));
15 }
16 Serial.println(F("Ayar icin yaz / To set, type: 2026-11-03 14:30:00"));
17}
18
19void loop() {
20 // Seri monitörden saat geldiyse ayarla / set the time sent from the Serial Monitor
21 if (Serial.available()) {
22 String line = Serial.readStringUntil('\n');
23 int y, mo, d, h, mi, s;
24 if (sscanf(line.c_str(), "%d-%d-%d %d:%d:%d", &y, &mo, &d, &h, &mi, &s) == 6) {
25 rtc.adjust(DateTime(y, mo, d, h, mi, s));
26 Serial.println(F("Saat ayarlandi / Time set"));
27 }
28 }
29
30 DateTime now = rtc.now();
31 char buf[] = "DD.MM.YYYY hh:mm:ss"; // biçim şablonu / format template
32 Serial.print(now.toString(buf));
33 Serial.print(F(" "));
34 Serial.print(rtc.getTemperature()); // yalnız DS3231 / DS3231 only
35 Serial.println(F(" C"));
36 delay(1000);
37}rtc.begin() возвращает false, если модуль не найден на шине I2C; в этом случае сначала проверь подключение. rtc.lostPower() читает флаг остановки генератора DS3231 (OSF): он возвращает true, если модуль запускается впервые или часы остановились из-за севшей батарейки, и тогда код выставляет время компиляции. DateTime(F(__DATE__), F(__TIME__)) берёт момент, когда компилятор собрал код; загрузка занимает несколько секунд, поэтому часы немного отстают, и точная подстройка через монитор порта очень кстати. toString() заменяет буквы в шаблоне «DD.MM.YYYY hh:mm:ss» реальными значениями.
| Функция | Что делает |
|---|---|
| rtc.begin() | Запускает модуль; возвращает false, если он не найден |
| rtc.adjust(DateTime(...)) | Записывает время и дату |
| rtc.now() | Читает текущее время как объект DateTime |
| now.year(), now.month(), now.day() (дата) | Год, месяц, день |
| now.hour(), now.minute(), now.second() (время) | Час (0–23), минута, секунда |
| now.dayOfTheWeek() | День недели: 0 = воскресенье, 6 = суббота |
| now.unixtime() | Секунды с 1 января 1970 года; идеально для сравнения двух моментов времени |
| now + TimeSpan(0, 1, 30, 0) | Прибавляет 1 час 30 минут (дни, часы, минуты, секунды) |
| rtc.lostPower() / rtc.isrunning() (проверка) | Показывает, верно ли время (DS3231 / DS1307) |
| rtc.getTemperature() | Температура микросхемы в °C (только DS3231) |
Для DS1307 отличие только в имени объекта: напиши RTC_DS1307 rtc;, вместо lostPower() используй проверку !rtc.isrunning() и удали строку с getTemperature(). При самой первой подаче питания генератор DS1307 стоит (бит CH равен 1); adjust() сбрасывает этот бит и запускает часы. Небольшие настройки, например время будильника, можно хранить в 56 байтах ОЗУ DS1307 с питанием от батарейки через rtc.writenvram() и rtc.readnvram(); благодаря батарейке эти данные тоже переживают отключения питания.
Время и дата на LCD-дисплее
Время на дисплее вместо монитора порта превращает проект в настоящие настольные часы. 16x2 I2C LCD и RTC подключаются к одной шине SDA-SCL: у LCD обычно адрес 0x27 или 0x3F, у RTC — 0x68. Код ниже выводит в верхнюю строку дату и сокращение дня недели, а в нижнюю — время и температуру, измеренную DS3231. Подключение LCD и установка библиотеки описаны в статье Как пользоваться I2C LCD-дисплеем.
1#include <Wire.h>
2#include <RTClib.h>
3#include <LiquidCrystal_I2C.h>
4
5RTC_DS3231 rtc;
6LiquidCrystal_I2C lcd(0x27, 16, 2); // adres 0x27 ya da 0x3F / address 0x27 or 0x3F
7
8// dayOfTheWeek(): 0 = Pazar / 0 = Sunday
9const char* const days[7] = {"Paz", "Pzt", "Sal", "Car", "Per", "Cum", "Cmt"};
10int lastSecond = -1;
11
12void setup() {
13 lcd.init();
14 lcd.backlight();
15 if (!rtc.begin()) {
16 lcd.print("RTC yok!"); // modül bulunamadı / module not found
17 while (true);
18 }
19 if (rtc.lostPower()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
20}
21
22void loop() {
23 DateTime now = rtc.now();
24 if (now.second() == lastSecond) return; // saniye değişmediyse yazma / skip until the second changes
25 lastSecond = now.second();
26
27 char line1[17], line2[17];
28 snprintf(line1, sizeof(line1), "%02d.%02d.%04d %s",
29 now.day(), now.month(), now.year(), days[now.dayOfTheWeek()]);
30 snprintf(line2, sizeof(line2), "%02d:%02d:%02d %2dC",
31 now.hour(), now.minute(), now.second(), (int)rtc.getTemperature());
32 lcd.setCursor(0, 0);
33 lcd.print(line1); // ör. / e.g. 03.11.2026 Sal
34 lcd.setCursor(0, 1);
35 lcd.print(line2); // ör. / e.g. 14:05:09 23C
36}%02d внутри snprintf добавляет ведущий ноль к однозначным числам, поэтому время показывается как 09:05:03, а не 9:5:3, и длина строки никогда не меняется. Благодаря постоянной длине lcd.clear() не нужен: очистка экрана в каждом цикле вызывает мерцание. Код пишет на дисплей только при смене секунды, поэтому зря не занимает шину I2C. В массиве days лежат турецкие сокращения; замени их на Вс, Пн, Вт и так далее, оставив воскресенье первым элементом.
Будильники и задачи по расписанию: автополив и кормление питомца
Самое полезное в RTC — выполнять дела по расписанию: поливать растения каждое утро в 08:00, насыпать коту корм в 19:30 или выключать свет в аквариуме на ночь. Сделать это можно двумя способами. Первый — программное сравнение: в loop() читается время и проверяется, не настал ли момент задачи. Это просто, и задач можно добавить сколько угодно. Второй — аппаратный будильник DS3231: в заданный момент микросхема переводит пин INT в LOW и сообщает Arduino через прерывание; так можно разбудить даже спящий микроконтроллер.
Частая ошибка при программном сравнении — проверять точную секунду, например now.second() == 0. Если в loop() есть долгий delay(), эта секунда может проскочить, и задача так и не выполнится. Код ниже сравнивает часы и минуты, хранит ключ из дня и минуты, чтобы задача не запустилась дважды за одну минуту, и отсчитывает время работы насоса через millis(). Насос управляется через модуль реле; подключение насоса описано в статье о мини-насосе для воды.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5
6const byte RELAY_PIN = 7;
7const byte RELAY_ON = LOW; // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
8const byte RELAY_OFF = HIGH;
9const unsigned long RUN_MS = 10000; // pompa 10 saniye çalışır / the pump runs for 10 seconds
10
11struct Task { byte hour; byte minute; };
12Task tasks[] = { {8, 0}, {19, 30} }; // her gün 08:00 ve 19:30 / every day at 08:00 and 19:30
13const byte TASK_COUNT = sizeof(tasks) / sizeof(tasks[0]);
14
15long lastRunKey = -1; // aynı dakikada ikinci kez çalışmasın / never run twice in one minute
16bool running = false;
17unsigned long startMs = 0;
18
19void setup() {
20 pinMode(RELAY_PIN, OUTPUT);
21 digitalWrite(RELAY_PIN, RELAY_OFF); // açılışta kapalı / off at start-up
22 rtc.begin();
23}
24
25void loop() {
26 DateTime now = rtc.now();
27 long key = (long)now.day() * 1440 + now.hour() * 60 + now.minute(); // gün + dakika / day + minute
28
29 for (byte i = 0; i < TASK_COUNT; i++) {
30 if (now.hour() == tasks[i].hour && now.minute() == tasks[i].minute && key != lastRunKey) {
31 lastRunKey = key;
32 running = true;
33 startMs = millis();
34 digitalWrite(RELAY_PIN, RELAY_ON); // pompayı aç / pump on
35 }
36 }
37
38 if (running && millis() - startMs >= RUN_MS) {
39 running = false;
40 digitalWrite(RELAY_PIN, RELAY_OFF); // pompayı kapat / pump off
41 }
42 delay(200);
43}День в ключе важен: если хранить только минуту и задача одна, на следующий день в ту же минуту ключ останется прежним, и задача больше никогда не выполнится. Для кормушки вместо реле используй сервопривод: поворот на 90 градусов в момент задачи и возврат через секунду открывает заслонку бункера и высыпает одну порцию корма. Чтобы полив стал умнее, в момент задачи считай показания датчика влажности почвы и не включай насос, если почва и так влажная. Второй пример ниже делает то же самое через аппаратный будильник DS3231.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5const byte ALARM_PIN = 2; // DS3231 SQW/INT -> D2 (kesme pini / interrupt pin)
6volatile bool alarmFlag = false;
7
8void onAlarm() { // kesme fonksiyonu kısa olmalı / keep the ISR short
9 alarmFlag = true;
10}
11
12void setup() {
13 Serial.begin(9600);
14 rtc.begin();
15 rtc.disable32K(); // 32K çıkışını kapat / turn off the 32K output
16 rtc.writeSqwPinMode(DS3231_OFF); // SQW pini alarm çıkışı olur / SQW becomes the alarm output
17 rtc.clearAlarm(1);
18 rtc.clearAlarm(2);
19 rtc.disableAlarm(2);
20
21 // Her gün 07:30:00; tarih kısmı yok sayılır / every day at 07:30:00; the date part is ignored
22 rtc.setAlarm1(DateTime(2026, 1, 1, 7, 30, 0), DS3231_A1_Hour);
23
24 pinMode(ALARM_PIN, INPUT_PULLUP); // INT çıkışı open-drain / INT is an open-drain output
25 attachInterrupt(digitalPinToInterrupt(ALARM_PIN), onAlarm, FALLING);
26}
27
28void loop() {
29 if (alarmFlag) {
30 alarmFlag = false;
31 rtc.clearAlarm(1); // temizlenmezse pin LOW kalır / the pin stays LOW until cleared
32 Serial.println(F("Alarm: mama vakti / Feeding time"));
33 // Servo, röle ya da buzzer kodunu buraya yaz / put your servo, relay or buzzer code here
34 }
35}У DS3231 два будильника. Будильник 1 работает с точностью до секунды; режим DS3231_A1_Hour срабатывает при совпадении часов, минут и секунд, то есть каждый день в одно и то же время. Другие режимы позволяют поставить будильник каждую секунду (PerSecond), каждую минуту (Second), каждый час (Minute), на определённое число месяца (Date) или на определённый день недели (Day). Будильник 2 работает с точностью до минуты. Пин SQW/INT — выход с открытым стоком и активным LOW: при срабатывании будильника он переходит в LOW и остаётся так, пока не вызвана clearAlarm(). Поэтому лучше всего в функции прерывания только поднимать флаг, а основную работу делать в loop(). Как работают прерывания, рассказано в статье Прерывания в Arduino.
Сколько служит батарейка RTC?
Оценить срок службы батарейки просто: время работы (ч) = ёмкость батарейки (mAh) ÷ потребляемый ток (mA). Ёмкость CR2032 — около 220 mAh. В режиме батарейки DS3231 в худшем случае потребляет около 3 µA, то есть 0,003 mA: 220 ÷ 0,003 ≈ 73 000 часов, или примерно 8 лет. Батарейка расходуется только когда VCC отключено; если модуль стоит в устройстве, которое всегда под питанием, батарейка почти не тратится и служит гораздо дольше. На практике предел обычно задают собственный срок хранения батарейки и схема зарядки на модуле.
| Микросхема | Ток от батарейки | Расчётное время работы от CR2032 (220 mAh) |
|---|---|---|
| DS1307 | ~0,5 µA | ~50 лет; на практике ограничено сроком хранения батарейки (около 10 лет) |
| DS3231 | ~3 µA (в худшем случае) | ~8 лет |
| DS1302 | ~0,3 µA | Ограничено сроком хранения батарейки |
| Модуль с включённой схемой зарядки + CR2032 | В батарейку принудительно идёт ток | Непредсказуемо; элемент может вздуться и быстро выйти из строя |
Батарейка CR2032 и ловушка со схемой зарядки
У большинства дешёвых модулей DS3231 (ZS-042) и DS1307 (Tiny RTC) есть простая схема зарядки, рассчитанная на самом деле на аккумулятор LIR2032. На ZS-042 ток идёт от VCC к батарейке через диод 1N4148 и резистор 200 Ω; у Tiny RTC похожая схема. Беда в том, что эти модули часто продаются с незаряжаемой CR2032. Когда модуль работает от 5 V, оставшиеся после диода примерно 4,3 V постоянно гонят ток в литиевый элемент на 3 V. Элемент, который не рассчитан на зарядку, со временем может вздуться, потечь и преждевременно разрядиться, и в итоге появляется проблема «батарейка стоит, а часы всё равно сбрасываются».
- Если стоит CR2032, разорви цепь зарядки: на ZS-042 выпаяй SMD-резистор 200 Ω с маркировкой «201» рядом с гребёнкой пинов или соседний диод. Для резисторов с непонятной маркировкой пригодится утилита SMD-кодов. Это самый распространённый и безопасный способ.
- Если схему оставить как есть, ставь LIR2032: ёмкость аккумулятора (около 40 mAh) примерно в пять раз меньше, чем у CR2032 (около 220 mAh), зато, пока на модуле есть питание, он остаётся заряженным.
- Если модуль питается от 3,3 V: после диода до батарейки доходит только около 2,6 V; LIR2032 никогда не заряжается полностью, а в CR2032 ток почти не идёт. И всё же самое чистое решение — выпаять резистор.
- Встроенная схема подзарядки DS1302 при включении выключена; если стоит CR2032, не включай её в коде.
- Измерь батарейку: новая CR2032 показывает 3,0–3,2 V; если напряжение упало ниже 2,5 V, меняй её.
Работа с DS1302 (3-проводное подключение)

У модуля DS1302 пять пинов: VCC, GND, CLK, DAT и RST. Поскольку I2C он не использует, подключается не к A4-A5, а к любым трём цифровым пинам; в примере ниже DAT идёт на D4, CLK на D5, RST на D2, а модуль питается от 5V. RTClib от Adafruit не поддерживает DS1302, поэтому установи через «Менеджер библиотек» библиотеку Rtc by Makuna. У DS1302 два защитных бита: пока включена защита от записи, время не установить, а пока выставлен бит остановки, часы не идут. Код проверяет оба и выставляет время компиляции, если сохранённое время неверно.
1#include <RtcDS1302.h>
2
3ThreeWire myWire(4, 5, 2); // DAT, CLK, RST pinleri / DAT, CLK, RST pins
4RtcDS1302<ThreeWire> rtc(myWire);
5
6void setup() {
7 Serial.begin(9600);
8 rtc.Begin();
9 if (rtc.GetIsWriteProtected()) rtc.SetIsWriteProtected(false); // yazma korumasını kaldır / remove write protection
10 if (!rtc.GetIsRunning()) rtc.SetIsRunning(true); // saati başlat / start the clock
11
12 RtcDateTime compiled(__DATE__, __TIME__);
13 if (!rtc.IsDateTimeValid() || rtc.GetDateTime() < compiled) {
14 rtc.SetDateTime(compiled); // derleme saatine ayarla / set to compile time
15 }
16}
17
18void loop() {
19 RtcDateTime now = rtc.GetDateTime();
20 char buf[20];
21 snprintf(buf, sizeof(buf), "%02u.%02u.%04u %02u:%02u:%02u",
22 now.Day(), now.Month(), now.Year(), now.Hour(), now.Minute(), now.Second());
23 Serial.println(buf);
24 delay(1000);
25}Самая частая жалоба на модули DS1302 — часы уходят на минуты за неделю. Одна из причин в том, что микросхеме нужен кварц, рассчитанный на ёмкость нагрузки 6 pF, а в дешёвых модулях ставят кварцы с другими параметрами. Длинные и плохо закреплённые провода тоже вызывают ошибки чтения на последовательной линии DS1302. DS1302 отлично подходит, чтобы разобраться, как работает RTC; но для часов, которые должны месяцами идти точно, переходи на DS3231.
NTP вместо RTC на ESP32: время из интернета
ESP32 умеет подключаться к Wi-Fi, поэтому часто модуль RTC ей вообще не нужен: по NTP (Network Time Protocol) она за несколько секунд получает точное время от серверов вроде pool.ntp.org. В ядре ESP32 для Arduino для этого есть готовые функции configTzTime() и getLocalTime(), а часовой пояс задаётся строкой-правилом. Турция с 2016 года живёт по UTC+3 без перехода на летнее время, поэтому правило в коде — постоянное смещение на +3 часа. В регионах с летним временем, как в большей части Европы, правило для Центральной Европы из комментария в коде само вычисляет даты перехода; для Великобритании используй «GMT0BST,M3.5.0/1,M10.5.0».
Слабое место NTP — зависимость от интернета: после отключения питания, пока не загрузился роутер, или после смены пароля Wi-Fi ESP32 не может узнать время. Собственный внутренний RTC-таймер ESP32 держит время во время глубокого сна, но сбрасывается при полном пропадании питания. Самое надёжное решение — сочетать оба способа: при запуске ESP32 синхронизирует DS3231 со временем из интернета, если NTP доступен, иначе читает время из DS3231, и раз в день синхронизируется заново. Подробнее о NTP — в статье Время по NTP на ESP32.
1#include <WiFi.h>
2#include <Wire.h>
3#include <RTClib.h>
4#include <time.h>
5
6const char* WIFI_SSID = "AgAdin"; // Wi-Fi ağ adı / Wi-Fi network name
7const char* WIFI_PASS = "Sifren"; // Wi-Fi şifresi / Wi-Fi password
8// Türkiye: UTC+3, yaz saati yok / Turkey: UTC+3, no daylight saving
9// Orta Avrupa / Central Europe: "CET-1CEST,M3.5.0,M10.5.0/3"
10const char* TZ_INFO = "<+03>-3";
11
12RTC_DS3231 rtc;
13unsigned long lastSync = 0;
14
15void syncFromNtp() {
16 struct tm t;
17 if (getLocalTime(&t, 10000)) { // en fazla 10 sn bekle / wait up to 10 s
18 rtc.adjust(DateTime(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec));
19 Serial.println("DS3231 NTP ile ayarlandi / DS3231 synced from NTP");
20 }
21 lastSync = millis();
22}
23
24void setup() {
25 Serial.begin(115200);
26 Wire.begin(21, 22); // SDA, SCL pinleri / SDA, SCL pins
27 rtc.begin();
28
29 WiFi.begin(WIFI_SSID, WIFI_PASS);
30 unsigned long start = millis();
31 while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) delay(250);
32
33 if (WiFi.status() == WL_CONNECTED) {
34 configTzTime(TZ_INFO, "pool.ntp.org", "time.google.com");
35 syncFromNtp();
36 } else {
37 Serial.println("Wi-Fi yok, DS3231 saati kullaniliyor / No Wi-Fi, using the DS3231");
38 }
39}
40
41void loop() {
42 DateTime now = rtc.now();
43 char buf[] = "DD.MM.YYYY hh:mm:ss";
44 Serial.println(now.toString(buf));
45
46 if (WiFi.status() == WL_CONNECTED && millis() - lastSync > 86400000UL) {
47 syncFromNtp(); // günde bir kez eşitle / sync once a day
48 }
49 delay(1000);
50}Встроенный RTC Raspberry Pi Pico
В микросхеме RP2040 на Raspberry Pi Pico есть блок RTC, а RP2350 на Pico 2 выполняет ту же работу с помощью всегда включённого таймера (AON timer). В MicroPython оба используются через один и тот же класс machine.RTC: RTC().datetime() читает или записывает время в виде (год, месяц, день, день недели, часы, минуты, секунды, доли секунды), и time.localtime() тоже берёт время из этих часов. Но батарейки у этих часов нет: когда Pico обесточивается, MicroPython запускает часы с 1 января 2021 года, 00:00.
Здесь есть ловушка для новичков: по умолчанию Thonny при подключении синхронизирует часы Pico с часами компьютера. Поэтому при тестах всё выглядит правильно, но стоит подключить Pico к зарядке от телефона или к батарее, как часы откатываются в 2021 год. Решение — подключить к Pico модуль DS3231 и при запуске выставлять от него внутренний RTC. Коду ниже не нужен никакой файл драйвера: он читает первые семь регистров DS3231 по I2C и переводит их из BCD в десятичные числа. На Pico W время можно получить и из интернета через ntptime.settime(); функция выдаёт UTC, поэтому смещение своего часового пояса нужно прибавить вручную. Если Pico в новинку, начни со статьи Что такое Raspberry Pi Pico?.
1from machine import Pin, I2C, RTC
2import time
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000)
5DS_ADDR = 0x68 # DS3231 ve DS1307 adresi / DS3231 and DS1307 address
6
7def bcd2dec(b):
8 return (b >> 4) * 10 + (b & 0x0F)
9
10def dec2bcd(d):
11 return ((d // 10) << 4) | (d % 10)
12
13def ds_read():
14 b = i2c.readfrom_mem(DS_ADDR, 0x00, 7) # saniyeden yıla 7 kayıt / 7 registers, seconds to year
15 return (2000 + bcd2dec(b[6]), bcd2dec(b[5] & 0x1F), bcd2dec(b[4] & 0x3F),
16 bcd2dec(b[2] & 0x3F), bcd2dec(b[1] & 0x7F), bcd2dec(b[0] & 0x7F))
17
18def ds_write(y, mo, d, h, mi, s):
19 # 24 saat biçiminde yazar; 4. bayt haftanın günü (1-7) / writes 24-hour time; 4th byte is day of week (1-7)
20 i2c.writeto_mem(DS_ADDR, 0x00, bytes([dec2bcd(s), dec2bcd(mi), dec2bcd(h), 1,
21 dec2bcd(d), dec2bcd(mo), dec2bcd(y - 2000)]))
22
23# İlk kurulumda bir kez çalıştır, sonra satırı sil / run once on first setup, then delete the line
24# ds_write(2026, 11, 3, 14, 30, 0)
25
26y, mo, d, h, mi, s = ds_read()
27RTC().datetime((y, mo, d, 0, h, mi, s, 0)) # dahili RTC'yi ayarla / set the internal RTC
28
29while True:
30 t = time.localtime() # artık dahili RTC'den okunur / now read from the internal RTC
31 print("{:02d}.{:02d}.{} {:02d}:{:02d}:{:02d}".format(t[2], t[1], t[0], t[3], t[4], t[5]))
32 time.sleep(1)Идеи проектов с модулем RTC
- Цифровые настольные часы и календарь: выводи время, дату и температуру, измеренную DS3231, на LCD, OLED или светодиодную матрицу.
- Автополив растений: каждое утро проверяй влажность почвы и при необходимости включай насос на заданное время.
- Кормушка для питомца: два-три раза в день открывай сервоприводом заслонку бункера и высыпай порцию корма.
- Регистратор данных с метками времени: записывай показания температуры и влажности вместе с датой и временем на модуль SD-карты, а потом строй графики в Excel.
- Звонок для школы или мастерской: включай зуммер или звонок через реле в начале и в конце каждого урока, а выходные пропускай с помощью dayOfTheWeek().
- Таймер для аквариума и фитолампы: включай свет утром и выключай вечером, плавно меняя яркость через ШИМ для эффекта рассвета и заката.
Частые ошибки и как их исправить
- «RTC not found» (RTC не найден), begin() возвращает false: перепутаны SDA и SCL, нет общей GND или модуль не получает питания. Запусти скетч I2C-сканера и проверь, появляется ли адрес 0x68.
- Бессмысленные значения вроде 2165 года, 165 или 85: данные от микросхемы не приходят, и каждый прочитанный байт равен 0xFF. Проверь подключение; если DS1307 питается от 3,3 V, переведи его на 5 V.
- После каждого перезапуска часы возвращаются к одному и тому же моменту: строка rtc.adjust() всё ещё стоит в setup() без условия; привяжи её к lostPower().
- Часы сбрасываются после отключения питания: батарейка села, вставлена неправильной стороной или её нет. Измерь её напряжение и помни, что схема зарядки могла погубить CR2032.
- Часы уходят на минуты за неделю: виноваты кварц DS1307 или DS1302 и перепады температуры. Перейди на DS3231 или регулярно синхронизируй время по NTP.
- Время отличается ровно на один или несколько часов: неверно задан часовой пояс или летнее время. Записывай в RTC местное время; при использовании NTP выбери правильное правило часового пояса.
- DS3231 показывает температуру выше комнатной: это собственная температура микросхемы, её точность ±3 °C, и на неё влияет нагрев платы. Для температуры окружающей среды используй отдельный датчик.
Итого: DS3231 — правильный выбор почти для любого проекта, где нужны время и дата; DS1307 справится в простых проектах на 5 V, а DS1302 годится для учёбы. На ESP32 используй NTP, когда есть интернет, и DS3231, когда его нет; на Pico самый надёжный путь — при запуске выставлять внутренний RTC от DS3231. В приложении BlueGrays есть пошаговые проекты со схемами подключения и кодом: настройка часов на DS1302 и часы на LCD, часы и календарь на точечной матрице с DS1307, цифровые часы на ESP32 с RTC, время из интернета по NTP и регистратор температуры с метками времени.
Частые вопросы
Работает ли модуль RTC без батарейки?
Пока подключено VCC, часы идут и их можно читать. Но как только питание пропадает, часы останавливаются или сбрасываются, и при следующем запуске их приходится выставлять заново. Весь смысл RTC в том, чтобы сохранять время при отключениях питания, поэтому батарейка нужна почти всегда; если DS1307 используется без неё, его пин VBAT нужно соединить с GND.
Что лучше: DS3231 или DS1307?
Почти в любом случае лучше DS3231. Благодаря встроенному кварцу с термокомпенсацией он ошибается всего примерно на минуту в год, тогда как DS1307 может уходить до минуты в месяц. Кроме того, DS3231 работает от 2,3–5,5 V, поэтому подключается к ESP32 и Pico напрямую, и у него есть два будильника и датчик температуры. С RTClib код для обоих почти одинаковый.
Сколько служит батарейка модуля RTC?
Когда модуль работает только от батарейки, DS3231 потребляет до 3 µA, а DS1307 — около 0,5 µA. По расчёту CR2032 на 220 mAh при таких токах прослужит больше 8 лет. На практике срок хранения элемента и схема зарядки на модуле могут его сократить; в модуле с включённой схемой зарядки CR2032 может выйти из строя гораздо раньше.
Почему модуль RTC постоянно сбрасывает время?
Есть три частые причины: строка rtc.adjust() в setup() при каждом запуске откатывает часы ко времени компиляции, батарейка села или вставлена наоборот, а схема зарядки испортила CR2032. Сначала привяжи строку adjust() к lostPower(), затем измерь напряжение батарейки мультиметром и замени элемент, если оно ниже 2,5 V.
Нужен ли модуль RTC для ESP32?
Если устройство всегда в сети, не нужен: ESP32 за несколько секунд получает точное время по NTP. Для проектов, где интернет может пропадать, где время должно быть известно после отключения питания ещё до загрузки роутера, или которые работают полностью офлайн, самый надёжный вариант — добавить DS3231. Лучше всего использовать оба способа и раз в день синхронизировать DS3231 по NTP.
Можно ли поставить CR2032 в модуль DS3231?
Да, но на модулях со схемой зарядки, таких как ZS-042, сначала нужно разорвать цепь зарядки. Если выпаять резистор 200 Ω (маркировка 201) или соседний диод, CR2032 будет безопасно работать годами. Если переделывать плату не хочется, используй аккумулятор LIR2032.
Что собрать после прочтения
Все проекты
Настройка модуля часов DS1302 RTC
Ты запускаешь маленький модуль часов, который никогда не забывает время, даже когда Arduino выключена. У модуля своя крошечная батарейка, и после установки часов дата и время каждую секунду выводятся

Часы на DS1302 RTC с LCD-дисплеем
Маленькие настольные часы, которые помнят время даже при отключении питания. Модуль часов DS1302 считает время благодаря своей крошечной батарейке; каждую секунду Arduino читает его и выводит время и

Цифровые часы на ESP32 и DS1307 RTC (I2C + LCD)
В этом проекте время и дата из модуля часов реального времени (RTC) DS1307 выводятся на I2C LCD-экран 16x2. DS1307 — RTC с резервной батарейкой, который хранит время даже при выключенной ESP32. Оба модуля делят одну шину I2C (SDA/SCL), и ты узнаёшь, как управлять несколькими устройствами всего по двум сигнальным проводам. Проект даёт практические знания о протоколе I2C, работе модуля RTC и динамическом выводе данных на LCD-экран.

Часы и календарь на матрице (MAX7219, DS1307)
Светящееся табло для стола или стены, которое показывает время и дату бегущей строкой. На светодиодном дисплее 8x32 крупные цифры часов, а две точки между ними мигают каждую секунду; в начале каждой м

Часы, календарь и метеостанция на матрице (MAX7219, DS1307)
Табло с бегущей строкой для стола или стены, которое по очереди показывает время, дату и погоду в комнате. На светодиодном дисплее 8x32 сначала видна температура в градусах Цельсия и Фаренгейта, затем

Регистратор температуры на ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Собери на ESP32 регистратор температуры с отметками времени! Каждую минуту читай температуру и влажность с DHT22, бери реальное время из DS1307 RTC и записывай всё на карту microSD в формате CSV. OLED показывает текущую температуру (крупным шрифтом), влажность в процентах, время и счётчик записей. Файл /temp_log.csv на SD-карте открывается в Excel, Google Sheets или Python pandas — идеально для теплиц, комнат, лабораторий и хранения продуктов.

Точное время из интернета через NTP на ESP32
ESP32 подключается к Wi-Fi и получает точное время с точностью до миллисекунд от серверов NTP (Network Time Protocol). Благодаря функции configTzTime() автоматически применяется часовой пояс Турции (TRT, UTC+3), а в странах с летним временем переходы обрабатываются автоматически по строке POSIX TZ. Время выводится в монитор порта и на необязательный I2C LCD. configTzTime() запускает службу SNTP, которая периодически пересинхронизирует часы.

Цифровые часы на 4-разрядном семисегментном индикаторе
Светящиеся цифровые часы из четырёх разрядов, почти как на кухонной духовке. Модуль часов DS1302 хранит время, а Arduino каждую секунду читает часы и минуты и показывает их на четырёхразрядном индикат
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

