Our RTC module from the Hardware posting “speaks” I2C and the Raspberry has some GPIO-pins for just that. Unfortunalety, in the default configuration the Raspberry does not understand I2C. We need to modify some files, have some packages installed and then we are ready to go.
One word of warning: I strongly discourage you from connecting anything to the Raspberry’s GPIO header when the Raspberry is running and/or connected to power. Before fiddling with hardware halt the system, disconnect the power and after you’ve done that, connect what you want.
In order to have I2C on the Raspberry we need to make sure that the proper kernel modules are loaded. Linux/Unix has the ability to dynamically load modules when they are needed but there also numerous modules that are loaded on boot. Think of a kernel module as a low-level driver for some specific hardware. To then interact with hardware, the so called “devices” are added to the filesystem. These are special “files” that serve as the connection between programs and the real hardware. One example was the parallel printer device from my Parallel Printer post.
The Raspberry has a file that blacklists modules the kernel should ignore. This means that even when the kernel detects new hardware, the module does not get loaded. This is to prevent special cases, where one or more modules support the same device which would cause erratic behaviour. The modprobe man page explains this even better.
So at first we get rid of the blacklisting. On your console do a
sudo nano /etc/modprobe.d/raspi-blacklist.conf
The contents of the file should look like this:
# blacklist spi and i2c by default (many users don't need them) blacklist spi-bcm2708 blacklist i2c-bcm2708
Remember, this file is a blacklist. So everything that is not commented out gets ignored. We want I2C to be enabled so we comment out the i2c-bcm2708 entry:
# blacklist spi and i2c by default (many users don't need them) blacklist spi-bcm2708 # blacklist i2c-bcm2708
Now the module will be loaded but what about the device? There is another file we need to edit. On the command line do
sudo nano /etc/modules
and edit the file by adding one line for the module i2c-dev, which is the module responsible for creating a device. Your file should then look like this: See, I also added an explicit line rtc-ds1307, we will need that later.
# /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. # Parameters can be specified after the module name. snd-bcm2835 i2c-dev rtc-ds1307
Next we need to load some packages. I recommend doing an update and an upgrade before that. So, again on the command line issue the following commands one at a time. The last line adds our user, that is pi if you didn’t change it, to the i2c group so that we have permissions to use the device.
sudo apt-get update sudo apt-get upgrade sudo apt-get install i2c-tools sudo apt-get install python-smbus sudo adduser pi i2c
Now all the necessary changes have been made and we are ready to connect the RTC. But remember, halt the system, remove power and then connect the RTC module.
Connect the RTC
After the Raspberry has booted up again, let’s see if the clock (or any other device on the I2C bus) gets detected:
sudo i2cdetect -y 1
If you have an old Raspberry (Revision 1 with 256 MB Ram) please type sudo i2cdetect -y 0. Between revision the bus has changed.
You should see something like this and that looks good. It tells us that there are two devices on the I2C bus, one with address 0x50, the other on 0x68. The latter one should be the RTC.
Now we need to create a device for the RTC. This next command must be run as root. This is what the line “sudo su” does. I do all this for a raspberry with 512 MB, so I am addressing the i2c bus number 1.
sudo su echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device exit
The second command initiates the creation of the device. This must be done by software, as I2C devices are not automatically numbered by the kernel. If you want to dive into more technicality here, check this link to the kernel documentation.
If everything went well to this point, you should now see a device called /dev/rtc0. Test it with the command ls -al /dev/rt* and see, if you get an output like this.
crw------- 1 root root 254, 0 Jul 2 16:11 /dev/rtc0
Now it’s time to read the time from our RTC module for the first time. (Wow, three times the word “time” in one sentence. My english teacher would have strongly disagreed)
To read the time, on the command line do
sudo hwclock -r
and you should get somethink like:
Sa 01 Jan 2000 01:18:35 CET -0.233700 seconds
To write the current system time to the RTC use the command
sudo hwclock -w
The time is there and readable, but my RTC obviously is not correctly set. But it works and so this is the proof of concept and I stop here. I won’t have the RTC module connected all the time, my Raspberry has an internet connection and gets the time via NTP. I just wanted to see what is necessary to add an RTC to the I2C bus of the Raspyberry. This is the essence of Tinkering. Try things out and be happy if they work out.
Please be aware that the device is not permanently created. After a reboot the /dev/rtc0 is gone and you need to restart from the “sudo su” lines above. To permanently add the RTC there is a good tutorial at elevendroids’ blog.