MicroPython的午睡(96) STM32版、曜日表現、Thonnyとマニュアル相違?

Joseph Halfmoon

今回はコマケー話です。STM32版のRTCに関して納得いかない部分があったので書いておきます。Day of Week、曜日の話です。MicroPythonマニュアルページを見ると曜日は月曜始まりで1から7の筈なのだけれど、手元のMicroPythonは0から6、ズレているのだけれども動いているみたいだし。どうなんだろ。

※「MicroPython的午睡」投稿順 Indexはこちら

ST Microelectronics社製Nucleo-F401REボード上で使用しているSTM32版MicroPythonについてはこちら

ドキュメント上のRTCの曜日の扱い

STM32系マイコンはカレンダ機能つきのRTC(実時間時計)を内蔵しており、年月日、時分秒(8ビットのサブ秒も)に加えて曜日もサポートしています。勿論アラームしかけたりもできるのですが、今回はアラームには触りませぬ。

まずはSTM32マイコンの「日本語参考資料」からカレンダの曜日の桁の説明部分を引用させていただきます。RTCstm32

 

上記のように3ビットで曜日を表し、月曜が1、日曜が7で、0は禁止となってます。

今回使用しているSTM32版のMicroPythonは、pyboard互換のpybモジュールと、machineモジュールの両方でRTCをサポートしています。pybモジュールの日時読み出し関数の記述を引用させていただきます。RTClib

day of week と書くのがメンドかったのか、weekdayという表現になってますが、1~7で1が月曜です。ここまでSTM32のマニュアルとも矛盾はありません。

今回試用のMicroPythonスクリプト

上記を踏まえ、今回以下のようなMicroPythonスクリプトをSTM32F401REマイコン搭載、Nucleo-F401REボードに書き込んで走らせてみました。書き込みは愛用のThonny IDEを使用してです。

#STM32F401RE: RTC
import pyb
import stm
import time

rtc = pyb.RTC()

def printDateTime():
    tn = rtc.datetime()
    print("{0}/{1}/{2} {3:02d}:{4:02d}:{5:02d}".format(tn[0], tn[1], tn[2], tn[4], tn[5], tn[6]))
    print("Weekday={0}".format(tn[3]))
    print("RTC_DR =0x{0:08x}".format(stm.mem32[stm.RTC+stm.RTC_DR]))

def printRTCinfo():
    print("{0:08x}".format(rtc.info()))

def printRTCcalibration():
    print("Calibration value: {0}".format(rtc.calibration()))

def main():
    print("STM32F401RE RTC test.")
    while True:
        printDateTime()
        printRTCinfo()
        printRTCcalibration()
        time.sleep(10)
    # Normal End

if __name__ == "__main__":
    main()
Thonny IDEのRTC初期化サービスとスクリプトの実行結果

マイコンのRTCの初期化は、ESP32のように簡単にネットワークから時刻を引っ張ってこれる機種を除くと面倒です。しかしThonny IDEを開発に使っている場合、Thonny IDEを実行しているホストにMicroPythonボードを接続するとRTCを自動初期化(ホストの時刻と同期した時刻に設定してくれているみたい)してくれます。当然、そのボード上のMicroPythonがRTCオブジェクトをサポートしていなければなりませんが。

よって接続すればカレンダと現在時刻を読み取る上記のスクリプトは即実行可能です。こんな感じ。RTC_Tue

 

 

ちゃんと現在時刻が読み取れているみたい。初期化サービス成功しているね。しかし、黄色のマーカ部分、Day of Week(pybマニュアルにあわせてWeekdayと記載)が1になってないかい。今日は火曜日だぜ。マニュアルでは1は月曜だった筈。この値がRTCのレジスタの値を直接反映していることは下のRTC_DRレジスタの読み取り値を調べると確認できます。ビット15..ビット13は、001となっているので、そのまま。

ううむ、マニュアルとは1ズレてます。たった1だが、月曜と火曜じゃエライ違いだ。

ThonnyIDEでは0~6

ThonnyIDE側では「確信」をもって0~6を曜日に割り当てているらしいことが以下の文書からわかります。

Thonny IDE  Version history (CHANGELOG.rst)

上記のCHANGELOGの2021年6月25日の条から1行引用させていただきます。

Use 0..6 for weekday when synchronizing RTC via machine, #1868

0 始まりの数字を代入しているみたいです。ただ、via machineという記述に引っかかります。STM32版MicroPythonの場合、pyb モジュールと machine モジュールの両方からRTCオブジェクトにアクセス可能です。各種ボードに対応しているThonnyはより一般的なmachineモジュールを使って初期化している筈。もしかしてpyb と machineで1ズレているのでは?

淡い期待のもとで pyb.RTC を machine.RTC に書き換えてみましたが結果は同じでした。トホホ。

ただ、以下のpybモジュールのRTCオブジェクトの記述

クラス RTC — リアルタイムクロック(pyb)

には、はっきり 1..7という記述があるのですが、以下のmachineモジュール側の記述を読むと

クラス RTC — リアルタイムクロック(machine)

weekdayフィールドは0始まりとも、1始まりとも書いてないのであります。微妙。この記述の違いに秘密?がある。

さらに考えると、

    • ThonnyIDEは、各種のMicroPythonボードをサポートしている
    • RP2040、micro:bit、ESP32など複数のボードは、それぞれインタプリタの書き込みからサポートしている
    • pyboard版は明示的な項目なし、Generic扱い
    • 当方で勝手ビルドしているSTM32版もGeneric扱い

pyboardとその子孫のSTM32版はSTM32マイコンの仕様から1始まりになるべきだけれども、それ以外のボードで0始まりの機種があり、ThonnyIDEの自動初期化値はそちらに合わせてある?と想像するとなんとなく納得がいきます。

0から1へは更新されたが。。。

しかし、0が書き込まれるどうなんだろ、STM32のハード的に更新されないんじゃ?RTCtst2

上記のように曜日フィールドが0でも、日付が変わると1に繰り上がりました。禁止ってドユコト?おっと、6の次が7になるのか、0に戻るのかは調べてないっす。お間抜け。これはまた今度だが、確かめないとな。

その上、手元のボードは8時間ほどRTCを動かしただけで数分も誤差がありました。RTCとして使うにはキャリブレーション必須のようです。STM32マイコンにはRTCクロックのキャリブレーション機能があるので、それも使ってみますか。

RTC、簡単なようで一筋縄でいかんな。

MicroPython的午睡(95) STM32版、ハードウエアCRC32演算器の試用 へ戻る

MicroPython的午睡(97) STM32版、RTC、日曜は7、月曜は1 へ進む