I2C RTC Clock (DS1307) is a runnable microcontroller simulation example on SensBench — open the wired circuit, inspect the code, and compile real firmware in your browser, no install needed. Last updated Aug 14, 2026.

FREE SIMULATOR EXAMPLE · INTERMEDIATE

I2C RTC Clock (DS1307)

This example reads the time from a virtual DS1307 real-time clock at I2C address 0x68 and prints HH:MM:SS plus the date to the Serial Monitor once a second. Open it and watch the seconds tick — then look at the code, because the DS1307 makes you work for those digits: every value comes back in BCD.

Board Arduino Uno (ATmega328P, 16 MHz, 5 V logic)
Difficulty intermediate
Category communication
Libraries None — just the Arduino core
Runs in Sensbench browser simulator — free, no account
Arduino Uno reading a virtual DS1307 RTC over I2C at address 0x68 in the Sensbench simulator

The exact circuit you get when you open this example — already wired, ready to run.

The sketch

// I2C RTC Reader — DS1307 at address 0x68
// Reads hours:minutes:seconds from the virtual RTC
// and prints to Serial Monitor every second.

#include <Wire.h>

#define DS1307_ADDR 0x68

byte bcdToDec(byte val) {
  return ((val >> 4) * 10) + (val & 0x0F);
}

void setup() {
  Wire.begin();
  Serial.begin(9600);

  Serial.println("===========================");
  Serial.println("  DS1307 RTC Reader (I2C)");
  Serial.println("===========================");
  Serial.println();
}

void loop() {
  // Set register pointer to 0 (seconds)
  Wire.beginTransmission(DS1307_ADDR);
  Wire.write(0x00);
  Wire.endTransmission();

  // Request 7 bytes: sec, min, hr, dow, date, month, year
  Wire.requestFrom(DS1307_ADDR, 7);

  if (Wire.available() >= 7) {
    byte sec   = bcdToDec(Wire.read() & 0x7F);
    byte min   = bcdToDec(Wire.read());
    byte hr    = bcdToDec(Wire.read() & 0x3F);
    byte dow   = bcdToDec(Wire.read());
    byte date  = bcdToDec(Wire.read());
    byte month = bcdToDec(Wire.read());
    byte year  = bcdToDec(Wire.read());

    // Print formatted time
    Serial.print("Time: ");
    if (hr < 10) Serial.print("0");
    Serial.print(hr);
    Serial.print(":");
    if (min < 10) Serial.print("0");
    Serial.print(min);
    Serial.print(":");
    if (sec < 10) Serial.print("0");
    Serial.print(sec);

    Serial.print("  Date: ");
    if (date < 10) Serial.print("0");
    Serial.print(date);
    Serial.print("/");
    if (month < 10) Serial.print("0");
    Serial.print(month);
    Serial.print("/20");
    if (year < 10) Serial.print("0");
    Serial.println(year);
  } else {
    Serial.println("Error: Could not read RTC");
  }

  delay(1000);
}

How it works

The read is a pointer-then-fetch transaction, same as an EEPROM: write register 0x00 to set the DS1307’s internal pointer to the seconds register, then Wire.requestFrom(DS1307_ADDR, 7) pulls seven bytes in order — seconds, minutes, hours, day-of-week, date, month, year. The chip auto-increments its pointer after every byte, so the order is fixed by the datasheet, not by you.

The bcdToDec() function exists because the DS1307 stores everything in binary-coded decimal: the high nibble holds the tens digit, the low nibble the units, and (val >> 4) * 10 + (val & 0x0F) converts it back. The masks matter just as much — & 0x7F on seconds strips bit 7, which is the clock-halt flag, and & 0x3F on hours strips the 12/24-hour mode bits. Print the raw bytes and 23:59 comes out looking like garbage.

Before you build it for real

The famous real-hardware gotcha is the CH (clock halt) bit: a brand-new DS1307 ships with the oscillator stopped, so seconds read as a frozen value until you clear bit 7 of register 0 with a write — the virtual RTC here runs immediately, a real one does not. Second: if the bus fails (no pull-ups, SDA/SCL swapped on A4/A5, dead coin cell), every read returns 0xFF and the BCD decode cheerfully prints 165:165:165 — when you see that number, the chip never answered. The DS1307 itself is 5 V-tolerant, so it pairs with the Uno without a level shifter.

Get the parts

Related examples

FAQ

Why does my real DS1307 print 165:165:165?

That is 0xFF pushed through the BCD decoder (15*10+15 = 165) — the bus read failed and Wire.read() returned all ones. Check pull-ups on SDA/SCL, that you are on A4/A5 and not two random analog pins, and that the module actually has power. It is a wiring error message, not a time.

Does the DS1307 keep time when the Uno is off?

Only if the module has a CR2032 coin cell fitted — keeping time across power loss is the entire point of an RTC. The virtual chip in the simulator always runs. Also note the DS1307 drifts a minute or two a week; for internet-accurate time you want NTP, not a better crystal.