I’ve been spending some time with the Maxim Integrated DS3231 “Extremely Accurate I2C Integrated RTC”. Many have recommended it to provide a RTC for an advanced Arduino style board called the Goldilocks, so I looked into putting one of these SOIC16 devices on the board. The bottom line is that the best device price to me is greater than the finished price for a Raspberry Pi compatible module, complete with either a battery or a super capacitor to maintain the time should the main power be lost.

DS3231 RTC Module
The DS3231 also contains an accurate thermometer, used to trim the timing to maintain the +-2ppm accuracy characteristic from 0 to 40 degrees Celcius. The registers for the temperature can be read, and make a useful secondary function for this device.
I purchased some DS3231 modules for my Raspberry Pi devices, and also to test their use as an option for the Goldilocks Analogue. This is to remind myself how the Raspberry Pi needs to be configured to use the DS3231 RTC module.
Arduino
Actually using the DS3231 on the Arduino platform is very easy. Simply, treat it exactly as a DS1307 device. It behaves identically, except it is significantly more accurate.
For the Goldilocks Analogue, the module can simply be plugged into the prepared port, replicating the Raspberry Pi interface.
The Goldilocks Analogue is now available on Kickstarter.
Configuring for Raspberry Pi
To contain cost the Raspberry Pi doesn’t have a hardware or real time clock capability. A fake RTC is provided which simply stores the time the Raspberry Pi was shut down, and reads this time out when the Raspberry Pi is booting. Obviously this time can be wrong by anything from 10 seconds to a year, depending on how long the Raspberry Pi is left unused.
The DS3231 module is an I2C device that is attached to IO pins 1 through 5 on the Raspberry Pi. The DS3231 can run from either 3V3 or 5V so it can work with both Arduino and Raspberry Pi I2C bus levels.
There are several Internet references on how to get the DS3231 working on the Raspberry Pi. But the most concise version is by Drew Keller. Initially I used these to get started, but the method described activates the RTC at the end of the boot sequence, long after the time is really needed to set logging and disk access times correctly. Fortunately, there is another instruction that describes some minor changes to the hwclock.sh script which enables the DS3231 early in the boot sequence, ensuring that we have the correct time when we need it. Unfortunately it describes insertion of the wrong module, and refers to the DS1307 (although this is essentially the same).
So that I don’t forget what to do, here are the instructions again.
Update: Kernel 3.18 breaks some things. This is the fix.
First lets fix something only relevant to those who are running the 3.18+ kernel.
Help, my I2C interface has disappeared. What do I do? Add
# Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c1=on dtparam=i2c1_baudrate=100000 dtparam=i2c_arm=on # Enable the DS3231 RTC dtoverlay=i2c-rtc,ds3231
to your /boot/config.txt and reboot. If you are feeling terse you can omit the “=on”, since that is the default option.
Now we have to edit the hwclock.sh file in /etc/init.d/ to add this function to initialise the RTC.
HCTOSYS_DEVICE=rtc0 init_rtc_device() { [ -e /dev/$HCTOSYS_DEVICE ] && return 0; # load i2c and RTC kernel modules # unnecessary from kernel 3.18 when using above dtoverlay # modprobe i2c-bcm2708 # 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 ds3231 0x68 >> $bus/new_device; if [ -e /dev/$HCTOSYS_DEVICE ]; 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 }
Then a bit further down in the start) section add in a call to the initialisation function we’ve just prepared, and also comment out the udev search as it won’t find the DS3231.
case "$1" in start) # initialise the hardware RTC DS3231 # this is for the module attached init_rtc_device ... # As UDEV won't find ds3231, comment this out # if [ -d /run/udev ] || [ -d /dev/.udev ]; then # return 0 # fi ...
Then we have to remove the I2C module blacklist entry (by commenting it out) so that it can be loaded on boot. The Raspberry Pi team think that their users won’t use I2C or SPI functions normally, so they’re preemptively disabled.
This step is probably unnecessary, as the I2C interface is no longer disabled by default.
sudo sed -i 's/blacklist i2c-bcm2708/#blacklist i2c-bcm2708/' /etc/modprobe.d/raspi-blacklist.conf
The final thing left is to remove the fake hardware clock function by typing this command from the shell.
sudo update-rc.d fake-hwclock remove
The reboot the Raspberry Pi and check that you can see the /etc/rtc0 and that the hwclock function returns a valid time. By studying the boot log messages relating to the RTC can also be seen. Check that you’re getting no errors. You should see something like this.
[ 10.631809] rtc-ds1307 1-0068: rtc core: registered ds3231 as rtc0 [ 10.650126] i2c i2c-1: new_device: Instantiated device ds3231 at 0x68
this worked great so far. first boot after change to hwclock script had this error:
Easy to fix with
to write an initial correct time into the new RTC device.
Good catch.
My DS3231 RTC device already had a valid time written to it, because I’d used it previously. Therefore, it didn’t flag this error on the first boot.
Pingback: Mini RTC Module / DS3231 for PI | chaeplin
Thanks for the guide! FYI through my research I found that you are missing two steps at the end:
sudo update-rc.d hwclock.sh enable # Enable the real hardware clock
sudo apt-get purge fake-hwclock # Uninstall fake-hwclock and it’s now useless cron jobs