На Aliexpress представлено большое количество разнообразных внешних модулей RTC и комбинированных модулей RTC + SD карта или EEPROM. Рассмотрю наиболее интересные для использования с компактными девелоперскими платами MH ET Live Minikit (ESP32) (другой вариант поиска) или Wemos D1 mini (ESP8266).
Tiny RTC с EEPROM на 32 кБит

- Tiny RTC с EEPROM на 32 кБит:
- RTC на чипе DS1307. Напряжение питания чипа 5 V.
- Память EEPROM 32 кБит (чип AT24C32).
- Выводы не совпадают с платой Wemos D1 mini, хотя по габаритам и совместима, поэтому использовать её неудобно.
- Модуль RTC использует интерфейс I2C, однако выставить на плате адрес шины нельзя.
- Размеры модуля, мм: 28×25.
- Батарея для питания: CR2032
- Цена с доставкой в Россию: 0,34 USD
- Модуль доступен у большого количества поставщиков на Aliexpress.
Основной плюс платы — низкая цена и наличие распаянного на плате EEPROM чипа. В некоторых случаях значительная емкость SD карты не нужна и переплачивать из-за этого лишние 300 руб не хочется.
К сожалению нормального варианта этого модуля, который бы «садился» на разъем девеоперских плат найти не удалось.
RTC + SD card reader module
![]() | ![]() |
- RTC + SD card reader module для платы Wemos D1 mini (ESP8266) или MH ET Live Minikit (ESP32):
- RTC на чипе DS1307. Напряжение питания чипа 5 V.
- Слот Micro SD карты для логирования.
- Модуль RTC использует интерфейс I2C, однако выставить на плате адрес шины нельзя.
- Размеры модуля, мм: 28×25.
- Батарея для питания: CR1220
- Цена с доставкой в Россию: 1,55 USD
- Судя по всему разработка компании RobotDyn. Там-же есть вариант модуля без SD карты.
- В разделе документации доступны схемы.
- Модуль доступен у большого количества поставщиков на Aliexpress.
Функционально второй модуль удобнее из-за наличия слота SD карты и возможности каскадирования («сэндвич») при использовании компактных девелоперских плат MH ET Live Minikit (ESP32) или Wemos D1 mini (ESP8266). Рассмотрю работу с этим модулем подробнее.
Схема для подключения не требуется, поскольку при стекировании девелоперских плат с Wemo D1 mini datalogger нужные пины уже состыкованы. Для подключения RTC пины:
| Wemos D1 mini (ESP8266) | Описание | ESP32 |
| D1 (GPIO5) | SCL | GPIO 22 (SCL) |
| D2 (GPIO4) | SDA | GPIO 21 (SDA) |
| 5V | 5V | |
| 3.3V | 3.3V | |
| GND | GND |
Ещё раз обращаю внимание, что питание чипа RTC — 5 V. Если его запитать от 3,3 V, то он работает некорректно. Не выдает ошибки при соединении, но при запросе даты — выдает некорректную.
SD карта запитывается от пина 3.3V. При подключении к ESP32 не нужно забывать подключать это напряжение.
Data logger RTC shield (Wemos D1 mini) НЕЛЬЗЯ использоваить при питании от аккумулятора 3.7 V. 🙁
Для подключения SD карты к ESP8266/ESP32:
| Wemos D1 mini (ESP8266) | Описание | ESP32 VSPI | ESP32 HSPI |
| D5 (GPIO 14) | CLK/SCK | GPIO18 | GPIO14 |
| D6 (GPIO 12) | DO/MISO | GPIO19 | GPIO12 |
| D7 (GPIO13) | DI/MOSI | GPIO23 | GPIO13 |
| D8 (GPIO 15) | CS/SS | GPIO5 | GPIO15 |
Выводы SD карты подключаются к выводам Wemos D1 без каких-либо дополнительных схем защиты от статического электричества. Например, диодной сборкой SMF05C.
Программа
Для работы с модулем Wemos D1 mini RTC + SD card datalogger использовал следующий код из библиотеки https://github.com/Makuna/Rtc.
Библиотека Adafruit не работает.
// CONNECTIONS:
// DS1307 SDA --> SDA
// DS1307 SCL --> SCL
// DS1307 VCC --> 5v
// DS1307 GND --> GND
/* for software wire use below
#include <SoftwareWire.h> // must be included here so that Arduino library object file references work
#include <RtcDS1307.h>
SoftwareWire myWire(SDA, SCL);
RtcDS1307<SoftwareWire> Rtc(myWire);
for software wire use above */
/* for normal hardware wire use below */
#include <Wire.h> // must be included here so that Arduino library object file references work
#include <RtcDS1307.h>
RtcDS1307<TwoWire> Rtc(Wire);
/* for normal hardware wire use above */
void setup ()
{
Serial.begin(9600);
Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.println(__TIME__);
//--------RTC SETUP ------------
// if you are using ESP-01 then uncomment the line below to reset the pins to
// the available pins for SDA, SCL
// Wire.begin(0, 2); // due to limited pins, use pin 0 and 2 for SDA, SCL
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
printDateTime(compiled);
Serial.println();
if (!Rtc.IsDateTimeValid())
{
if (Rtc.LastError() != 0)
{
// we have a communications error
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
// what the number means
Serial.print("RTC communications error = ");
Serial.println(Rtc.LastError());
}
else
{
// Common Cuases:
// 1) first time you ran and the device wasn't running yet
// 2) the battery on the device is low or even missing
Serial.println("RTC lost confidence in the DateTime!");
// following line sets the RTC to the date & time this sketch was compiled
// it will also reset the valid flag internally unless the Rtc device is
// having an issue
Rtc.SetDateTime(compiled);
}
}
if (!Rtc.GetIsRunning())
{
Serial.println("RTC was not actively running, starting now");
Rtc.SetIsRunning(true);
}
RtcDateTime now = Rtc.GetDateTime();
if (now < compiled)
{
Serial.println("RTC is older than compile time! (Updating DateTime)");
Rtc.SetDateTime(compiled);
}
else if (now > compiled)
{
Serial.println("RTC is newer than compile time. (this is expected)");
}
else if (now == compiled)
{
Serial.println("RTC is the same as compile time! (not expected but all is fine)");
}
// never assume the Rtc was last configured by you, so
// just clear them to your needed state
Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
}
void loop ()
{
if (!Rtc.IsDateTimeValid())
{
if (Rtc.LastError() != 0)
{
// we have a communications error
// see https://www.arduino.cc/en/Reference/WireEndTransmission for
// what the number means
Serial.print("RTC communications error = ");
Serial.println(Rtc.LastError());
}
else
{
// Common Cuases:
// 1) the battery on the device is low or even missing and the power line was disconnected
Serial.println("RTC lost confidence in the DateTime!");
}
}
RtcDateTime now = Rtc.GetDateTime();
printDateTime(now);
Serial.println();
delay(10000); // ten seconds
}
#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(const RtcDateTime& dt)
{
char datestring[20];
snprintf_P(datestring,
countof(datestring),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print(datestring);
}Код не требует какой-либо настройки и начинает работать сразу.
Работа с Wemos D1 mini Datalogger через I2C (библиотека Wire.h) без использования дополнительных библиотек.
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
Serial.begin(9600);
second = 45;
minute = 3;
hour = 7;
dayOfWeek = 5;
dayOfMonth = 17;
month = 4;
year = 8;
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
Serial.print(hour, DEC);
Serial.print(":");
Serial.print(minute, DEC);
Serial.print(":");
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(" Day_of_week:");
Serial.println(dayOfWeek, DEC);
delay(1000);
}Micro SD карта на Wemos D1 mini datalogger
Схема для подключения модуля по-прежнему не нужна. 🙂 Все соединения работают нормельно после сборки «сэндвича» из
Wemos D1 mini (ESP8266) и Wemos D1 mini datalogger.
Проверил работу штатной библиотеки ESP8266 для работы с Micro SD картой. Тестовый пример без проблем откомпилировался и отработал. Так что модуль работает без проблем.
ВАЖНЫЙ МОМЕНТ РАБОТЫ SD карты с ESP8266!!!
Я использовал Samsung 32Gb EVO Plus отформатированную в FAT32 и с ней DataLogger не инициализировал карту. После того как отформатировал в FAT16 ESP8266 стал читать SD карту.
При этом на дешевой Micro SD «SP Elite» 16 Gb отформатированной в FAT32 проблем с чтением не возникло, ESP8266 без проблем проинициализировал карту.
В коде ниже нужно обратить внимание на CS PIN инициализации SD.init(15). На Wemos Mini D1 пин CS заведен на GPIO15, а не GPIO4.
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
created Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// nothing happens after setup
}Подключение SD карты к ESP32 описано здесь. В цело все то-же самое. Проблем возникнуть не должно.
Полезные ссылки
- Wemos D1 mini datalogger (DS1307 + SD card) schematic and description.
- Размеры модуля Wemos D1 mini datalogger (DS1307 + SD card).
- Библиотека для работы с DS1307.
- Видеообзор модуля Wemos D1 mini datalogger (DS1307 + SD card) на русском.
- Подключение SD карты к ESP32 от разработчиков Espressif.
- Подключение SD карты к ESP32.
- ESP32 Pinout Reference: Which GPIO pins should you use?

