稼働中

マイクロビット(e_17)DS3231 リアルタイムクロックモジュール(1)

RCT DS3231 日時カレンダ

DS3231を搭載したリアルタイムクロック(RTC)モジュールを使ってみようと思います。このRTCモジュールにはAT24C32 32Kビット(4Kバイト)のEEPROMも付いています。I2C通信で接続します。※以後は単にDS3231、モジュールと記す場合があります。

DS3231 AT24C32モジュールの外観を下図に示します。リチウムコイン電池は充電可能なLIR2032を使うそうです。けっこう価格が高いです。安価なリチウムコイン電池CR2032を使う場合はダイオードかチップ抵抗を外して充電できないようにする必要があります。※コイン電池をセットしなくても動作の確認はできます。
AT24C32のスレーブアドレスはモジュールに抵抗追加で変更できるようです。※詳細はモジュールのデータシートなど参照ください。
RTC外観2 RTC外観2

接続例

DS3231のデータシートをみると3.0Vで動作するので、micro:bitから電源供給できます。I2C通信で接続します。スレーブアドレスを調べると、RTC_DS3231が 0x68(104)、 EEPROM_AT24C32が 0x57(84) です。

RTCアドレス

接続は以下の図のようにしました。
micro:bitのクロック信号SCL(pin19)、データ信号SDA(pin20)とDS3231モジュールのSCL、SDAと接続します。スレーブアドレスは0x68(104)です。

RTC接続例

以下は実体写真です。

RTC実体写真

日時カレンダの設定

データーシートをみると日時カレンダを設定するレジスタがあります。0x00~0x06です。下の表の形式に合わして日時などを書きこむだけです。
例えば、15時のデータを24h表示する場合には、0b0001_0101(0x15)を書きこむことになります。hexでみると分かりやすいかもしれません。

レジスタマップ
※データシートからの引用に赤枠を付けてます。

スクリプト

カレンダ日時の設定と設定状態の確認をします。スクリプトは以下のようにしました。ただし時間は24時間表示、曜日は日曜を’0’にしました。


from microbit import *
#RTC DS3231 0x68(104) EEPROM : 0x50~0x57
adr_rtc=0x68

# read register
def read_reg(reg,num):          # reg:読込むレジスタのアドレス、num:読込むバイト数
    buf=bytearray(1)
    buf[0]=reg
    i2c.write(adr_rtc,buf)      # 読込み開始レジスタのアドレスを送信
    sleep(5)
    r_reg=i2c.read(adr_rtc,num) # 設定バイト数のデータを読出し
    sleep(5)
    return r_reg                # 読出したデータを返す

# min sec date day month year>> register 
def d2reg(dat):                 # 秒、分、日付、曜日、月、年のレジスタに送るデータ
    s= (dat//10 << 4) | (dat%10) 
    return s
def h24reg(dat):                # 時 24H形式でレジスタに送るデータ
    #p= (0<<6)|(dat//10 << 4) | (dat%10)
    p= (dat//10 << 4) | (dat%10) 
    return p
def reg2d(dat):                 # 秒、分、日付、曜日、月、年のレジスタデータを10進に戻す
    H_bit=dat >> 4
    L_bit=dat & 0x0f
    d_num=H_bit*10+L_bit
    #return H_bit,L_bit,d_num
    return d_num
# register >> 24h
def reg24h(dat):                # 時間のレジスタデータを10進に戻す
    H_bit=(dat >> 4)&0b0011
    L_bit=dat & 0x0f
    d_num=H_bit*10+L_bit
    return d_num

## ---------------------------------------------------
# 2018/5/30 23:30:45 Wed
#d=([2021, 11, 29, 20, 47, 00, 1]) この形式でカレンダ日時を入力する

def set_ds3231(d_set):      # カレンダ日時データを書込むデータに変換する
    d=d_set
    #06h year
    yy=d2reg(d[0]-2000)
    #05h Mounth
    mo=d2reg(d[1])
    #04h date
    dd=d2reg(d[2])
    #02h hour
    hh=h24reg(d[3])
    #01h min
    mm=d2reg(d[4])
    #00h sev
    ss=d2reg(d[5])
    #03h weekday
    ww=d2reg(d[6])

    set_data=[ss,mm,hh,ww,dd,mo,yy]     # レジスタ順に変換したデータを並べる
    #### set_dataに書き込み開始アドレス0x00を追加してバイトアレイ化する
    #### write regista addr 
    st_reg=0
    wr_data=[st_reg,ss,mm,hh,ww,dd,mo,yy]
    set_buf=bytearray(8)                # データが8個あるので
    # k << bytearrayの位置
    k=0
    for x in wr_data:
        set_buf[k]=x
        k=k+1
    i2c.write(adr_rtc,set_buf)      # データを送信(書込む)する
    sleep(5)
    print('## SET DONE ##')

def read_ds3231():                # カレンダ日時レジスタから読出し、設定値を確認
    wday=['sun','mon','tue','wed','thu','fri','sat'] # 表示用 日曜が0
    #00h - 0x07h RTC-Data
    rtc_data=read_reg(0x00,7)       # 関数へ 0x00から7バイト読込む
    #print( list(rtc_data) )
        
    r_yy=reg2d(rtc_data[6])+2000
    #05h Mounth
    r_mo=reg2d(rtc_data[5])
    #04h date
    r_dd=reg2d(rtc_data[4])
    #02h hour
    r_hh=reg24h(rtc_data[2])
    #01h min
    r_mm=reg2d(rtc_data[1])
    #00h sec
    r_ss=reg2d(rtc_data[0])
    #03h weekday
    r_ww=reg2d(rtc_data[3])
    r_wd=wday[r_ww]
    print('DS3231 DATA READ')
    print(r_yy,'/',r_mo,'/',r_dd,' ',r_wd,' ',r_hh,':',r_mm,':',r_ss)

# ここに時計カレンダ設定値を記載すればよい
# 2021/11/30 11:30:45 thu ( 0:sun 1:mon 2:tue 3:wed...)
s=([2021, 12, 10, 15, 33, 15, 3])
print("DS3231 set_data",s)
# 確認だけならset_ds3231をコメントアウトする
set_ds3231(s)
read_ds3231()

実行結果


>>> %Run 1130_ds3231_day_time_set_0b.py
DS3231 set_data [2021, 12, 10, 15, 33, 15, 3]   # 設定するカレンダ日時のデータ(入力値)
## SET DONE ##
DS3231 DATA READ
2021 / 12 / 10   wed   15 : 33 : 15             # 設定されたデータの確認

カレンダの日時設定が出来たようです。

まとめ

DS3231モジュールのカレンダ日時を作成したスクリプトで設定できました。これでmicro:bitビットでリアルタイムが確認できると思います。