In this article we look at a Raspberry Pi Pico RTC Module based on the DS1302 chip
The Raspberry Pi Pico out of the box does not have RTC capabilities so with the addition of this
Here is a picture of the purchased module
Lets look at the DS1302 chip
The DS1302 chip contains a real-time clock/calendar and 31 bytes of static RAM. It communicates with a microprocessor via a simple serial interface.
The real-time clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The end of the month date is automatically adjusted for months with fewer than 31 days, including corrections for leap year.
The clock operates in either the 24-hour or 12-hour format with an AM/PM indicator.Interfacing the DS1302 with a microprocessor is simplified by using synchronous serial communication. Only three wires are required to communicate with the clock/RAM: CE, I/O (data line), and SCLK (serial clock).
Data can be transferred to and from the clock/RAM 1 byte at a time or in a burst of up to 31 bytes. The DS1302 is designed to operate on very low power and retain data and clock information on less than 1μW.
Specifications
Operating voltage | 3.3V |
---|---|
Backup battery voltage | 2.3V ~ 5.5V |
Operating temperature | -40°C ~ +85°C |
Power consumption | 100nA (keeping Clock and data) |
Product page
There are 2 products on the page, the DS1302 board costs about $6
Code
This is the test example
This can be found in the link below in the github repo
from machine import Pin import framebuf import time from machine import * DS1302_REG_SECOND = (0x80) DS1302_REG_MINUTE = (0x82) DS1302_REG_HOUR = (0x84) DS1302_REG_DAY = (0x86) DS1302_REG_MONTH = (0x88) DS1302_REG_WEEKDAY= (0x8A) DS1302_REG_YEAR = (0x8C) DS1302_REG_WP = (0x8E) DS1302_REG_CTRL = (0x90) DS1302_REG_RAM = (0xC0) class DS1302: def __init__(self, clk, dio, cs): self.clk = clk self.dio = dio self.cs = cs self.clk.init(Pin.OUT) self.cs.init(Pin.OUT) def DecToHex(self, dat): return (dat//10) * 16 + (dat%10) def HexToDec(self, dat): return (dat//16) * 10 + (dat%16) def write_byte(self, dat): self.dio.init(Pin.OUT) for i in range(8): self.dio.value((dat >> i) & 1) self.clk.value(1) self.clk.value(0) def read_byte(self): d = 0 self.dio.init(Pin.IN) for i in range(8): d = d | (self.dio.value()<<i) self.clk.value(1) self.clk.value(0) return d def getReg(self, reg): self.cs.value(1) self.write_byte(reg) t = self.read_byte() self.cs.value(0) return t def setReg(self, reg, dat): self.cs.value(1) self.write_byte(reg) self.write_byte(dat) self.cs.value(0) def wr(self, reg, dat): self.setReg(DS1302_REG_WP, 0) self.setReg(reg, dat) self.setReg(DS1302_REG_WP, 0x80) def start(self): t = self.getReg(DS1302_REG_SECOND + 1) self.wr(DS1302_REG_SECOND, t & 0x7f) def stop(self): t = self.getReg(DS1302_REG_SECOND + 1) self.wr(DS1302_REG_SECOND, t | 0x80) def Second(self, second = None): if second == None: return self.HexToDec(self.getReg(DS1302_REG_SECOND+1))%60 else: self.wr(DS1302_REG_SECOND, self.DecToHex(second%60)) def Minute(self, minute = None): if minute == None: return self.HexToDec(self.getReg(DS1302_REG_MINUTE+1)) else: self.wr(DS1302_REG_MINUTE, self.DecToHex(minute%60)) def Hour(self, hour = None): if hour == None: return self.HexToDec(self.getReg(DS1302_REG_HOUR+1)) else: self.wr(DS1302_REG_HOUR, self.DecToHex(hour%24)) def Weekday(self, weekday = None): if weekday == None: return self.HexToDec(self.getReg(DS1302_REG_WEEKDAY+1)) else: self.wr(DS1302_REG_WEEKDAY, self.DecToHex(weekday%8)) def Day(self, day = None): if day == None: return self.HexToDec(self.getReg(DS1302_REG_DAY+1)) else: self.wr(DS1302_REG_DAY, self.DecToHex(day%32)) def Month(self, month = None): if month == None: return self.HexToDec(self.getReg(DS1302_REG_MONTH+1)) else: self.wr(DS1302_REG_MONTH, self.DecToHex(month%13)) def Year(self, year = None): if year == None: return self.HexToDec(self.getReg(DS1302_REG_YEAR+1)) + 2000 else: self.wr(DS1302_REG_YEAR, self.DecToHex(year%100)) def DateTime(self, dat = None): if dat == None: return [self.Year(), self.Month(), self.Day(), self.Weekday(), self.Hour(), self.Minute(), self.Second()] else: self.Year(dat[0]) self.Month(dat[1]) self.Day(dat[2]) self.Weekday(dat[3]) self.Hour(dat[4]) self.Minute(dat[5]) self.Second(dat[6]) def ram(self, reg, dat = None): if dat == None: return self.getReg(DS1302_REG_RAM + 1 + (reg%31)*2) else: self.wr(DS1302_REG_RAM + (reg%31)*2, dat) ds = DS1302(Pin(2),Pin(3),Pin(4)) # CLK GPIO2 # DAT GPIO3 # RST GPIO4 ds.DateTime() # Return: [2021, 1, 31, 7, 11, 10, 56] #ds.Year() #Get today's year #ds.Month() #Get today's month #ds.Day() #Get today's date #ds.Weekday() #Get the current day of the week #ds.Hour() #Get the current hour #ds.Minute() #Get the current minute #ds.Second() #Get the current second # You can add a number to the above function to set the time # E.g #ds.Year(2021) #Set this year to 2021 #ds.Day(2)#Set today as the 2nd ds.Year(2021) ds.Month(3) ds.Day(21) ds.Weekday(3) ds.Hour(11) ds.Minute(23) ds.Second(45) while 1: print(ds.Year(),ds.Month(),ds.Day(),ds.Weekday(),ds.Hour(),ds.Minute(),ds.Second()) time.sleep(1)