Board and part

ESP32 DS3231 RTC Simulator: Wiring, Code and a Live Circuit

This is a DS3231 real-time clock wired to an ESP32 DevKit over I2C, read live with Adafruit's RTClib: the date and time every second, and the chip's own temperature.

  • 3.3 V logic
  • Library: RTClib.h
  • I2C address 0x68
  • SDA 21, SCL 22
ESP32 · DS3231 RTClive0.000 s 0.00x
Click to open it in the editor
The circuit itself, running on the simulator with the sketch below. Press what can be pressed; click anything else to open it in the editor.
Connections

Wiring the DS3231 RTC to the ESP32

Four wires: 3V3, GND, SDA to GPIO 21 (D21) and SCL to GPIO 22 (D22). The sketch sets the clock to a fixed time, so the first line is always the same.

Every connection in the circuit above, with the board’s own pin names.

DS3231 RTC pinESP32 pinWhy
VCC3V3Most DS3231 modules run from 3.3 to 5.5 V.
GNDGNDCommon ground.
SCLGPIO 22 (D22)I2C clock. The module has its own pull-up resistors.
SDAGPIO 21 (D21)I2C data.

Power

On an ESP32 DevKit, Wire.begin() with no arguments puts SDA on GPIO 21 and SCL on GPIO 22, labeled D21 and D22. The module carries its own I2C pull-ups, and the chip answers at the fixed address 0x68. The 32K and SQW pins are outputs this page leaves unwired.

Pins to leave alone on the ESP32

GPIO 34, 35, 36 (VP) and 39 (VN) are input only: they cannot drive a pin or take an internal pull-up. GPIO 0, 2, 5, 12 and 15 are strapping pins, read at power-on, and GPIO 6 to 11 are the flash chip.

On a real bench

The thirty-pin DevKit straddles a breadboard with one row of holes free on each side, which is where the DS3231 RTC’s jumpers go. Many ESP32 boards are wider and cover both rows; then use two breadboards side by side. Hold BOOT while uploading if the IDE cannot connect.

The sketch

The code, and what it does.

The sketch the circuit above runs. Open it in the editor, change a line and press Run: it compiles in your browser.

DS3231 clock on ESP32 I2C
#include <Wire.h>
#include <RTClib.h>

RTC_DS3231 rtc;   // on I2C: SDA GPIO 21 (D21), SCL GPIO 22 (D22), address 0x68

void setup() {
  Serial.begin(115200);
  if (!rtc.begin()) {
    Serial.println("No DS3231 found");
    for (;;) {}
  }
  if (rtc.lostPower()) {
    Serial.println("Clock lost power, setting it");
    rtc.adjust(DateTime(2026, 11, 7, 9, 30, 0));
  }
}

void loop() {
  DateTime now = rtc.now();
  char text[24];
  snprintf(text, sizeof(text), "%04d-%02d-%02d %02d:%02d:%02d",
           now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
  Serial.print(text);
  Serial.print("  Chip: ");
  Serial.print(rtc.getTemperature(), 2);
  Serial.println(" C");
  delay(1000);
}

rtc.begin() looks for the chip at 0x68. lostPower() reads the oscillator-stop flag, which a DS3231 sets whenever it has lost its time. On a real module with a coin cell it is clear after the first set, so a sketch sets the clock once. The simulated chip has no coin cell and starts every run with the flag set, so this sketch sets it each run.

rtc.now() reads all seven time registers in one transfer and converts them from BCD, so the sketch never sees a BCD byte. getTemperature() is the thermometer inside the chip, which it uses to correct its crystal; it measures the chip, not the room.

Serial.begin(115200) opens the serial monitor. Serial is UART0 on the USB bridge. ESP32 sketches usually run it at 115200 baud, which this one does.

Pitfalls

Common mistakes with the DS3231 RTC on the ESP32

Setting the time on every boot

A sketch that calls rtc.adjust() unconditionally resets the clock each time the board restarts. Guard it with lostPower(), as above, so a real module with a battery keeps its time.

Another chip at 0x68

The MPU6050 also answers at 0x68. Two such parts on one bus clash; the DS3231 has no address pin to move it.

Using compile time on an old build

DateTime(F(__DATE__), F(__TIME__)) sets the time the sketch was compiled, not now. If you upload a day later, the clock is a day behind.

FAQ

Questions and answers

Can I simulate a DS3231 with an ESP32 DevKit?

Yes. The circuit at the top of this page is an ESP32 DevKit with a DS3231 real-time clock, running in your browser on a simulated ESP32 (Xtensa LX6). The simulated chip counts real seconds and answers the library over I2C, registers and all. It has no coin cell, so it forgets the time between runs. Press Run it in the editor to change the wiring or the code; it is free and needs no account.

Where does the DS3231 connect on the ESP32?

On an ESP32 DevKit, Wire.begin() with no arguments puts SDA on GPIO 21 and SCL on GPIO 22, labeled D21 and D22.

How accurate is a DS3231?

It corrects its crystal for temperature and keeps time to within about a minute a year, where a DS1307 can drift that much in a month.

Does it keep time when the board is off?

A real module does, from a coin cell on the back. The simulated one has no battery, so it starts each run at the time the sketch sets.

Build your own DS3231 RTC project

Open this circuit in the editor, change the wiring or the code, and keep your version in a free account.