It's easy to use the DS3231 RTC with CircuitPython too!  There's a handy Adafruit CircuitPython DS3231 module you can load on a board and get started setting and reading the time with Python code!

First wire up the DS3231 to your board as shown on the previous Arduino page.  The DS3231 uses a simple I2C connection with:

  • Vin connected to your board's 3.3V or 5V output.
  • GND connected to your board's ground.
  • SCL connected to your board's I2C SCL / clock line.
  • SDA connected to your board's I2C SDA / data line.

You'll also need to install the Adafruit CircuitPython DS3231 library on your CircuitPython board.  Remember this module is for Adafruit CircuitPython firmware and not firmware!

First make sure you are running the latest version of Adafruit CircuitPython for your board.

Next you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  For example the Circuit Playground Express guide has a great page on how to install the library bundle for both express and non-express boards.

Remember for non-express boards like the Trinket M0, Gemma M0, and Feather/Metro M0 basic you'll need to manually install the necessary libraries from the bundle:

  • adafruit_ds3231.mpy
  • adafruit_bus_device
  • adafruit_register

Before continuing make sure your board's lib folder or root filesystem has the adafruit_ds3231.mpy, adafruit_bus_device, and adafruit_register files and folders copied over.

Next connect to the board's serial REPL so you are at the CircuitPython >>> prompt.

Then import the necessary board and busio modules to initialize the I2C bus:

Download: file
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)

Note on some boards like the ESP8266 that don't have a hardware I2C interface you might need to instead import and use the bitbangio module, like:

Download: file
import board
import bitbangio
i2c = bitbangio.I2C(board.SCL, board.SDA)

Now import the DS3231 module and create an instance of the DS3231 class using the I2C interface created above:

Download: file
      import adafruit_ds3231
ds3231 = adafruit_ds3231.DS3231(i2c)

At this point you're read to read and even set the time of the clock.  You just need to interact with the datetime property of the DS3231 instance.  For example to read it you can run:

Download: file

Notice the time is returned as a special Python time structure.  This is from the time module in Python and it has properties like:

  • tm_year - The year of the timestamp
  • tm_mon - The month of the timestamp
  • tm_mday - The day of the month of the timestamp
  • tm_hour - The hour of the timestamp
  • tm_min - The minute of the timestamp
  • tm_sec - The second of the timestamp
  • tm_wday - The day of the week (0 = Monday, 6 = Sunday)
  • tm_yday - The day within the year (1-366)
  • tm_isdst - 0 if not in daylight savings, 1 if in savings, and -1 if unknown

Also notice if the time hasn't been set it defaults to a value of January 1st, 2000 (wow Y2K retro!).

You can write to the datetime property to set the time of the clock, for example to set it to January 1st, 2017, at midnight local time you could run:

Download: file
import time
ds3231.datetime = time.struct_time((2017, 1, 1, 0, 0, 0, 6, 1, -1))

Notice the parameters to the struct_time initializer, you must pass in a tuple of all the values listed above.

Now if you read the datetime property you'll see the clock is running from the set time.  For example if you want to read and print out just the year, month, day, hour, minute, and second you could run:

Download: file
current = ds3231.datetime
print('The current time is: {}/{}/{} {:02}:{:02}:{:02}'.format(current.tm_mon, current.tm_mday, current.tm_year, current.tm_hour, current.tm_min, current.tm_sec))

That's all there is to using the DS3231 with CircuitPython!  Simply import the DS3231 module, create an instance of the class, and interact with its datetime property to set and get the time!

Here's a complete example program you can save as on your board and see the time and date printed every second to the REPL:

# Simple demo of reading and writing the time for the DS3231 real-time clock.
# Change the if False to if True below to set the time, otherwise it will just
# print the current date and time every second.  Notice also comments to adjust
# for working with hardware vs. software I2C.

import time
import board
# For hardware I2C (M0 boards) use this line:
import busio as io
# Or for software I2C (ESP8266) use this line instead:
#import bitbangio as io

import adafruit_ds3231

i2c = io.I2C(board.SCL, board.SDA)  # Change to the appropriate I2C clock & data
                                    # pins here!

# Create the RTC instance:
rtc = adafruit_ds3231.DS3231(i2c)

# Lookup table for names of days (nicer printing).
days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")

#pylint: disable-msg=bad-whitespace
#pylint: disable-msg=using-constant-test
if False:   # change to True if you want to set the time!
    #                     year, mon, date, hour, min, sec, wday, yday, isdst
    t = time.struct_time((2017,  10,   29,   15,  14,  15,    0,   -1,    -1))
    # you must set year, mon, date, hour, min, sec and weekday
    # yearday is not supported, isdst can be set but we don't do anything with it at this time
    print("Setting time to:", t)     # uncomment for debugging
    rtc.datetime = t
#pylint: enable-msg=using-constant-test
#pylint: enable-msg=bad-whitespace

# Main loop:
while True:
    t = rtc.datetime
    #print(t)     # uncomment for debugging
    print("The date is {} {}/{}/{}".format(days[int(t.tm_wday)], t.tm_mday, t.tm_mon, t.tm_year))
    print("The time is {}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec))
    time.sleep(1) # wait a second
This guide was first published on Feb 03, 2016. It was last updated on Feb 03, 2016. This page (CircuitPython) was last updated on Dec 12, 2018.