Raspberry Pi PicoでPicoMite(MMBasic)を使う〜RTCの利用

# はじめに

Raspberry Pi PicoはRTC（Real Time Clock）を内蔵していますがバッテリーバックアップされていないため、時刻を合わせていても再起動時にはリセットされてしまう。また、時刻の精度も悪いようです。
ここではMMbasicでの時刻の扱い方と外部RTCの接続とその利用を試した内容を記す。

# PicoMiteの日付時刻取得と設定

PicoMiteは起動時および再起動時に時刻を2024年1月1日 0時0分0秒にセットされます。
MMBasicでは日付の情報は`DATE$`関数で取得、`DATE$=`コマンドで設定できます。また、時間は`TIME$`関数で取得、`TIME$=`コマンドで設定できます。
日時にかかわる関数、コマンドを以下に示す。

| コマンドおよび関数 | 説明|
| ----------------| ---|
| DATE$           | 内蔵クロックの日付をDD-MM-YYYY形式で取得する関数 |
| DATE\$=日付文字列      | 内蔵クロックの設定するコマンド<br>次のいずれかの形式で日付を指定する<br>DD-MM-YY[YY]、DD/MM/YY[YY]、YY[YY]-MM-DD、YY[YY]/MM/DD |
| TIME\$           | 内蔵クロックの時間をHH:MM:SS形式で取得する関数|
| TIME\$=時刻       | 内蔵クロックを設定するコマンド<br>”HH:MM:SS"の形式で指定する。MM:SSは省略でき、省略した場合は0となる。 |
| DATETIME\$(n)      | エポックタイムnに対応する日付と時刻をDD-MM-YYYY HH:MM:DDの形式で返す関数<br>現在の日付と時刻はDATETIME$(NOW)で取得できる|
| DAY\\$(date\\$)     | date\$で指定した日付の曜日を取得する関数<br>曜日は英語表記でえられる（例：Mondayなど |
| EPOCH(DATETIME\\$) | DATETIME\\$で指定した日時のエポックタイムを取得する関数<br>DATETIME\$の形式はDD-MM-YYYY HH:MM:SS、DD-MM-YY HH:MM:SS、YYYY-MM-DD HH:MM:SSのいずれか<br>現在の日時のエポックタイムはEPOCH(NOW)で取得できる |

これらのコマンドはコマンドプロンプトでも利用できる。

※エポックタイムは1970年1月1日 00:00:00 UTCからの経過秒数のこと。

## 日付と時刻の取得

現在の日付は`DATE＄`関数で、時刻は`TIME$`関数で取得でき、PRINTコマンドでコンソールに出力できる。

```BASIC
> PRINT DATE$
01-01-2024
> PRINT TIME$
00:11:14
>
```

## 日付と時刻の設定

Raspberry Pi PicoのRTCは起動時に2024年1月1日 00時00分00秒にリセットされるため正しい時刻を扱いたいときは手動で設定するか後ほど述べる外部RTCを使って自動的に設定するかのいずれかになる。
日付の設定は`DATE$=`コマンドを、時刻の設定は`TIME$=`コマンドを使う。
たとえば、日付を2025年5月8日に、時刻を13時55分30秒に設定する場合はコマンドプロンプトで次のようにコマンドを実行する。

```
> DATE$="2024/05/08"
> TIME$="13:55:30"

> PRINT DATE$,TIME$
08-05-2024      13:56:10
```


# 外部RTCの接続

起動のたびに日時を手動で設定するのは面倒な場合、外部RTCを接続すれば自動的に日時が設定されるようにすればよい。

## 使用部品

