JUGEMテーマ:電子工作

RTC8564をESP32のmicropythonで使う

 

ESP32のRTCをそのまま使った場合、電源引っこ抜くと
時刻忘れてしまうので、外部のRTCが必要になる場合がある。

 

□回路

 


SCLとSDAをつなぐだけ

 

□ソース説明

 

 なんとなく、気分でclassにしてみた。

 

・初期化

 ピンの22,27でi2c通信します。
 SoftI2Cを作ったらクラスへ渡します。

 

 I2C_ADDR_RTC8564NB = 0x51
 pin22 = machine.Pin(22, machine.Pin.IN, machine.Pin.PULL_UP)
 pin27 = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_UP)
 i2cbus = SoftI2C(scl=pin22, sda=pin27, freq=100000)
 
 rtc8564 = RTC8564(i2cbus)

 

・ESP32のRTCから読んで8564へ書き込み

 

 rtc8564.setDatetimeESP32toRTC()

 

・8564のRTCから読んでからESPへ書き込み

 

 rtc8564.setDatetimeRTCtoESP32()

 

・8564のRTCから読んで表示

 

 buf = rtc8564.makeDatetimeStrRTC()
 print("8564 time ="+buf)
 

□ソース
 

from machine import SoftI2C, Pin
import utime
import machine
import time
import struct

class RTC8564 :
    def __init__(self, i2cbus):
        self.i2cbus = i2cbus
    
    # ------------------------
    # BCD変換
    # ------------------------
    def to_bcd(self, bin):
        keta1 = bin % 10
        keta2 = int(bin / 10)
        r = b''
        r += struct.pack('B', keta2 * 16 + keta1)
        return r
    
    # ----------------------------------------
    # RTC8564にセット
    # ----------------------------------------
    def setDatetimeRTC(self, year, month, days, hour, minute, second):
        # stop rtc
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 0, b'¥x20')
    
        # year
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 8, self.to_bcd(year - 2000))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 7, self.to_bcd(month))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 5, self.to_bcd(days))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 4, self.to_bcd(hour))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 3, self.to_bcd(minute))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 2, self.to_bcd(second))
    
        # start rtc
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 0, b'¥x00')
    
        return True
    
    # ------------------------------------
    # ESP32からRTC8564にセット
    # ------------------------------------
    def setDatetimeESP32toRTC(self):
        now_time = time.time()
        t = time.localtime(now_time)
    
        # stop rtc
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 0, b'¥x20')
    
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 8, self.to_bcd(t[0] - 2000))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 7, self.to_bcd(t[1]))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 5, self.to_bcd(t[2]))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 4, self.to_bcd(t[3]))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 3, self.to_bcd(t[4]))
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 2, self.to_bcd(t[5]))
    
        # start rtc
        self.i2cbus.writeto_mem(I2C_ADDR_RTC8564NB, 0, b'¥x00')
    
        return True
    
    
    # ------------------------------------
    # RTC8564からESP32にセット
    # ------------------------------------
    def setDatetimeRTCtoESP32(self):
        t = self.getDatetimeTupleRTC()

        rtc = machine.RTC()
        rtc.datetime((t[0] + 2000, (t[1]), (t[2]), 0, (t[3]), (t[4]), (t[5]), 0))
        
        return True
    
    # --------------------------------------
    # RTC8564から取得してタプルで返す
    # --------------------------------------
    def getDatetimeTupleRTC(self):
        sec_h, sec_l     = self.readFromI2CRTC8564NB(2)
        min_h, min_l     = self.readFromI2CRTC8564NB(3)
        hour_h, hour_l   = self.readFromI2CRTC8564NB(4)
        day_h, day_l     = self.readFromI2CRTC8564NB(5)
        month_h, month_l = self.readFromI2CRTC8564NB(7)
        year_h, year_l   = self.readFromI2CRTC8564NB(8)
    
        return year_h*10+year_l, month_h*10+month_l, day_h*10+day_l, hour_h*10+hour_l, min_h*10+min_l, sec_h*10+sec_l
    
    # ------------------------------------
    # 8564メモリ読み出し
    # ------------------------------------
    def readFromI2CRTC8564NB(self, mem_address):
        result = self.i2cbus.readfrom_mem(I2C_ADDR_RTC8564NB, mem_address, 1)[0]
    
        bitmasks_l = [0b00001111, 0b00001111, 0b00001111, 0b00001111, 0x00000111, 0b00001111, 0b00001111]
        bitmasks_h = [0b00000111, 0b00000111, 0b00000011, 0b00000011, 0x00000000, 0b00000001, 0b00001111]
    
        # lower digit
        l_digit = result & bitmasks_l[mem_address-2]
    
        # upper digit
        h_digit = result >> 4
        h_digit = h_digit & bitmasks_h[mem_address-2]
    
        return h_digit, l_digit
    
    # -----------------------------------------------
    # RTC8564からYYYYMMDDHHMMSS形式で取得
    # -----------------------------------------------
    def makeDatetimeStrRTC(self):
        sec_h   , sec_l     = self.readFromI2CRTC8564NB(2)
        min_h   , min_l     = self.readFromI2CRTC8564NB(3)
        hour_h  , hour_l   = self.readFromI2CRTC8564NB(4)
        day_h   , day_l     = self.readFromI2CRTC8564NB(5)
        month_h , month_l = self.readFromI2CRTC8564NB(7)
        year_h  , year_l   = self.readFromI2CRTC8564NB(8)
    
        datetime_str = "20%d%d/%d%d/%d%d %d%d:%d%d:%d%d" %(year_h, year_l, month_h, month_l, day_h, day_l, hour_h, hour_l, min_h, min_l, sec_h, sec_l)
    
        return datetime_str
    
