Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

DS3231 RTC with ESP32 DevKit V1 — keep time through power cuts

Wire a DS3231 module to an ESP32 DevKit V1 at 3.3 V on GPIO21/22, set it once from compile time, and read date, time and temperature with RTClib.

Arduino C++Verified — core esp32 3.3.12, RTClib 2.1.4, 3 Nov 2026Compile-only

Community draft — report a mistake

The DS3231 is a temperature-compensated real-time clock that drifts only about a minute a year, and keeps counting on a coin cell when the power goes.

On the ESP32 DevKit V1 it runs at 3.3 V on D21/D22 — no level shifting. The sketch sets the clock from your PC’s time the first time (or after the battery dies), then prints the date, time and the chip’s own temperature reading every second.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicDS3231 real-time clock (RTC) moduleGNDD22D213V332K (not connected)SQW (not connected)SCLSDAVCCGND
Every connection
ESP32 DevKit V1DS3231 real-time clock (RTC) moduleWireNotes
3V3VCCredThe module pulls SDA/SCL up to VCC, so 3V3 keeps them at ESP32 levels. The DS3231 keeps full accuracy at 3.3 V.
GNDGNDblack
D22SCLyellow
D21SDAblue

2.3–5.5 V part, 3.3 V board. The module pulls SDA/SCL up to its own VCC. On a 3.3 V board, power it from 3.3 V — the DS3231 keeps excellent time at 3.3 V.

Board quirks

  • Why an RTC on a Wi-Fi board? NTP needs internet. During a power cut the router is off too, so a timer or logger that must know the time at boot gets it from the DS3231 and its coin cell.
  • The common ZS-042 module has a charging resistor and diode that try to charge the coin cell from VCC. With a non-rechargeable CR2032 that is unsafe; remove the diode (or the 200 Ω resistor next to it), or fit an LIR2032. At 3.3 V the charge current is small, but the fix still matters.
  • The time is set from your PC’s clock when you compile — IST if your PC is on IST. It only happens when the RTC reports lost power, so later uploads don’t overwrite a running clock.
  • 32K and SQW are unused here. SQW can wake the ESP32 from deep sleep as an alarm output — wire it to an RTC-capable pin such as D33 with esp_sleep_enable_ext0_wakeup().
  • The module also carries a 24C32 EEPROM at 0x57. It is not the RTC; the RTC is always at 0x68.

Code

ds3231-esp32.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// DS3231 real-time clock on an ESP32 DevKit V1 — keeps time through power cuts.
// VCC → 3V3, GND → GND, SCL → D22, SDA → D21. 32K and SQW unused.
#include <Wire.h>
#include <RTClib.h>

RTC_DS3231 rtc;
const char *DAYS[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);
  if (!rtc.begin(&Wire)) {
    Serial.println("No DS3231 at 0x68 — check wiring");
    while (true) delay(1000);
  }
  if (rtc.lostPower()) {
    // First run or flat coin cell: set the clock to the time this sketch was compiled
    // (your PC's local time, e.g. IST). Upload right after compiling for best accuracy.
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    Serial.println("RTC had lost power — set from compile time");
  }
  rtc.disable32K();  // the 32 kHz output isn't used; saves a little current
}

void loop() {
  DateTime now = rtc.now();
  Serial.printf("%s %02d-%02d-%04d %02d:%02d:%02d  RTC temp %.2f °C\n", DAYS[now.dayOfTheWeek()],
                now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(),
                rtc.getTemperature());
  delay(1000);
}

Library: RTClib (Adafruit) — compiled with RTClib 2.1.4.

Expected serial output

Serial Monitor · 115200Output
RTC had lost power — set from compile time
Tue 03-11-2026 14:22:07  RTC temp 29.25 °C
Tue 03-11-2026 14:22:08  RTC temp 29.25 °C

Common errors

Time resets to the compile time on every power-up

The coin cell is flat, missing or the wrong way round. Replace the CR2032 (+ side up on most modules).

“No DS3231 at 0x68”

SDA/SCL swapped or no power. The I2C scanner should show 0x68 and 0x57.

Clock is a few seconds behind after setting

The compile-time stamp is taken before the upload finishes. Adjust once with rtc.adjust(DateTime(2026, 11, 3, 14, 22, 0)), upload, then remove the line.

↑↓ to move · Enter to open