[EN] RTC DS1302 and Micropython

This article describes programming to use the DS1302 (Figure 1), another RTC (Real-Time Clock) IC (previously written to PCF8583 in Python and Arduino C++). And it is a module that is popular for beginners because it is a module in the learning kit of Arduino, IoT, 37-Sensors or 45 Sensors, etc.

(Figure. 1 Example of ds1302 module connection.)

DS1302

The features of the DS1302 are as follows.

  1. Store seconds, minutes, hours, day of month, month, day of week, year.
  2. Year values are valid starting until 2100.
  3. It has 31 bytes of 8-bit RAM memory (RAM) backed up by battery.
  4. Operates at 2.0VDC to 5.5VDC
  5. Use current less than 300nA when using 2VDC voltage.
  6. Work in temperature -40°C to 85°C

The arrangement of the pins of the IC chassis is as shown in Figure 2, it is found that there are a total of 8 pins, namely Vcc1, Vcc2, X1, X2, GND, CE, SCLK and I/O. Pin X1, X2 are the pins connected to crystal, and the pins for connecting to the microcontroller are Vcc, GND, SCLK, CE (for reset) and I/O as shown in Figure 3.

(Figure. 2 The arrangement of the pins of the DS1302 IC.(Credit DS1302 Datasheet)
(Figure. 3 The DS1302 module and pins are connected to the microcontroller.)

The address of the internal memory DS1302 is shown in Figure 4.

(Figure. 4 DS1302 internal memory address(Credit DS1302 Datasheet.)

The format of the instruction sent to the RTC is 8 bits, with each bit meaning as shown in Figure 5.

(Figure. 5 DS1302 command/position bytes(Credit DS1302 Datasheet.)

From Figure 5, it can be seen that the different bits have the following meanings:

  1. RAM or CK/
  2. A0-A4, address value to be accessed
  3. RD , WR/

The format of data transmission in communication between the microcontroller and DS1302 is shown in Figure 6.

(Figure. 6 Data transmission/receiving pattern between microcontroller and DS1302(Credit ds1302 Datasheet.)

The time-diagram of writing and reading data of the DS1302 is shown in Figures 7 and 8, respectively.

(Figure. 7 Timeline of data writing(Credit ds1302 datasheet.)
(Figure. 8 Timeline of data reading(Credit ds1302 datasheet.)

From the picture of the format of transmitting and receiving data, it is noted that before sending bits, the SCLK state must be changed from 0 to 1, and when it is sent, it must be changed from 1 to 0 and alternated until all data is transmitted.

  1. Change the status of the CE pin from 0 to 1.
  2. Send the R/W’ bit to indicate the transmission flag.
  3. Send bits A0, A1, A2, A3 and A4 to indicate the address.
  4. Send R/C’ bit.
  5. End with bit 1.
  6. Send 8-bit data in order of D0, D1, D2, …, D7.
  7. Change the status of the CE pin from 1 to 0.

Example Code

Example code for setting and displaying time by connecting between ESP32 and Module DS1302 as shown in Figure 9.

(Figure. 9 Example of connecting to ESP32.)
################################################
# demo_ds1302.py
# (C) 2021, JarutEx (https://www.jarutex.com
################################################
from machine import Pin
import time

# setting
class DS1302:
    REG_SECOND = const(0x80)
    REG_MINUTE = const(0x82)
    REG_HOUR   = const(0x84)
    REG_DAY    = const(0x86)
    REG_MONTH  = const(0x88)
    REG_WEEKDAY= const(0x8A)
    REG_YEAR   = const(0x8C)
    REG_WP     = const(0x8E)
    REG_CTRL   = const(0x90)
    REG_RAM    = const(0xC0)
    
    def __init__(self, _sclk=12, _io=13, _ce=14):
        self.pinClk = Pin( _sclk, Pin.OUT )
        self.pinIO = Pin( _io )
        self.pinCE = Pin( _ce, Pin.OUT )
        self.pinCE.value(0) # disable
        self.pinClk.value(0)
        self.rtc = [0,0,0,0,0,0,0] # y/m/d/dw/h/mi/s

    def dec2bcd(self, n):
        return ((n // 10 * 16) + (n % 10))

    def bcd2dec(self, n):
        return ((n // 16 * 10) + (n % 16))

    def write(self, data):
        self.pinIO.init(Pin.OUT)
        for i in range(8):
            bit = (data & 0x01)
            data = (data >> 1)
            self.pinIO.value(bit)
            self.pinClk.value(1)
            self.pinClk.value(0)
        
    def read(self):
        self.pinIO.init( Pin.IN )
        byte = 0
        for i in range(8):
            bit = self.pinIO.value() & 0x01
            bit = (bit << i)
            byte = (byte | bit)
            self.pinClk.value(1)
            self.pinClk.value(0)
        return byte
            
    def set(self, reg, data):
        self.pinCE.value(1)
        self.write( reg )
        self.write( data )
        self.pinCE.value(0)
            
    def get(self, reg):
        self.pinCE.value(1)
        self.write( reg+1 )
        data = self.read()
        self.pinCE.value(0)
        return data

    def now(self):
        self.rtc[0] = self.bcd2dec(self.get(REG_YEAR))+2000
        self.rtc[1] = self.bcd2dec(self.get(REG_MONTH))
        self.rtc[2] = self.bcd2dec(self.get(REG_DAY))
        self.rtc[3] = self.bcd2dec(self.get(REG_WEEKDAY))
        self.rtc[4] = self.bcd2dec(self.get(REG_HOUR))
        self.rtc[5] = self.bcd2dec(self.get(REG_MINUTE))
        self.rtc[6] = self.bcd2dec(self.get(REG_SECOND))
        
    def adjust(self, day, month, year, dow, hour, minute, second ):
        # convert
        year = year - 2000
        year = self.dec2bcd(year)
        month = self.dec2bcd(month)
        day = self.dec2bcd(day)
        dow = self.dec2bcd(dow)
        minute = self.dec2bcd(minute)
        hour = hour & 0x1F
        hour = self.dec2bcd(hour)
        second = self.dec2bcd(second)
        # adjust
        self.set(REG_YEAR, year)
        self.set(REG_MONTH, month)
        self.set(REG_DAY, day)
        self.set(REG_WEEKDAY, dow)
        self.set(REG_HOUR, hour)
        self.set(REG_MINUTE, minute)
        self.set(REG_SECOND, second)

    def show(self):
        print("{} {}-{}-{} {}:{}:{}".format(
            self.rtc[3],
            self.rtc[0], self.rtc[1], self.rtc[2],
            self.rtc[4], self.rtc[5], self.rtc[6]
            ))        

# main program
rtc = DS1302()
rtc.adjust(7,7,2021, 3, 17,57,00)
while True:
    rtc.now()
    rtc.show()
    time.sleep_ms(1000)

The result is as shown in Figure 10.

(Figure. 10 Result of the code.)

Conclusion

From this article, you will find that Python programming has the same hardware accessibility as pure C++, but the execution speed may vary. However, the ease of reading and porting code to the other systems makes this language interesting. Finally, we hope that this article will be more or less useful. And have fun with programming.

If you want to talk with us, feel free to leave comments below!!

Reference

  1. DS1302 Datasheet

(C) 2020-2021, By Jarut Busarathid and Danai Jedsadathitikul
Updated 2021-10-19