Code Along - Chapter 18

Real-Time Clock (DS1307)

Optional practice: read the time from a DS1307, print it as HH:MM:SS and DD/MM/YYYY with snprintf, check the clock is running, and switch an alarm on at a set time.

Estimated time 40-60 min, optionalExercises passed 0 / 5

Optional practice: a real-time clock on the virtual Uno

This chapter is optional. Do it after Lesson 26 if you have time. Nothing in class depends on it. It uses snprintf and %02d from the Text & Time Formatting chapter.

The virtual board has a DS1307 clock module on the I2C pins. Its display shows the time the chip holds:

  • when you press Run, the clock starts from your computer's time and keeps going
  • when you press Test, it starts from a fixed time instead (the exercise says which), so everyone's expected output is the same
  • tick Battery removed and the chip stops and forgets the time: rtc.isrunning() becomes false and rtc.now() reads 01/01/2000 00:00:00

Every sketch here keeps the lesson's set-the-clock line, commented out: // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); - uncomment it on a real Uno to set the clock once. The simulator's clock already has the right time, so if you do uncomment it here it is ignored, with a note under the editor.

Get the time with DateTime now = rtc.now();, then read its parts with now.hour(), now.minute(), now.second(), now.day(), now.month() and now.year().

Worked example

The lesson's sketch

Press Run: the Serial Monitor shows your computer's date and time, one line a second. The expected output below was made with the test clock, so its numbers are different. Then tick Battery removed while it runs.

#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 rtc;
char line[24];

void setup() {
  Serial.begin(9600);
  if (!rtc.begin()) {
    Serial.println("RTC not found");
    while (true) { delay(100); }
  }

  // Sets the time ONLY if the clock stopped or lost battery power
  if (!rtc.isrunning()) {
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
}

void loop() {
  DateTime now = rtc.now();
  snprintf(line, sizeof(line), "%02d/%02d/%04d %02d:%02d:%02d",
           now.day(), now.month(), now.year(),
           now.hour(), now.minute(), now.second());
  Serial.println(line);
  delay(1000);
}

Turn on JavaScript to edit, run and test this code in the browser.

Expected output
14/03/2026 09:59:58
14/03/2026 09:59:59
14/03/2026 10:00:00
14/03/2026 10:00:01
  • DateTime now = rtc.now(); copies the whole time out of the chip at once, so the parts always belong together.
  • With the battery removed the clock reads 01/01/2000 00:00:00 and stands still - that is what isrunning() is there to catch.
Exercise 18.1

Hour, minute and second

Not started

now already holds the time. Print the hour, a colon, the minute, a colon and the second, then end the line - once a second.

The test clock starts at 09:59:58. Look closely at the third line of the output: you will fix it in the next exercise.

Sample output
9:59:58
9:59:59
10:0:0
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 rtc;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  if (!rtc.isrunning()) {
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
}

void loop() {
  DateTime now = rtc.now();
  // Print hour:minute:second on one line

  delay(1000);
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 18.2

HH:MM:SS with leading zeros

Not started

10:0:0 is not how a clock looks. Build the text with snprintf and %02d, which pads each number to two digits with a leading zero, so the output becomes 09:59:58, 09:59:59, 10:00:00.

text is already declared and printed - fill it in with one snprintf line.

Sample output
09:59:58
09:59:59
10:00:00
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 rtc;
char text[9];   // "HH:MM:SS" plus the end marker

void setup() {
  Serial.begin(9600);
  rtc.begin();
  if (!rtc.isrunning()) {
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
}

void loop() {
  DateTime now = rtc.now();
  // snprintf the hour, minute and second into text, two digits each

  Serial.println(text);
  delay(1000);
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 18.3

Date and time on one line

Not started

Add the date in front of the time, like the lesson's sketch:

31/12/2026 23:59:58

Day and month get %02d; the year gets %04d. This test starts the clock two seconds before New Year, so you can watch every part roll over at once.

Sample output
31/12/2026 23:59:58
31/12/2026 23:59:59
01/01/2027 00:00:00
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 rtc;
char line[24];

void setup() {
  Serial.begin(9600);
  rtc.begin();
  if (!rtc.isrunning()) {
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
}

void loop() {
  DateTime now = rtc.now();
  // Add the day, month and year in front: DD/MM/YYYY HH:MM:SS
  snprintf(line, sizeof(line), "%02d:%02d:%02d",
           now.hour(), now.minute(), now.second());
  Serial.println(line);
  delay(1000);
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 18.4

Is the clock running?

Not started

A DS1307 that lost its battery stops, and reads 01/01/2000 00:00:00 until someone sets it. In setup(), print one line about the clock before the times start:

  • Clock stopped - set the time when rtc.isrunning() is false
  • Clock OK when it is running

Try it: Run, then tick Battery removed and press ↻ Restart. The test does the same.

Sample output
Clock OK
09:59:58
09:59:59
#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 rtc;
char text[9];

void setup() {
  Serial.begin(9600);
  rtc.begin();
  if (!rtc.isrunning()) {
    // Print "Clock stopped - set the time" here
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
  // ...and print "Clock OK" when it is running
}

void loop() {
  DateTime now = rtc.now();
  snprintf(text, sizeof(text), "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  Serial.println(text);
  delay(1000);
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 18.5

An alarm at 07:00

DeeperNot started

Switch the alarm LED on D8 on for the whole minute 07:00, and off at every other time. Both the hour and the minute must match - 08:00 is not 07:00.

The test starts the clock at 06:59:57. To watch it with Run, change ALARM_HOUR and ALARM_MINUTE to the next minute on your computer's clock.

#include <Wire.h>
#include <RTClib.h>

const int ALARM_PIN = 8;
const int ALARM_HOUR = 7;
const int ALARM_MINUTE = 0;

RTC_DS1307 rtc;

void setup() {
  pinMode(ALARM_PIN, OUTPUT);
  rtc.begin();
  if (!rtc.isrunning()) {
    // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   // uncomment on a real Uno to set the clock once
  }
}

void loop() {
  DateTime now = rtc.now();
  // Alarm ON during the alarm minute, OFF the rest of the time

}

Turn on JavaScript to edit, run and test this code in the browser.

Try it on a real Uno

Wire the module as in Lesson 26: SDA to A4, SCL to A5, and a backup cell of the right type. Upload Is the clock running? with the rtc.adjust line uncommented, so a stopped clock gets set from your PC. Then unplug the Uno for a minute, plug it back in and check the time carried on.

The alarm is the start of the clock and alarm capstone (Lesson 28). Swap the LED for the buzzer and add a button to silence it.