Arduino UNO R4 の RTC のズレを解消

Arduino UNO R4の7回目です。
前回、Arduino UNO R4のRTC(Real Time Clock)で作った時計が、1日で10分弱も進む件を何とかしたいです。
では、それ、やってみよう!
RTCの前回の記事は、以下をクリック。

前回の状況

Arduino UNO R4のUSB端子に、ダイソーのモバイルバッテリにつないで翌日まで動作させました。
すると、翌日、8分30秒ほど進んでいました。他の情報をネットで探してみると、Arduino UNO R4 Minimaは1日で10分以上ずれることもあるようです。

対策として考えたのは、
1 外部水晶振動子を増設する
2 「LOCO ユーザトリミングコントロールレジスタ(LOCOUTCR)」で修正する
です。

そこで、手軽に試せるR4互換機の「コアボード」に、同じスケッチを書き込んで試しました。
「コアボード」には、純正R4にはない外部水晶振動子(メイン:16 MHz、サブ:32.768 kHz)が搭載されています。

「コアボード」のクロック周りの配線
純正R4のクロック周り

ところが、外部水晶振動子を搭載されている「コアボード」で検証したら、15分以上進んでしまいました。
(Arduino UNO R4の互換機については、以下をクリック)

解決策を探せ

ルネサス社のHP

まず、MCUの製造会社であるルネサス社のフォーラムを覗いてみました。
かふぇルネ」です。

こちらのHPで「RTC」に関する書き込みを調べましたが、思ったような書き込みは見つかりませんでした。
(このフォーラムは製造現場の方が多く参加している様です。通常の出荷商品で、外部水晶振動子を搭載しない製品などあり得ないでしょう。)

唯一、参考になったのが、「クロック発生回路について」です。
MCUが「RL78」での質問ですが、内蔵オシレータの周波数精度が±1%であることや、外部サブ・クロック(32.768 kHz)を取り付けて、HALTモードにすると1 μA以下の動作電流になることなどの記載が有りました。
しかし、「RA4M1」で内蔵オシレータを使用すると、RTCが極端にズレることの解決策は見つかりません。

ArduinoのHP

ArduinoのHPにあるUNO R4の「フォーラム」です。

内蔵クロックから外部水晶振動子への切り替えは「Frequency counter for UNO R4 wanted」のpost#11などに記載があります。
まずは、HOCO((内蔵)高速オンチップオシレータ)から外部メインクロックに切り替えてみましょう。
Githubの「Arduino_UNO_R4_RA4M1_HOCO_to_XTAL_switch」に、HOCOから外部水晶振動子に切り替えるスケッチの例があります。

また、「R4 RTC」などで検索してみました。
いくつか質問が出ていました。
特に「UNO R4 WiFi RTC runs fast by about 1 second per minute」(UNO R4 WIFIのRTCが1分で1秒も進んじゃうよ。)と「Can we fix the RTC?」(RTCなんとかならないの?)などは、そのままの質問ですね。

内蔵メインオシレータから外部水晶振動子への切り替え

HOCO((内蔵)高速オンチップオシレータ)から外部水晶振動子に切り替えるには、色々な制約があるようです。
このGithubの説明文によると、

1 USBの動作はHOCOのままに残す。(ここの周波数が変わると、パソコンと繋がらなくなりますね。)
2 外部水晶振動子は、4.0 ~ 12.5 MHzであること。(あれ?「コアボード」は16 MHzだけど)
3 発振器を切り替えるには、タイミングや動作状態などの細かな制約がある。

とりあえず、このスケッチをLCDとRTCで時計を作ったスケッチに組み込んで、メインオシレータに切り替えて様子を見てみます。
1時間ほどたってから、時間を見てみます。

すでに大きく進んでいます。
ダメですね。

その他のHOCOに関する書き込みを確認します。
Uno R4 schematic」のpost#25には、HOCOについての細かな記載があります。
データシート(RA4シリーズ クイックデザインガイド)によると、HOCOの精度は、「24MHz、32MHz、48MHz、または64MHzで動作し、標準精度は±2%またはそれ以上」とありますが、実際のR4では48 MHzで動作しているそうです。
関連するGithubの記載内容では、筆者の実測ですが、1/4にした12 MHzの状態で内部クロックの周波数は「11.96 MHz」であったとのことです。

