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)