title | layout | meta-description | share | author | about | cats | simple-description |
---|---|---|---|---|---|---|---|
DS3241 Real Time Clock on the Microbit |
text-width-sidebar |
Connect a DS3231 RTC to the microbit and take time & date with python. |
true |
jez |
Use a RTC to record the time in Python |
external |
DS3231 RTC |
Ignore this.
All of it!
A Real Time Clock (RTC) allows the microbit to know the time. It has a small battery and can keep the time for years. The microbit can use this data for datalogging and other programs.
This page uses the DS3231
chip. The module is a generic one from eBay.
{:.ui .dividing .header}
You must connect 4 of the wires from the module to the microbit.
{:.ui .very .basic .small .table}
Board Pin | Microbit Pin |
---|---|
GND |
GND |
VCC |
3V |
SDA |
PIN 20 |
SCL |
PIN 19 |
You'll need a microbit edge connector to access the microbit's 19 & 20 pins.
Before beginning we need to obtain the I2C address of the device. Here are the results of the scan script on my module:
{% highlight python %}
Scanning I2C bus... Found: [0xe] Found: [0x1d] Found: [0x57] Found: [0x68] Scanning complete Reference: Magnetometer [0x0e] Accelerometer [0x1d] {% endhighlight %}
There are two additional devices: 0x57
& 0x68
whereas only the RTC might be expected.
There are often two devices on each module. One is the DS3231 RTC and the other is EEPROM memory. On my devices, the RTC has the address 0x68
.
{:.ui .dividing .header}
This example uses a Python module to communicate with the RTC. Download it from https://github.com/switchdoclabs/RTC_SDL_DS3231/blob/master/SDL_DS3231.py. Flash your script in mu (as below) and then upload the module. There's more detail on the how to page.
The head of the main script file would look like this:
{% highlight python %}
from microbit import I2C, display
from ds3231 import DS3231
rtc = SDL_DS3231()
{% endhighlight %}
The time on the RTC must be set.
You will need only to update it for British Summer Time or if the battery is replaced.
{% highlight python %}
rtc.set_datetime( seconds=20, minutes=32, hours=14, day=13, month=10, year=2016, )
{% endhighlight %}
With the time set, it is possible to read the time from the RTC.
There are three functions for returning the time:
datetime_tuple()
--- a tuple of the time and datedatetime_string()
--- a string of the time and datetime_string()
--- a string of the time, eg. 11:33
Return the time and date as a tuple.
Format is (YYYY, MM, DD, HH, MM, SS) {% highlight python %}
rtc.datetime_tuple() (2016, 10, 13, 14, 32, 20) {% endhighlight %}
Return the time & date as a string.
Format is YYYY-MM-DDTHH:MM:SS. This is useful for recording as a .CSV
file and importing into excel.
{% highlight python %}
rtc.datetime_string() '2016-10-13T14:32:20' {% endhighlight %}
Return the time as a string.
Format is HH:MM.
{% highlight python %}
rtc.time_string() '14:32' {% endhighlight %}
{% highlight python %}
from microbit import i2c, display
from ds3231 import DS3231
rtc = DS3231()
rtc.set_datetime( second=20, minute=32, hours14, day=13, month=10, year=2016, )
rtc.datetime_tuple()
rtc.datetime_string()
display.scroll(rtc.time_string())
year, month, day, hour, minute, seconds = rtc.datetime_tuple()
if hour > 23 and hour < 7: display.show(Image.GHOST) else: display.show(Image.FABULOUS) {% endhighlight %}
{:.ui .dividing .header}
-
There is 32k of EEPROM memory on many of these modules. It would be possible to log data to the memory. I've not quite managed to work out how to do this yet.
-
There's also a thermometer. Again, I've not managed get it working!
AT24C32 Code
from microbit import i2c, sleep
def _bcd2bin(value):
return value - 6 * (value >> 4)
def _bin2bcd(value):
return value + 6 * (value // 10)
class DS3231():
def __init__(self, addr=0x68):
self._addr = addr
self._at24c32_addr = at24c32_addr
def datetime_tuple(self):
buffer = bytearray(7)
buffer = i2c.read(self._addr, 7)
return (
_bcd2bin(buffer[6]) + 2000, # year
_bcd2bin(buffer[5]), # month
_bcd2bin(buffer[4]), # day
_bcd2bin(buffer[2]), # hour
_bcd2bin(buffer[1]), # minute
_bcd2bin(buffer[0]), # second
)
def time_string(self):
year, month, day, hour, minute, second = self.datetime_tuple()
return '%02d:%02d' % (hour, minute)
def datetime_string(self):
year, month, day, hour, minute, second = self.datetime_tuple()
return '%02d-%02d-%02dT%02d:%02d:%02d' % (year, month, day, hour, minute, second)
def set_datetime(self, year, month, day, hour, minute, second):
buffer = bytearray(7)
buffer[6] = _bin2bcd(year % 1000)
buffer[5] = _bin2bcd(month)
buffer[4] = _bin2bcd(day)
buffer[2] = _bin2bcd(hour)
buffer[1] = _bin2bcd(minute)
buffer[0] = _bin2bcd(second)
i2c.write(self._addr, buffer)