また、「RA4シリーズ クイックデザインガイド」の「5. クロック発生回路」を確認すると、メインクロックの主な用途にRTCが含まれておらず、サブクロック(32.768 kHz)にのみRTCが書かれています。


個人のブログを確認してみても、メインとサブのクロックは別だとの記載がありました。
てっきり、RTC用の32.768 kHzはメインクロックを分周して作っており、メインを外部水晶振動子に切り替えればRTCの精度も向上すると思っていたのですが違うようです。

内蔵サブオシレータから外部水晶振動子への切り替え

UNO R4 WiFi RTC runs fast by about 1 second per minute」のpost#5に「RTC.cpp」についての記載が、post#14にはRTCの自動補正用のレジスタ「RADJ」に関する記載があります。

「RTC.cpp」(2023年7月時点での記載)では、「.clock_source = RTC_CLOCK_SOURCE_LOCO」の記載を「RTC_CLOCK_SOURCE_SUBCLK」と書き換えることで外部サブクロックに切り替えることが出来ると記載されていますが、現在の「RTC.cpp」を見てみると、その記載は削除されています。
Arduino UNO R4のライブラリ内の各種ファイルは、GitHubで「ArduinoCore-renesas」で公開されています。
その中の「ArduinoCore-renesas/libraries/RTC/src/RTC.cpp」で現在の「RTC.cpp」も公開されていますが、「History」で以前のファイルも見ることが出来ます。

以前のファイルの「C33: use 32Khz crystal as RTC source」を見ると、447行目に以下の記載がありました。
どうやら、外部水晶振動子が搭載されている場合は、「RTC.cpp」でクロック・ソースを書き換える予定だったようです。
(「https://arduino.atlassian.net/browse/HWH33-204」には、ログインできませんでした。)

447    // TODO: change me to RTC_CLOCK_SOURCE_SUBCLK when capacitors are mounted
448    // https://arduino.atlassian.net/browse/HWH33-204
449    // Fixes counting time in VBAT mode on H33
450    // Leave as is for Santiago
451    .clock_source = RTC_CLOCK_SOURCE_LOCO,

次に、自動補正用のレジスタ「RADJ」についてです。
RTCの自動補正用レジスタの「RADJ」が使えれば、大きくズレるLOCO(内蔵クロック)の自動補正が出来ると思ったのですが、データシート(Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編)の「24.2.21 時計誤差補正レジスタ(RADJ)」では、外部発振器を使用したときのみ有効で、LOCOでは使用できないそうです。(残念!)

「RADJ」による自動補正がLOCOでは使用できないことが分かったので、RTCのズレを修正するには、外部サブクロックを追加するしかないことが分かりました。

純正のR4では、NCとなっているpin6とpin7に32.768 kHzの外部水晶振動子を取り付けます。
幸いなことに、手元にある「コアボード」にはサブクロックが搭載されているので、すぐに確認できます。

あまりやりたくはありませんが、「RTC.cpp」を書き換えます。

455行目にある「define RTC_CLOCK_SOURCE RTC_CLOCK_SOURCE_LOCO」を「define RTC_CLOCK_SOURCE RTC_CLOCK_SOURCE_SUBCLK」と書き換えます。

時計(RTC)の動作確認

「RTC.cpp」を書き換えた状態で、外部水晶振動子が搭載されている「サブボード」にLCDを接続して、以前使ったスケッチを書き込みます。
エラーも出ずにコンパイルと転送が終了して、時間を表示しました。動作は問題ないようです。
この状態で、ダイソーのモバイルバッテリをつないで1日放置します。

翌日です。
24時間経ちました。

結果は、成功です!
セイコーの電波時計と1日経過しても、1秒のズレもありません。(19時00分37秒です。)

トランジスタ技術の2024年1月号の第2部 第1章「プログラムはほぼAI生成! Uno R4温度計時計の製作」でも解決していなかったRTCのズレが、「RTC.cpp」の一部を書き換えるだけで解決しました。

今後の予定

今回はズレを解消する検証がメインで、簡単にLOCO(内蔵オシレータ)を外部水晶振動子に切り替えるために「RTC.cpp」を書き換えましたが、本来はスケッチ内でレジスタの操作をするべきですね。

RTCで時計を作るスケッチでのクロック切り替えの修正は、今後の課題とします。

コメント