Keeping time in all your projects!

Introduction

One of the essential aspects of many Raspberry Pi projects is time management. Whether you want to create an alarm clock, a data logger or any other device requiring precise time synchronization, using an RTC (Real Time Clock) module is the ideal solution.

The RTC module is fitted with a button cell that enables it to continue calculating the time even when the Raspberry Pi is switched off, so that the correct time is maintained when the Pi is restarted.

In this course, we’ll explore the DS1307 RTC module for Raspberry Pi. This module uses the Raspberry’s I2C to transmit these values.

Here’s a diagram of how to connect the DS1307 to the Raspberry Pi:

Programming

One of the essential aspects of many Raspberry Pi projects is time management. Whether you want to create an alarm clock, a data logger or any other device requiring precise time synchronization, using an RTC (Real Time Clock) module is the ideal solution.

Here’s what you get when you type this command. Our RTC module has i2c address 0x068. It appears with I2Cdetect, which means it’s connected to our Raspberry Pi :

If you get an error when typing i2cdetect, it means that i2cdetect is not enabled in the Raspberry pi configuration. In our course on i2c on the Raspberry we explain how to activate it.

Once I2C has been activated and your PSTN module has been detected by the board, we’ll move on to the time-reading program. The first step is to install the library needed to manage the I2C:

sudo apt install -y python-smbus

Next, we’ll create a python file in which to write our program:

sudo nano module_rtc.py

Here’s the program to read the time from the module:

import smbus
import time

# DS1307 I2C address
rtc_address = 0x68

# Initializes I2C bus
bus = smbus.SMBus(1) # Use 0 for Raspberry Pi version 1

def bcd_to_decimal(bcd):
    return ((bcd // 16) * 10 + (bcd % 16))

def read_ds1307():
    # Read data from RTC clock
    second = bcd_to_decimal(bus.read_byte_data(rtc_address, 0x00) & 0x7F) # Hide seconds “halt” bit
    minute = bcd_to_decimal(bus.read_byte_data(rtc_address, 0x01))
    hour = bcd_to_decimal(bus.read_byte_data(rtc_address, 0x02) & 0x3F) # Hide 12/24 hour mode bits

    return hour, minute, second

def print_time(hour, minute, second):
    print(f “Current time : {hour:02d}:{minute:02d}:{second:02d}”)

try:
    hour, minute, second = read_ds1307()
    print_time(hour, minute, second)

except IOError:
    print("Communication error with the RTC module. Make sure it is correctly connected.")

To run the program, use the following command line:

sudo python module_rtc.py

As you can see, the time is not necessarily correct. So we’re going to have to configure it correctly. Here’s the program to modify the time:

import smbus
import time

# DS1307 I2C address
DS1307_ADDR = 0x68

# I2C bus number on Raspberry Pi
I2C_BUS = 1

def bcd_to_decimal(bcd):
    return (bcd // 16) * 10 + (bcd % 16)

def decimal_to_bcd(decimal):
    return ((decimal // 10) << 4) + (decimal % 10)

def read_ds1307():
    bus = smbus.SMBus(I2C_BUS)
    data = bus.read_i2c_block_data(DS1307_ADDR, 0, 7)
    bus.close()
    
    second = bcd_to_decimal(data[0] & 0x7F)
    minute = bcd_to_decimal(data[1])
    hour = bcd_to_decimal(data[2] & 0x3F)
    day = bcd_to_decimal(data[4])
    month = bcd_to_decimal(data[5])
    year = bcd_to_decimal(data[6]) + 2000
    
    return (year, month, day, hour, minute, second)

def set_ds1307(year, month, day, hour, minute, second):
    bus = smbus.SMBus(I2C_BUS)
    
    data = [0, decimal_to_bcd(second), decimal_to_bcd(minute),
            decimal_to_bcd(hour), 0, decimal_to_bcd(day),
            decimal_to_bcd(month), decimal_to_bcd(year - 2000)]
    
    bus.write_i2c_block_data(DS1307_ADDR, 0, data)
    bus.close()

if __name__ == “__main__”:
    # Read current time from DS1307
    current_time = read_ds1307()
    print(“DS1307 current time:”, current_time)

    # Set a new time (replace these values with the desired ones)
    new_time = (2024, 3, 5, 12, 30, 0)
    print(“Set new time for DS1307:”, new_time)
    
    # Apply new time to DS1307
    set_ds1307(*new_time)
    
    # Read and display new time from DS1307
    updated_time = read_ds1307()
    print(“New time for DS1307:”, updated_time)

You need to replace the time in “new time” with your own, so that it’s correct. Then restart the first program to see the correct time displayed.