Setting up hardware RTC in Raspbian

My Raspberries are expanded with DS3231 I2C realtime clock. It’s a very simple solution, as only required external component is a backup battery (crystal is integrated into the chip!). And it’s also claimed to be very accurate :)

By default, Raspbian installation uses “fake hwclock” to read previously stored date/time from file just before clock is synced by NTP client. We’re going to switch to “full” hwclock, first ensuring that our RTC is seen by kernel.

First, modify /etc/init.d/hwclock.sh to initialize clock’s i2c device.
Create RTC initialization function:

init_rtc_device()
{
  [ -e /dev/rtc0 ] && return 0;

  # load i2c and RTC kernel modules
  modprobe i2c-dev
  modprobe rtc-ds1307

  # iterate over every i2c bus as we're supporting Raspberry Pi rev. 1 and 2
  # (different I2C busses on GPIO header!)
  for bus in $(ls -d /sys/bus/i2c/devices/i2c-*);
  do
    echo ds1307 0x68 >> $bus/new_device;
    if [ -e /dev/rtc0 ];
    then
      log_action_msg "RTC found on bus `cat $bus/name`";
      break; # RTC found, bail out of the loop
    else
      echo 0x68 >> $bus/delete_device
    fi
  done
}

Call it from the “start” section.
We also have to comment out/remove udev check as our RTC won’t be handled by it.

...
init_rtc_device

# Raspberry Pi doesn't have udev detectable RTC
# if [ -d /run/udev ] || [ -d /dev/.udev ]; then
# return 0
# fi
...

Next, reboot and check if /dev/rtc0 is present and/or “hwclock -r” successfully gets time from RTC.
If everything seems working OK, our RasPi will get proper time even without network connectivity or with ntp client disabled.

We can now disable fake-hwclock from running:

# update-rc.d fake-hwclock remove

13 thoughts on “Setting up hardware RTC in Raspbian

  1. Anthony

    I can’t thank you enough for this! Everyone tells me, “no, put it in rc.local..”
    Each reboot we go back to the when Hendrix was alive and sometimes the RTC doesnt kick in until after data logging daemon has started. But now its real time all the way. I even reread syslog four times to make sure i wasn’t dreaming. Thank you!

    I’m using rdate to synch clock with an NTP box every fortnight even though the ds3231 is more accurate than most RTCs. I was wondering what you rthoughts are?

    Reply
  2. andres

    Hi I’m so newbie with this. I’m trying but I don’t know what is the “start” section. Please I need help. Whenever, thanks for this post.

    Reply
    1. elevendroids Post author

      Hi,
      In /etc/init.d/hwclock.sh file search for hwclocksh() procedure:

      ...
      hwclocksh()
      {
      ...

      Few lines further, there’s a “case” clause with “start” block:

      case "$1" in
      start)
      # If the admin deleted the hwclock config, create a blank
      # template with the defaults.
      if [ -w /etc ] && [ ! -f /etc/adjtime ] && [ ! -e /etc/adjtime ]; then
      printf "0.0 0 0.0n0nUTC" > /etc/adjtime
      fi
      ...

      Insert “init_rtc_device” call right after above fragment.

      Reply
      1. andres

        Thanks for your response. Unfortunately it doesn’t works. I tried this with the raspbian last release and one ds1307 but is useless . I know ds1307 have 0x68 address and I did everything about configuration and the system recognizes all. I save the commands in /etc/rc.local and I review the exec permissions (chmod)., but every time than I do a system reboot, the time is wrong on system but is right on rtc(ds1307). Then I must to write “sudo hwclock -s” to update the system date. It’s so frustrating. Anyway, thanks for your generosity triyng help to me.

        Reply
        1. elevendroids Post author

          You have to put this (see post) code into /etc/init.d/hwclock.sh not /etc/rc.local as RTC should be enabled as early as possible to avoid problems with services starting with invalid system time. rc.local is executed at the end of system initialization (it’s too late)…

          Reply
          1. andres

            I’m sorry. I made a mistake saying etc/rc.local. It was /etc/init.d/hwclock.sh where I did it. To the end doesn’t work. Thanks again.

          2. elevendroids Post author

            Could you send me your hwclock.sh file? If you can access your RTC manually, then it has to work this way too.
            Use my email from Contact tab :)

  3. Hormiguero

    I was having the same problem as Andres. The hwclock.sh script apparently needs to be activated in the /etc/rcS.d/ directory by renaming the symlink from K06hwclock.sh to S06hwclock.sh. The update-rc.d should be run. Now the system clock is set from the rtc on boot.

    My problem is that when I change the system date/time from the command line, the hardware clock isn’t changed on shutdown to preserve the new setting… How do I do that?? I have fiddled with the hwclock.sh in the other runlevels, but it still doesn’t change the hwclock on shutdown…

    Reply
  4. regregex

    Excellent page, thank you! However I found the I2C kernel module is blacklisted by default, which can be remedied by commenting out the relevant line in /etc/modprobe.d/raspi-blacklist.conf . This was taken from a page on enabling full I2C support on the Pi (see the link on my name; no affiliation) and after following those instructions as well, I have a working real-time clock.

    Also the init_rtc_device() function can be improved by adding the line:
    ln -s rtc0 /dev/rtc
    just above log_action_message. This lets hwclock find the RTC with the default settings.

    Reply
    1. regregex

      One more thing – as hormiguero suggested, I had to do
      sudo update-rc.d hwclock.sh enable
      sudo update-rc.d fake-hwclock disable

      Reply
  5. Mark

    Thank you for this great tutorial, i did things a little different but it works :-)
    i put my modules (i2c-dev and i2c:mcp7941x) in /etc/modules
    and just added the line:
    echo mcp7941x 0x6f > /sys/class/i2c-adapter/i2c-1/new_device
    at the top from hwclock.sh in /etc/init.d
    Edited the symlinks and used update-rc.d to enable everything.

    When i reboot i see that the time is set from the RTC, but when i change the
    time at the command line and do another reboot, the time isn’t saved to the
    RTC……
    When i do manually ./hwclock.sh stop the time is saved to the RTC, any ideas
    why this doesn’t happen when i reboot?

    Grtzz Mark

    Reply
  6. Pingback: Real Time Clock (Software – I2C) | MyRaspberryAndMe

  7. John L. Males

    Hello,

    I too have a DS3231 based RTC for my RPi which I am trying to configure to set the system time from the RTC at boot. The distribution I use is systemd based and so far despite all the searchng, reading and attempts what I have read and varied in hopes of being able to cause the system time to be set from the DS3231 RTC have not ben successful.

    The RPi distribution I am using had no fakeclock package installed from the start. It was easy to enable the DS3231 RTC such that every time the RPi boots it has access to the RTC. This means if I use “hwclock -s” at the command line the system time that is 1970 based is set to the time of the RTC. So the only challenge is how to have systemd execute the “hwclock -s” command during boot.

    I have read at that systemd has some method to set the RTC at boot that bypasses drift calculations, such as hwclock calculates, which I really do nto want to bypass. The RPi will be run without being connected to the internet almost all the time. I intend to connect the RPi a few times every few weeks on purpose to allow RTC drift calculations to be made by hwclock/ntpd so the clock is accutate like my laptop is when I do not connect to the internet for days or weeks at a time.

    Any help would be greatly appreciated.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *