Home

Awesome

MicroPython TinyRTC I2C module

MicroPython driver for the TinyRTC I2C module, featuring a DS1307 RTC and AT24C32N EEPROM.

demo

Pins

Pins are available on both sides. You can use either. One side exposes more pins.

PinNameDescription
BATBattery VoltageFor monitoring battery voltage
GNDGroundGround
VCCInput Supply+5V power for module and to charge coin cell battery
SDAI2C DataI2C data for DS1307 and EEPROM
SCLI2C ClockI2C clock for DS1307 and EEPROM
DSDS18B20Optional temperature sensor 1-wire data
SQSquare WaveOptional square wave or logic level output

DS1307 RTC Examples

# VCC-GND STM32F407VET6 on SPI3
>>> from machine import I2C, Pin
>>> i2c = I2C(3) # SCL=A8, SDA=C9
>>> i2c.scan()
[80, 104]

# 80 == 0x50 == AT24C32N EEPROM
# 104 == 0x68 == DS1307

>>> import ds1307
>>> ds = ds1307.DS1307(i2c)
ds.datetime()
ds.datetime(now)

# initial datetime value, oscillator disabled
>>> ds.datetime()
(2000, 1, 1, 0, 0, 0, 0, 0)

# read datetime after 1 second (no change)
>>> ds.datetime()
(2000, 1, 1, 0, 0, 0, 0, 0)

# enable oscillator
>>> ds.halt(False)

# read datetime after 1 second
>>> ds.datetime()
(2000, 1, 1, 0, 0, 0, 1, 0)

# read datetime after 1 more second
>>> ds.datetime()
(2000, 1, 1, 0, 0, 0, 2, 0)

# read datetime after 1 more second
>>> ds.datetime()
(2000, 1, 1, 0, 0, 0, 3, 0)

# set the datetime 24th March 2018 at 1:45:21 PM
>>> now = (2018, 3, 24, 6, 13, 45, 21, 0)
>>> ds.datetime(now)

# read datetime after 1 second
>>> ds.datetime()
(2018, 3, 24, 6, 13, 45, 22, 0)

# read datetime after 1 second
>>> ds.datetime()
(2018, 3, 24, 6, 13, 45, 23, 0)

# disable oscillator
>>> ds.halt(True)

# read datetime after 1 second
>>> ds.datetime()
(2018, 3, 24, 6, 13, 45, 24, 0)

# read datetime after 1 second (no change)
>>> ds.datetime()
(2018, 3, 24, 6, 13, 45, 24, 0)

# minute increment (00:00:59 -> 00:01:00)
>>> ds.datetime((2018, 3, 24, 6, 0, 0, 58, 0))
>>> ds.datetime()
(2018, 3, 24, 6, 0, 0, 59, 0)
>>> ds.datetime()
(2018, 3, 24, 6, 0, 1, 0, 0)

# hour increment (00:59:59 -> 01:00:00)
>>> ds.datetime((2018, 3, 24, 6, 0, 59, 58, 0))
>>> ds.datetime()
(2018, 3, 24, 6, 0, 59, 59, 0)
>>> ds.datetime()
(2018, 3, 24, 6, 1, 0, 0, 0)

# day + weekday increment (23:59:59 Sat -> 00:00:00 Sun)
>>> ds.datetime((2018, 3, 24, 6, 23, 59, 58, 0))
>>> ds.datetime()
(2018, 3, 24, 6, 23, 59, 59, 0)
>>> ds.datetime()
(2018, 3, 25, 0, 0, 0, 0, 0)

# month increment (Wed 28th Feb 2018 -> Thu 1st Mar 2018)
>>> ds.datetime((2018, 2, 28, 3, 23, 59, 58, 0))
>>> ds.datetime()
(2018, 2, 28, 3, 23, 59, 59, 0)
>>> ds.datetime()
(2018, 3, 1, 4, 0, 0, 0, 0)

# month increment on leap year Feb has 29 days (Sun 28th Feb 2016 -> Mon 29th Feb 2016)
>>> ds.datetime((2016, 2, 28, 0, 23, 59, 58, 0))
>>> ds.datetime()
(2016, 2, 28, 0, 23, 59, 59, 0)
>>> ds.datetime()
(2016, 2, 29, 1, 0, 0, 0, 0)

# month increment on leap year (Mon 29th Feb 2016 -> Tue 1st Mar 2016)
>>> ds.datetime((2016, 2, 29, 1, 23, 59, 58, 0))
>>> ds.datetime()
(2016, 2, 29, 1, 23, 59, 59, 0)
>>> ds.datetime()
(2016, 3, 1, 2, 0, 0, 0, 0)

# year increment (31st Dec 2018 -> 1st Jan 2019)
>>> ds.datetime((2018, 12, 31, 1, 23, 59, 58, 0))
>>> ds.datetime()
(2018, 12, 31, 1, 23, 59, 59, 0)
>>> ds.datetime()
(2019, 1, 1, 2, 0, 0, 0, 0)

# square wave output on pin SQ - 1Hz
>>> ds.square_wave(1, 0)

# square wave output on pin SQ - 4.096kHz
>>> ds.square_wave(4, 0)

# square wave output on pin SQ - 8.192kHz
>>> ds.square_wave(8, 0)

# square wave output on pin SQ - 32.768kHz
>>> ds.square_wave(32, 0)

# logic level output on pin SQ - high
>>> ds.square_wave(0, 1)

# logic level output on pin SQ - low
>>> ds.square_wave(0, 0)

DS18B20 1-Wire Temperature Sensor Examples

>>> from machine import Pin
>>> import onewire
>>> ow = onewire.OneWire(Pin('A9'))
>>> ow.scan()
[bytearray(b'(\xc9E\x01\x00\x00\x80/')]

>>> import time, ds18x20
>>> ds = ds18x20.DS18X20(ow)
>>> roms = ds.scan()
>>> ds.convert_temp()
>>> time.sleep_ms(750)
>>> for rom in roms:
...     print(ds.read_temp(rom))
23.8125

AT24C32N EEPROM Examples

>>> from machine import I2C, Pin
>>> i2c = I2C(3) # SCL=A8, SDA=C9
>>> i2c.scan()
[80, 104]

>>> import at24c32n
>>> eeprom = at24c32n.AT24C32N(i2c)

# read 32 bytes starting from memory address 0
>>> eeprom.read(0, 32)
b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'

# write hello world to memory address 0
>>> eeprom.write(0, 'hello world')

# read back the hello world
>>> eeprom.read(0, 32)
b'hello world\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
>>> eeprom.read(0, 11)
b'hello world'

# write multiple pages (32 bytes per page)
>>> eeprom.write(0, b'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')

# read multiple pages (32 bytes per page)
>>> eeprom.read(0,64)
b'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\xff\xff'

# mutliple page writes (fill pages 0 and 1 with test data)
# write is performed in two steps, "0" x 32 in the first page, then "1" x 32 in the next page
# memory address was at the start of a page boundary so each write is a full 32 byte page write
>>> eeprom.write(0, b'0000000000000000000000000000000011111111111111111111111111111111')
>>> eeprom.read(0,64)
b'0000000000000000000000000000000011111111111111111111111111111111'

# partial page writes
# write some bytes spanning two pages, not starting at a page boundary
# write is performed in two steps, "abc" in the first page then "def" in the next page
>>> eeprom.write(29, b'abcdef')
>>> eeprom.read(0,64)
b'00000000000000000000000000000abcdef11111111111111111111111111111'

# fill entire eeprom with 0xFF
>>> buf = b'\xff' * 32
>>> for i in range(128):
...     eeprom.write(i*32, buf)

# show page boundaries
>>> for i in range(128):
...     eeprom.write(i*32, '|-Page-{:-<24}|'.format(i))
>>> eeprom.read(0,128)
b'|-Page-0-----------------------||-Page-1-----------------------||-Page-2-----------------------||-Page-3-----------------------|'

# read entire eeprom
>>> eeprom.read(0,4096)

PyBoard / STM32F4 built-in RTC

You do not need this module if you are using a PyBoard or STM32 microcontroller with built in RTC hardware.

Simply add a coin cell battery between GND + VBAT and use pyb.RTC.

On the early pyboards, VBAT is the backup battery for the RTC. On the newer boards, VBAT is for powering the pyboard using a battery and the RTC battery is called Vbackup.

# on the PyBoard or a STM32F407
rtc = pyb.RTC()
# set time
rtc.datetime((2018, 3, 24, 6, 13, 45, 21, 0))
# attach battery between GND + VBAT
# disconnect, reconnect
# get time
print(rtc.datetime())

Troubleshooting

If you are using the ESP32 loboris port, swap the addrsize=16 for a adrlen=2.

Parts

Connections

STM32F407VET6TinyRTC I2C module
A9 (any pin)DS
A8 (I2C3 SCL)SCL
C9 (I2C3 SDA)SDA
3V3VCC
GNDGND

Links

License

Licensed under the MIT License.