外部RTCとしてAmazonで購入した[WINGONEER 小型DS3231 AT24C32 I2Cモジュール用の高精度リアルタイムクロックモジュール,ボタン電池付き（A145）](https://amzn.to/3SwRTvn)を使用しました。このRTCはPicoMiteがサポートしているクロックチップDS3231を使用しているので扱いが簡単です。

時刻の表示は以前使ったI<sup>2</sup>C接続のOLED、[YUWENW OLEDディスプレイ 0.96インチ 2個入り OLEDモジュール I2C 128X64 4ピン ホワイト Arduino](https://amzn.to/3EXD2XQ)に対応を使用しました。

いずれの部品もI<sup>2</sup>Cで接続します。

## 配線

RTCとOLEDを下図のように配線しました。いずれのデバイスのSDAとSCLは同じピンに接続します。

| RTCおよびOLEDのピン | Picoのピン（物理ピン） |
| :----: | :-----------: |
|  SCL   |   GP14(19)    |
|  SDA   |   GP15(20)    |
|  VCC   |    3V3(36)    |
|  GND   |    GND(38)    |


![RTC-OLED_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/bcf6ed45-005c-4600-ab25-d1e70d0b6ab1.png)

# RTCに関連する設定

## I<sup>2</sup>Cの設定

PicoMiteはサポートしているOLEDやRTCなどI<sup>2</sup>Cデバイスを接続するI<sup>2</sup>CピンをOPTIONコマンドでシステム用として設定しておきます。すでに設定している場合には不要です。

今回はSDAにGP14ピンを、SCLにGP15ピンを使用するので次のコマンドをコマンドプロンプトで実行して設定します。設定済みの場合にはエラーメッセージ`Error : I2C already configured`が表示されます。

```
> OPTION SYSTEM I2C GP14,GP15	
```

SSD1306チップのOLEDを使うので次のOPTIONコマンドをコマンドプロンプトで実行します。すでに設定されている場合はエラーメッセージ`Error : Display already configured`が表示されます。

```
> OPTION LCDPANEL SSD1306I2C, LANDSCAPE
```

## 外部RTCの時刻設定

I<sup>2</sup>Cの設定ができたら外部RTCの時刻を`RTC SETTIME`コマンドで設定します。次の構文に示すように日付、時刻を順にカンマで区切って並べます。

`RTC SETTIME year, month, day, hour, minute, second`

たとえば、2025年5月8日14時34分45秒に設定し、確認するコマンドは次の通りです。

```
> RTC SETTIME 2025, 5, 8, 14, 34, 45
> print date$, time$
08-05-2025      14:34:55
> 
```

これでRaspberry Pi PicoのRTCと外部RTCの時刻が設定されます。

## 外部RTCの時刻取得

`RTC SETTIME`コマンドで時刻を設定しても再起動するとRaspberry Pi PicoのRTCはリセットされてしまう。外部RTCから時刻を取得する`RTC GETTIME`コマンドをコマンドプロンプトで実行するとRaspberry Pi PicoのRTCの時刻が更新されます。

このコマンドは手動で実行しますが次の設定によって起動時、再起動時に外部RTCから自動的に時刻を取得できます。

- サブルーチン`MM.STARTUP`に`RTC GETTIME`コマンドを加える
- コマンドプロンプトで`OPTION RTC AUTO ENABLE`コマンドを実行する
このオプション設定で起動時および毎時、RTCから自動的に時刻を読み込み設定される

RTCからの時刻同期の無効化するには`OPTION RTC AUTO DISABLE`コマンドを実行します。

# 時計的なプログラム

タイマ割り込みを使って日時のデータを読み取り、OLEDへ出力するプログラムを以下に示す。

```BASIC:RTC.bas
SetTick 1000, DClock                              ' Define priodic interruput

CLS                        

Do
  Pause 500
Loop

Sub DClock
  '　Create a date string in the format YYYY/MM/DD
  datestr$ = Mid$(Date$, 7, 4) + "/"              ' Get year
  datesrt$ = datestr$ + Mid$(Date$, 4, 2) + "/"   ' Get month
  datestr$ = datestr$ + Mid$(Date$, 1, 2)         ' Get date
  Text 0,  0, datestr$,,4                         ' Draw date string
  Text 0, 16, Day$(Date$),,4                      ' Draw day of the week
  Text 0, 32, Time$,,4                            ' Draw time
End Sub

Sub MM.STARTUP                                    ' Code to run when the program starts
  RTC GETTIME                                     ' Get clock from RTC
End Sub
```

プログラム最後のサブルーチン`MM.STARTUP`内に`RTC GETTIME`コマンドがあるので再起動時に外部RTCから日時を取得されます。

## 実行結果

![RTC-OLED.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/9a5a789d-264c-4320-83f4-849ee24064f9.jpeg)

# 補足

Raspberry Pi Pico WやPico 2 WのWi-Fiに対応したファームウェアを使えばNTPから時刻を取得して内蔵RTCの時刻を設定できる。

# 参考サイトなど

- [PicoMite User Manual](https://geoffg.net/Downloads/picomite/PicoMite_User_Manual.pdf)