Things are constantly moving forward in Raspberry Pi land and setting up a Real-Time Clock (RTC) on the RPi is no exception. For the old way of doing things see this page. For the new way under Jessie / Stretch or Buster read on. Although this page describes setting up the RTC on Sleepy Pi 2, this same method can actually apply to any supported RTC – you just need to change the overlay as explained below.
Setting up the i2c tools #
Note: If you have used the Sleepy Pi setup script you can skip straight to “Detect the RTC”.
The first order of business is to setup / enable the i2c bus on the Rpi. You can do this by uncommenting a line in config.txt. Here are the magic incantation in a command window:
sudo nano /boot/config.txt
scroll down until you find the line:
#dtparam=i2c_arm=on
and uncomment by removing the # then exit & save (Ctrl-X then y). This will enable the i2c bus (well it will on your next reboot).
Next install the i2ctools by typing:
sudo apt-get install i2c-tools
This will install some handy utilities for the i2c and then reboot:
sudo reboot
Detect the RTC #
To give you a warm cuddly feeling, it’s always a good idea to check the i2c bus with this command:
i2cdetect -y 1
if you’ve got one of the original Raspberry Pi’s, then the bus was 0 so you would type:
i2cdetect -y 0
You should see something like this:
If you are using a Sleepy Pi 1, then the listing is the same but without the 0x24 listing. If you see “UU” instead of “68” it means that the RPi has loaded a driver for it and it is in use – see below.
Setup the RTC #
To tell the Raspberry Pi that we have a hardware clock, we need to add the following line to config.txt.
sudo nano /boot/config.txt
scroll down to the bottom and add the line:
dtoverlay=i2c-rtc,pcf8523
then exit and save (Ctrl-X then y). That’s a comma, not full stop, between i2c-rtc and pcf8523! And it’s a “dash” not “equals” between i2c and rtc!
BTW: if you have another RTC that you are trying to get working and want to know whether out is supported and what the overlay is called, have a look here and see if yours is listed.
Now comment out some lines in hwclock-set:
sudo nano /lib/udev/hwclock-set
and comment out the following lines (using the #).
if [ -e /run/systemd/system ] ; then exit 0 fi
It’s also a good idea to comment out all the –systz lines too (as shown below). These update the RTC from the RPi and can cause issues.
if [ yes - "$BADYEAR" ] ; then # /sbin/hwclock --rtc=$dev --systz --badyear /sbin/hwclock --rtc=$dev --hctosys --badyear else # /sbin/hwclock --rtc=$dev --systz --badyear /sbin/hwclock --rtc=$dev --hctosys fi
then exit and save (Ctrl-X then y). This will stop that script exiting early and will update the clock on boot.
Next reboot and the configuration is done.
Reading and Writing the RTC #
Note: from Buster onwards you need to use a battery with RTC for reasons explained here.
To read the time from the hardware RTC you can issue the following commands. To read the time:
sudo hwclock -r
To copy the time from the RPi system to the hardware RTC (RPi-> RTC):
sudo hwclock -w
To copy the time from the hardware RTC to the RPi system (RTC – RPi):
sudo hwclock -s
You can directly set the time of the hardware RTC with:
sudo hwclock --set --date="2011-08-14 16:45:05"
Running the RTC Off-Grid #
If you set-up the RTC as decided above then by-and-large things should be tickety-boo. If you are connected to a network, the RPI will go and get the time from the Net and you can then copy it across to the RTC with a “sudo hwclock -s”. If we left the –systz uncommented in the /lib/udev/hwclock-set it would even do this automagically (the –systz is shorthand for sys to rtc). However, I’m sure you know there’s a “but” coming….
Avoiding RTC Corruption #
But, the RTC is a funny beast and when you disconnect the RPi from the network strange things can occur which invariably manifest themselves as corrupting the time on the RTC. Pinning down why this occurs is quite arcane, but what is for sure, is that it is caused by the RPi looking for a time synchronisation source and when it doesn’t find it, it decides to ruin everyone’s fun and corrupt the RTC. This is very bad news if you are relying on your RTC to trigger a wake-ups as we do with Sleepy Pi.
So basically persecute any automatic RPI to RTC writes with extreme vengence.
The first step, is to stop the RPi writing to our RTC at boot. If you have followed the instructions above, you will have commented out the –systz lines in /lib/udev/hwclock-set.
Next the mechanism for updating the time over the network is NTP or Network Time Protocol. Disable this by doing:
sudo systemctl stop ntp.service sudo systemctl disable ntp.service
These two steps should do the trick, but if it’s also a good idea to disable the “fake hwclock” (after all, we have a real one!).
Disable this by doing:
sudo systemctl stop fake-hwclock.service sudo systemctl disable fake-hwclock.service
Gotchas #
Whilst working with the RTC, you may come up against a few things that will bite you. Here’s a couple:
Remember to Use “sudo” When Accessing the Clock #
The image below shows that if you don’t use sudo, you’ll get an (not too helpful) error shown below.
This can look really throw you off track when you are configuring the RTC because it makes you think that you haven’t configured it properly.
When You’ve Configured the Clock it Appears as UU Not as 68 #
If you run:
i2cdetect -y 1
after you have configured the RTC in the system then it appear as UU in the map.
This can be pretty disconcerting, but is perfectly normal. It just means that the address 0x68 has been reserved for system use.
If you want to play around with settings on the RTC with the i2c command line tools, you won’t be able to once the System is using it. You can either use the command line tools OR load the System driver, but not both 😥
Troubleshooting #
This section gives you a few tools and techniques to check on…when RTC’s attack.
Remember, with Linux there are always multiple ways of doing the same thing – this can confuse the *%$^ out you. The tips listed below can virtually all be done in other ways. It drives me to distraction…
Getting a Warm and Cuddly Feeling #
You can check that the pcf8523 driver is loaded without a problem by looking to see whether it was loaded at the last boot:
dmesg | grep rtc
Checking the Clocks #
There is a very nice little command that lets you check on the state of the clocks:
timedatectl status
You can see from the above image that there is a line marked “RTC Time” – if you haven’t got the RTC setup, then this line will be blank. You can also see that the RPi time – shows up in Local and Universal is initially different from the RTC time before a “sudo hwclock -w” syncs the 2 together.
You can also do a simple read of the RPi Clock with:
date
and the RTC with:
sudo hwclock -r
Setting the Clocks #
To set the RPi clock you can do:
sudo date -s "03 OCT 2017 14:00:00"
RTC:
sudo hwclock --set --date="2011-08-14 16:45:05"
You can also enable the ntp service and get the current time with a sudo systemctl restart ntp.service. If you are feeling adventurous, then here’s another way:
sudo timedatectl set-ntp true
and similarly “false” to disable.
Checking the Services #
You can check the state of various services with the systemctl command. Here are some examples:
systemctl status ntp.service systemctl status fake-hwclock.service
You can also turn them back on with:
sudo systemctl restart ntp.service
Checking When the Clock Updates #
If you are troubleshooting strange clock syncs, the following command trawls the log for when the system updates the clock:
cat /var/log/syslog | grep "Time has been changed"
Other Clock Syncing #
The whole clock thing under Linux is a complete Dog’s Breakfast. The timesync service also does a similar job to NTP. Why have 2? You tell me. Whenever I’ve looked, it appears to be disabled but you may need to check this puppy out if you are having problems:
systemctl status systemd-timesyncd.service
and if is is active, stop it:
sudo systemctl stop systemd-timesyncd.service sudo systmectl disable systemd-timesyncd.service
I have an issue where I cant read from my RTC. hen I run sudo hwclock -r, it says:
hwclock: iotcl(RTC_RD_TIME) to /dev/rtc0 to read time failed: Invalid argument
When I run dmesg | grep rtc, it says:
pi@raspberrypi:~ $ dmesg | grep rtc
[ 6.552835] rtc-pcf8523 1-0068: low voltage detected, time is unreliable
[ 6.553134] rtc-pcf8523 1-0068: registered as rtc0
[ 6.553612] rtc-pcf8523 1-0068: low voltage detected, time is unreliable
[ 6.553632] rtc-pcf8523 1-0068: hctosys: unable to read the hardware clock
[ 6.638778] rtc-pcf8523 1-0068: low voltage detected, time is unreliable
[ 6.639272] rtc-pcf8523 1-0068: low voltage detected, time is unreliable
[ 42.587954] rtc-pcf8523 1-0068: low voltage detected, time is unreliable
I have run the setup script and done all of the above steps. Where am I going wrong?