Raspberry Pi Python Library for DS3231 Real Time Clock
Here is the third of a series of Python libraries for the Raspberry Pi for various Real Time Clocks (RTC). This is the pure Python driver for the DS3231 Real Time Clock(SwitchDoc Module here). The original
code is the DS1307 library from @XiErCh. The main changes involve removing the 12 hour mode, which didn’t work correctly in all cases and a different clock starting procedure. This library now only runs in 24 hour mode. The DS3231 also has an on board temperature sensor that I will add into the library for the next version (this is now done as of August 7, 2014).
I will be releasing a library for the PCF8563 in the next couple of weeks. I have already released the DS1307 and the MCP79400 libraries. The DS3231 library is on https://github.com/switchdoclabs/RTC_SDL_DS3231.
The DS3231 (I used the SwitchDoc Labs DS3231 Module from our store ) is a 3.3V/5V device. You just connect it up to the Raspberry Pi I2C pins and you are ready to go.
To the right is a picture of the four RTC test jig. I have released the libraries for the
DS1307 and the MCP79400 over the past few weeks. The Python library for the PCF8563 will be released next week.
Example Code for the DS3231
There is a testSDL_DS3231.py included with the library. Here is the bare code needed:
#!/usr/bin/env python
#
# Test SDL_DS3231
# John C. Shovic, SwitchDoc Labs
# 08/03/2014
#
#
# imports
import sys
import time
import datetime
import SDL_DS3231
# Main Program
print “”
print “Test SDL_DS3231 Version 1.0 – SwitchDoc Labs”
print “”
print “”
print “Program Started at:”+ time.strftime(“%Y-%m-%d %H:%M:%S”)
filename = time.strftime(“%Y-%m-%d%H:%M:%SRTCTest”) + “.txt”
starttime = datetime.datetime.utcnow()
ds3231 = SDL_DS3231.SDL_DS3231(1, 0x68)
ds3231.write_now()
# Main Loop – sleeps 10 minutes, then reads and prints values of all clocks
while True:
currenttime = datetime.datetime.utcnow()
deltatime = currenttime – starttime
print “”
print “Raspberry Pi=\t” + time.strftime(“%Y-%m-%d %H:%M:%S”)
print “DS3231=\t\t%s” % ds3231.read_datetime()
time.sleep(10.0)
<\code>
You should see a result like this:
Test SDL_DS3231 Version 1.0 - SwitchDoc Labs Program Started at:2014-08-03 19:29:58 Raspberry Pi= 2014-08-03 19:29:58 DS3231= 2014-08-03 19:29:58
Initial Test Results for the DS3231
I am in the process of running an month long test of three RTCs (DS3231, MCP79400 and the PCF8563) and so far, the DS3231 is running with an error < 2ppm (parts per million). 2ppm is about .17 seconds per day. I ran the test for the DS1307 and saw > 20ppm. Since I only can detect errors > 1 second, it will be a few more days until we all find out what the error rate really is. The DS3231 does do temperature compensation, so it is not going to drift as much with temperature. Temperature is clearly a problem for a project such as Project Curacao in the tropics, so I am planning to use this RTC in the upgrade in September.
Project Curacao, Arduino and the DS3231
I used a Adafruit DS1307 on Project Curacao connected to the Arduino Battery Watchdog. This has been the source of reliability issues on the Arduino. It requires a reboot (power on / off) about once a month. And it is the DS1307 getting lost. Noise? Heat? I am not sure. But I am replacing it in September with the DS3231 which is temperature compensated in any case.
Hello,
I’m having a little trouble adding the alarms to your python script and was hoping you could help.
I added the registers to the class:
class SDL_DS3231():
_REG_SECONDS = 0x00
_REG_MINUTES = 0x01
_REG_HOURS = 0x02
_REG_DAY = 0x03
_REG_DATE = 0x04
_REG_MONTH = 0x05
_REG_YEAR = 0x06
_A1M1 = 0x07
_A1M2 = 0x08
_A1M3 = 0x09
_A1M4 = 0x0A
_A2M2 = 0x0B
_A2M3 = 0x0C
_A2M4 = 0x0D
_CONTROL = 0x0E
And added some read write functions for the alarm values:
#Alarm Values
def read_A2Min(self):
return _bcd_to_int(self._read(self._A2M2))
def write_A2Min(self,min):
self._write(self._A2M2, _int_to_bcd(min))
def read_A2Hr(self):
return _bcd_to_int(self._read(self._A2M3))
def write_A2Hr(self,hr):
self._write(self._A2M3, _int_to_bcd(hr))
def read_A2Day(self):
return _bcd_to_int(self._read(self._A2M4))
def write_A2Day(self,day):
self._write(self._A2M4, _int_to_bcd(day))
def read_Control(self):
return _bcd_to_int(self._read(self._CONTROL))
def write_Control(self,ctrl):
self._write(self._CONTROL, _int_to_bcd(ctrl))
But I’m a little stuck on how to set the alarm register mask bits (Bit 7) and the control register.
Are you able to provide an example that say sets alarm 2 for every 15 minutes?
Thanks in advance.
I ran the testSDL_DS3231.py – but encountered the following issue
The DS3231 is a module (with 5 pins) from a China website
File “testSDL_DS3231.py”, line 46, in
ds3231.write_AT24C32_byte(x, value)
File “/home/pi/python/SDL_DS3231.py”, line 242, in write_AT24C32_byte
self._bus.write_i2c_block_data(self._at24c32_addr,a1,[a0, value])
IOError: [Errno 5] Input/output error
Sorry for the posted question – the module I have don’t have the AT24C32 – it has only the DS3231
Please advise if and how to use your reference code – (masking the AT24C32 portion ? Can it work without those lines ? )
Thanks
I masked those AT24C32 – work fine
Thanks and sorry for these questions
No problem. Note, your board does have the AT24C32 on it. The I2C address 0x68 is the DS3231 and 0x56 is the AT24C32. Note that on some of the new revision boards the AT24C32 address is 0x57.
So you may have to change the address for the AT24C32 to 0x57.
SDL
Hi SDL,
Ido believe the board don’t have the AT24C32 (after checking picture of those board has this and the one I have) – I can send you picture for reference if you are interested. (Need email address)
I tried both 0x56 and 0x57 and same error occurred.
Thanks
Regards