Working Principle
The DS3231 from Maxim Integrated is a high-precision I²C real-time clock (RTC) with an integrated temperature-compensated crystal oscillator (TCXO). Unlike the common DS1307 (which uses an external 32.768 kHz crystal and drifts up to ±2 minutes/month), the DS3231 integrates the crystal and actively compensates for temperature variation, achieving ±2 ppm accuracy (approximately ±1 minute/year).
The DS3231 tracks seconds, minutes, hours, day of week, date, month, and year (with leap year compensation through 2100). It has two programmable alarms, a 32 kHz square-wave output, and a temperature sensor (used internally for TCXO compensation but also readable by the MCU).
Electrical Characteristics
| Parameter | DS3231 | DS1307 (comparison) |
|---|---|---|
| Accuracy | ±2 ppm (0–40 °C) | ±20 ppm typical |
| Annual Drift | ~±1 min/year | ~±10 min/year |
| Supply Voltage | 2.3–5.5 V | 4.5–5.5 V |
| Battery Backup | CR2032 coin cell (years of backup) | CR2032 coin cell |
| Interface | I²C (address 0x68) | I²C (address 0x68) |
| Alarms | 2 programmable alarms | 1 square wave / no alarm |
| Temperature Sensor | Integrated (±3 °C accuracy) | None |
| Current (VCC) | ~200 µA active | ~300 µA active |
| Current (battery) | ~3 µA timekeeping | ~500 nA timekeeping |
Interfacing with an MCU
Connect VCC, GND, SDA, SCL, and optionally SQW/INT to an MCU interrupt pin for alarm wake-up. Most DS3231 modules (ZS-042, Chronodot) include pull-up resistors and a CR2032 battery holder. The I²C address is fixed at 0x68.
Calibration
- Initial time set: Set the time once from a reliable source (NTP, GPS, or compile-time); the DS3231 then maintains it through power cycles
- Aging offset register: Fine-tune the oscillator frequency via the aging offset register (0x10) in increments of ~0.12 ppm for ultra-precise applications
- Temperature readout: Use the built-in temperature register (0x11-0x12) for coarse temperature measurement; updates every 64 seconds
Code Example
/*
* DS3231 Precision RTC — Arduino
* Library: RTClib by Adafruit (install via Library Manager)
* Wiring: VCC → 3.3/5V, GND, SDA → A4, SCL → A5
*/
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.println("DS3231 not found!");
while (1);
}
/* Set time if RTC lost power (only runs once) */
if (rtc.lostPower()) {
Serial.println("Setting time to compile time");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
/* Read internal temperature */
float temp = rtc.getTemperature();
Serial.print("RTC Temperature: ");
Serial.print(temp);
Serial.println(" C");
}
void loop() {
DateTime now = rtc.now();
Serial.print(now.year()); Serial.print('/');
Serial.print(now.month()); Serial.print('/');
Serial.print(now.day()); Serial.print(' ');
Serial.print(now.hour()); Serial.print(':');
Serial.print(now.minute()); Serial.print(':');
Serial.println(now.second());
delay(1000);
}
Real-World Applications
Data Logging, IoT Timestamping & Scheduled Events
DS3231 RTCs are used in data loggers (SD card with timestamps), IoT sensor nodes (time-stamped MQTT messages), scheduled irrigation controllers, alarm clocks, attendance systems, GPS-denied timekeeping, embedded systems requiring precise timing, and scientific instruments. The alarm function enables low-power wake-up for battery-operated devices.
Limitations
- Not a standalone clock: Needs an MCU to read and display the time; no built-in display.
- Fixed I²C address: Address 0x68 is shared with some accelerometers (MPU6050); may conflict on the same bus.
- No time zone: Stores UTC or local time (your choice); time zone handling must be in firmware.
- Battery dependent: Eventually the CR2032 dies (3–8 years); without backup, time is lost until re-set.