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 Arduino Mega 2560 — daily alarm on the SQW interrupt

Wire a DS3231 to an Arduino Mega 2560 on SDA/SCL (20/21) with SQW on pin 2, and fire a daily 06:30 alarm by interrupt — for a bell or pump timer.

Arduino C++Verified — core avr 1.8.8, RTClib 2.1.4, 3 Nov 2026Compile-only

Community draft — report a mistake

A school bell, a timed irrigation pump or a shop’s sign light needs to switch at a real time of day, even after a power cut. The DS3231 keeps that time on its coin cell and can also wake the Mega with an alarm signal.

The I2C lines go to SDA/SCL (pins 20/21) and the alarm output SQW to pin 2, an interrupt pin. The sketch sets a daily alarm for 06:30 and prints a message when it fires.

Wiring

Arduino Mega 2560Only the pins used are shown · 5 V logicDS3231 real-time clock (RTC) module5VGNDD2SDA · 20SCL · 2132K (not connected)SQWSCLSDAVCCGND
Every connection
Arduino Mega 2560DS3231 real-time clock (RTC) moduleWireNotes
5VVCCred
GNDGNDblack
SDASDAblueSame signal as pin 20.
SCLSCLyellowSame signal as pin 21.
D2SQWgreenOpen-drain alarm output; the internal pull-up is enabled in the sketch.

2.3–5.5 V part, 5 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

  • I2C on the Mega is pins 20/21 (or SDA/SCL by AREF), not A4/A5.
  • SQW is open-drain: it only pulls LOW. INPUT_PULLUP on pin 2 gives it a high level. Pin 2 is one of the Mega’s six external-interrupt pins (2, 3, 18, 19, 20, 21).
  • The alarm keeps SQW LOW until clearAlarm(1) is called — forget it and the next alarm never fires.
  • On ZS-042 modules with a CR2032, disable the coin-cell charging circuit (remove the resistor near the diode) or use an LIR2032.
  • Pumps and bells on 230 V go through a contactor or suitable relay, wired by an electrician.

Code

ds3231-mega.inoArduino C++Open in PlaygroundOpen in Playground
// DS3231 RTC on an Arduino Mega 2560 with a daily alarm on the SQW pin (school bell, pump timer).
// VCC → 5V, GND → GND, SDA → SDA (20), SCL → SCL (21), SQW → D2 (interrupt, open-drain, pulled up).
#include <Wire.h>
#include <RTClib.h>

RTC_DS3231 rtc;
const uint8_t SQW_PIN = 2;
const uint8_t ALARM_HOUR = 6, ALARM_MIN = 30;  // 06:30 every day
volatile bool alarmFlag = false;

void onAlarm() { alarmFlag = true; }

void setup() {
  Serial.begin(115200);
  if (!rtc.begin()) {
    Serial.println(F("DS3231 not found - check SDA/SCL (20/21)"));
    for (;;) {}
  }
  if (rtc.lostPower()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  rtc.disable32K();
  rtc.writeSqwPinMode(DS3231_OFF);  // SQW becomes the alarm interrupt output
  rtc.clearAlarm(1);
  rtc.clearAlarm(2);
  rtc.disableAlarm(2);
  rtc.setAlarm1(DateTime(2000, 1, 1, ALARM_HOUR, ALARM_MIN, 0), DS3231_A1_Hour);  // hh:mm:ss match
  pinMode(SQW_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SQW_PIN), onAlarm, FALLING);
  Serial.print(F("Alarm set for "));
  Serial.print(ALARM_HOUR);
  Serial.print(':');
  Serial.println(ALARM_MIN);
}

void loop() {
  if (alarmFlag) {
    alarmFlag = false;
    rtc.clearAlarm(1);  // releases SQW so the next alarm can fire
    Serial.println(F("*** ALARM - switch the bell / pump here ***"));
  }
  static unsigned long last = 0;
  if (millis() - last >= 10000) {
    last = millis();
    char buf[] = "DD-MM-YYYY hh:mm:ss";
    Serial.println(rtc.now().toString(buf));
  }
}

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

Expected serial output

Serial Monitor · 115200Output
Alarm set for 6:30
03-11-2026 06:29:52
*** ALARM - switch the bell / pump here ***

Common errors

Alarm never fires

SQW not set to alarm mode (writeSqwPinMode(DS3231_OFF)), no pull-up on pin 2, or the previous alarm was not cleared.

DS3231 not found

Module wired to A4/A5 instead of 20/21. Full fix.

↑↓ to move · Enter to open