Introduction
Ever wanted to add a real-time clock to your Arduino project but didn’t have the hardware handy? With Velxio, you can simulate an I2C RTC (DS1307) right in your browser. In this tutorial, we’ll build a simple I2C reader that fetches the current time and date from a virtual DS1307 and prints it to the Serial Monitor. No external libraries needed—just the built-in Wire library.

Circuit Walkthrough
This example is remarkably simple because the DS1307 is already integrated into the virtual Arduino Uno board. There are no external components or wires to add. The I2C bus (SDA on A4, SCL on A5) is internally connected to the DS1307 at address 0x68. The only component is the Arduino Uno itself.

To start, open the Velxio editor and select an Arduino Uno from the component picker. The DS1307 is built into the simulation environment, so you don’t need to add it separately. The circuit is ready to go.
Code Walkthrough
Let’s break down the code step by step.
Include and Define
#include <Wire.h>
#define DS1307_ADDR 0x68
We include the Wire library for I2C communication and define the DS1307’s I2C address as 0x68.
BCD to Decimal Conversion
byte bcdToDec(byte val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
The DS1307 stores time values in Binary-Coded Decimal (BCD) format. This helper converts a BCD byte to a regular decimal number.
Setup
void setup() {
Wire.begin();
Serial.begin(9600);
Serial.println("===========================");
Serial.println(" DS1307 RTC Reader (I2C)");
Serial.println("===========================");
Serial.println();
}
We initialize the I2C bus and Serial communication at 9600 baud. Then we print a header.
Loop
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);
}
In the loop, we first set the DS1307’s register pointer to 0 (seconds register) by sending a single byte 0x00. Then we request 7 bytes from the RTC. The DS1307 returns seconds, minutes, hours, day-of-week, date, month, and year in BCD. We mask the top bit of seconds (bit 7 is the clock halt flag) and the top two bits of hours (bits 6-7 are mode/AM-PM). After conversion, we print the time and date with leading zeros. If fewer than 7 bytes are available, we print an error. Finally, we wait 1 second.
Key Concepts
- I2C Communication: The Wire library handles the I2C protocol.
beginTransmission()starts a write,write()queues data,endTransmission()sends it.requestFrom()reads bytes from a slave. - BCD Format: The DS1307 stores time in BCD, where each nibble represents a decimal digit. The
bcdToDec()function converts it. - Register Addressing: The DS1307’s internal registers are accessed by first writing the register address, then reading or writing data.
- Masking Bits: The seconds register’s top bit (CH) indicates clock halt; we mask it with
& 0x7F. The hours register’s top bits indicate 12/24-hour mode; we mask with& 0x3F.
Common Pitfalls and Debugging Tips
- I2C Address Wrong: Ensure the address is 0x68 (7-bit). If you use an 8-bit address, shift left by 1.
- Missing Pull-up Resistors: In real hardware, I2C lines need pull-ups. In Velxio, they are simulated internally.
- Serial Monitor Not Showing: Make sure baud rate matches (9600). Click the Serial Monitor icon in the editor toolbar.

- Compile Errors: Check that you have included
Wire.h. The code uses no external libraries. - RTC Not Responding: If you see “Error: Could not read RTC”, the I2C communication may have failed. Verify the address and wiring.
Suggested Extensions
- Set the Time: Add code to set the DS1307’s time via Serial input.
- Display on LCD: Use an I2C LCD to show the time.
- Alarm Function: Implement an alarm using the DS1307’s alarm registers.
- Data Logging: Log timestamps to EEPROM or an SD card.
Try It Yourself
Ready to see it in action? Open the live example on Velxio and hit the Run button. You’ll see the time updating every second in the Serial Monitor.
Launch the I2C RTC Reader on Velxio

Happy simulating!