#
# 変数
#
I2C_ADDR_RTC8564NB = 0x51
pin22 = machine.Pin(22, machine.Pin.IN, machine.Pin.PULL_UP)
pin27 = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_UP)
i2cbus = SoftI2C(scl=pin22, sda=pin27, freq=100000)

buf = i2cbus.scan()
for id in buf:
    print("scan:"+str(id))

rtc8564 = RTC8564(i2cbus)

# -----------------------------------------
# ESPのRTCに書き込み
# -----------------------------------------
def SetTime(yyyy, mm, dd, h, m, s) :
    time_value = utime.mktime((yyyy, mm, dd, h, m, s, 00, 00)) #+  ( 9 * 60 * 60 )
    t = utime.localtime(time_value)
    yyyy = t[0]    #yyyy
    mm   = t[1]    #mm
    dd   = t[2]    #dd
    h    = t[3]    #hh
    m    = t[4]    #mm
    s    = t[5]    #ss
    rtc = machine.RTC()
    rtc.init((yyyy, mm, dd, 0, h, m, s, 0))

#set RTC time
rtc8564.setDatetimeRTC(2023, 2, 1, 12, 0, 0)
#読み込み
buf = rtc8564.makeDatetimeStrRTC()
print("8564 time ="+buf)

#set ESP time
SetTime(2001, 1, 11, 9, 0, 0)
#読み込み
t = utime.localtime()
stime = "%d/%02d/%02d %02d:%02d:%02d %01d %03d" % (t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7])
print("esp time ="+stime)

#ESP-->RTC
#rtc8564.setDatetimeESP32toRTC()
##読み込み
#buf = rtc8564.makeDatetimeStrRTC()
#print("8564 time ="+buf)

#RTC-->ESP
rtc8564.setDatetimeRTCtoESP32()
#読み込み
t = utime.localtime()
stime = "%d/%02d/%02d %02d:%02d:%02d %01d %03d" % (t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7])
print("esp time ="+stime)


while True :
    str = rtc8564.makeDatetimeStrRTC()
    print(str)
    utime.sleep(1)