RaspberryPi Pico に内蔵のRTCを Arduino IDE で使用する

# Pico は RTC（リアルタイム・クロック）を内蔵している！！

私は Arduino Nano 等に RTC（リアルタイム・クロック）モジュールを接続してましたがRaspberryPi Pico では MCUのRP2040 が RTCを内蔵しているので RTCのハードウェア、つまりIC（DS1307が有名）やモジュール（シールド。基板）は不要です！！　
システムがコンパクトになり、しかも経済的と、とても有難いことです。

　　　　　　RP2040のブロック図：　Peripheralsの中にRTCの白いボックスがあります。
![RP2040-RTCライブラリインストール0.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/4ebd2712-75bf-973a-f595-3b91957f86f4.jpeg)

このRTCを動かすには下記の３つのライブラリが必要です。私の開発環境は Windows10、Arduino IDE 1.8.15で、RaspberryPi Pico は Arduino Mbed OS RP2040 版を使用してます。
このライブラリは earlephilhower版でも動作するとのことです。

(1) RP2040_RTC   // https://www.arduino.cc/reference/en/libraries/rp2040_rtc/
(2) TimeLib          // https://github.com/PaulStoffregen/Time
(3) Timezone_Generic // https://github.com/khoih-prog/Timezone_Generic

ライブラリ(ZIPファイル)の入手とインストールを経験されている方は、この情報だけで十分かと思いますが、そうでない場合は以下の手順をご覧ください。
※重要：経験者の方も［手順７］のソースファイルの修正は必要なのでご覧ください。
　また、［手順８］動作確認のスクリーンショット、［手順９］改造もご参考まで。

```C++:手順一覧
［手順１］RP2040_RTC をダウンロードする
［手順２］TimeLib をダウンロードする
［手順３］Timezone_Generic をダウンロードする
［手順４］RP2040_RTC をインストールする
［手順５］TimeLib をインストール（手順４と同様）
［手順６］Timezone_Generic をインストール（手順４と同様）
［手順７］ソースファイルの修正
［手順８］動作確認
［手順９］改造：PCからシリアルモニタ経由で日付と時刻を設定する
```
RP2040_RTC は本家Arduinoのページ以外に Githubと作者のホームページでも公開してます。

3つのZIPファイルをダウンロードしてインストールする方法を紹介してますが、もっと簡単な方法があります。

手順１と手順４に代わって「ツール」⇒「ライブラリを管理」⇒「ライブラリマネージャ」の画面の検索ボックスに「RP2040_RTC」と入力し、検索結果で表示されるRP2040_RTCライブラリを選択します。

この方法は試してませんのでTimeLibとTimezone_Genericが同時にインストールされるのか、あるいは別途インストールする必要があるのか分かりません。

###［手順１］RP2040_RTC をダウンロードする
https://www.arduino.cc/reference/en/libraries/rp2040_rtc/
![RP2040-RTCライブラリインストール1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/efaf6a6c-b681-bad4-0a9d-ddec00a79ae2.jpeg)
この画面の下の「Releases」 の 「1.0.4(latest)」 をクリックするとRP2040_RTC-1.0.4.zip というファイルが Windows10 の場合はダウンロードフォルダに格納されます。

###［手順２］TimeLib をダウンロードする
  https://github.com/PaulStoffregen/Time
![RP2040-RTCライブラリインストール2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/6d3e4a71-f105-02ec-bc9c-a97e01b2e019.jpeg)
緑色の「Code」ボタンをクリックし、一番下の「Download ZIP」をクリックすると Time-master.zip というファイルが Windows10 の場合はダウンロードフォルダに格納されます。

###［手順３］Timezone_Generic をダウンロードする
  https://github.com/khoih-prog/Timezone_Generic
![RP2040-RTCライブラリインストール9.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/12ba2edd-db1b-5e84-5acc-c6fb88c3b19a.jpeg)
手順２と同様、緑色の「Code」ボタン⇒「Download ZIP」クリックでTimezone_Generic-main.zip というファイルが Windows10 の場合はダウンロードフォルダに格納されます。

###［手順４］RP2040_RTC をインストールする
Arduino IDE の「スケッチ」⇒「ライブラリをインクルード」⇒「.ZIP形式のライブラリをインストール」をクリックします。
![RP2040-RTCライブラリインストール3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/60d569c1-061b-f7f7-4558-a7d7868a58af.jpeg)
現れたウィンドウで先ほど格納したフォルダを指定しRP2040_RTC-1.0.4.zip ファイルをダブルクリックするとインストールされます。
![RP2040-RTCライブラリインストール4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/77f535ff-4f62-d2a7-e378-02df8b876d7c.jpeg)

###［手順５］TimeLib をインストール（手順４と同様）

###［手順６］Timezone_Generic をインストール（手順４と同様）

###［手順７］ソースファイルの修正
(1) Arduino IDE の「ファイル」⇒「スケッチ例」⇒「RP2040_RTC」⇒「Time」⇒「RP2040_RTCTime」をクリックすると、スケッチのウィンドウが表示されます。
![RP2040-RTCライブラリインストール5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/ba54e90f-1c4f-b7fa-8d06-d10840987952.jpeg)
(2) ■■■■重要■■■■
　　プログラムに #include < TimeLib.h > という行を追加します。
![RP2040-RTCライブラリインストール6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/b2a8be4d-dc44-08ff-2272-18152a8e4c13.jpeg)

###［手順８］動作確認
(1) 「ツール」⇒「ボード」⇒「ボードマネージャー」⇒「Arduino Mbed OS RP2040」⇒「Raspberry Pi Pico」を選択
![RP2040-RTCライブラリインストール7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/fc08cc86-8362-75c1-aea3-703e90652abd.jpeg)
(3) [⇒]ボタン（マイコンボードに書き込む）をクリック
(4) Picoへの書込みが終了したら、画面右上の虫眼鏡のボタン（シリアルモニタ）をクリックするとシリアルモニタに下記のように表示されます。
![RP2040-RTCライブラリインストール8.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/729ece02-36f4-553b-8216-39220ccbff5e.jpeg)

###［手順９］改造：PCからシリアルモニタ経由で日付と時刻を設定する

【スケッチの変更】
新たに set_datetime_fromPC() という関数を作成しました。
これを void loop() から呼び出すようにします。

```C++:変更前
void loop()
{ 
  displayRTCTime();
}
```

```C++:変更後
void loop()
{ 
  set_datetime_fromPC();
  displayRTCTime();
}
//--------------------------------------------------------------------
// set Date & Time from PC (Serial Monitor)
//     setting parameter:  "t yyyy mmdd w hhmmss"
//     w：Day of The Week（0:Sun 1:Mon 2:Tue 3:Wed 4:Thr 5:Fri 6:Sat）
//     ex："t 2021 0907 2 235900" = 2021/09/07 Tue 23:59:00
void set_datetime_fromPC()
{
  int16_t year ;
  int8_t  month;
  int8_t  day  ;
  int8_t  dotw ;  // Day of The Week
  int8_t  hour ;
  int8_t  min  ;
  int8_t  sec  ;

  if(Serial.available()) {
    if (Serial.read() == 0x74) {    // "t"=0x74
      Serial.println("t command received");
      Serial.read();
      year   = (Serial.read() & 0x0F) *1000;
      year  += (Serial.read() & 0x0F) *100;
      year  += (Serial.read() & 0x0F) *10;
      year  += (Serial.read() & 0x0F) ;
      Serial.read();
      month  = (Serial.read() & 0x0F) *10;
      month += (Serial.read() & 0x0F);
      day    = (Serial.read() & 0x0F) *10;
      day   += (Serial.read() & 0x0F);
      Serial.read();
      dotw   = (Serial.read() & 0x07);    // Day of The Week
      Serial.read();
      hour   = (Serial.read() & 0x0F) *10;
      hour  += (Serial.read() & 0x0F);
      min    = (Serial.read() & 0x0F) *10;
      min   += (Serial.read() & 0x0F);
      sec    = (Serial.read() & 0x0F) *10;
      sec   += (Serial.read() & 0x0F);

      if ((month >= 1 ) && (month <= 12 ) &&
          (day >= 1 )   && (day <= 31 ) &&
          (dotw >= 0 )  && (dotw <= 6 ) &&
          (hour >= 0 )  && (hour <= 23 ) &&
          (min >= 0 )   && (min <= 59 ) &&
          (sec >= 0 )   && (sec <= 59 )) {
        datetime_t pcTime = { year, month, day, dotw, hour, min, sec };
        rtc_set_datetime(&pcTime);
        Serial.print(pcTime.year); 
        Serial.print("/"); 
        Serial.print(pcTime.month);
        Serial.print("/");
        Serial.print(pcTime.day);
        Serial.print(" ");
        Serial.print(pcTime.dotw);
        Serial.print(" ");
        Serial.print(pcTime.hour);
        Serial.print(":");
        Serial.print(pcTime.min);
        Serial.print(":");
        Serial.println(pcTime.sec);
       } else {
         Serial.println("Illegal data! Cannot set the clock.");      
       }
    }
  }
}
```

【使用法】
シリアルモニタの送信データ入力ボックスに下記フォーマットで入力し「送信」ボタンをクリックします。

"t yyyy mmdd w hhmmss"（最初と最後の「"」は入力する必要はありません）

「w」は曜日 (Day of The Week) 
　0:日Sun 1:月 2:火 3:水 4:木 5:金 6:土

例："t 2021 0907 2 235900" ⇒ 2021/09/07 火曜 23:59:00

入力した値の妥当性をチェックしていて間違ったデータを送信するとエラーメッセージをシリアルモニタに表示します。但し、チェックは厳密でなく、月に関係なく日は1～31ならOKになります。

例えば 0931（9月31日）と入力してもエラーメッセージは出ません。これをそのままRTCにセットすると10月1日になり、同様に日付を0230（2月30日）と入力すると3月2日になりました。ちょっと賢いですね。
![RP2040-RTCライブラリ改造後の動作.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/ff46afac-db35-dc9a-caf2-4a79ec76e2c5.jpeg)

# 余談：その他のサンプルプログラム（スケッチ）
手順７のスケッチ例で「RP2040_RTC」の下には下記６つのプログラム（スケッチ）があります。

```C++:
RP2040_RTC_Alarm
RP2040_RTC_Alarm_Ethernet
RP2040_RTC_Alarm_WifiNINA

RP2040_RTC_Time
RP2040_RTC_Time_Ethernet
RP2040_RTC_Time_WifiNINA
```
「Time」は現在時刻を表示し、「Alarm」は指定した時間になると指定した関数（コールバック関数）を呼び出します。

「Ethernet」と「WifiNINA」は、インターネットに接続してNTP サーバからUTCタイムを取得して時刻合わせをします。「Ethernet」は W5x00 イーサネットシールドを使用し、「WifiNINA」は、WifiNINA を搭載した NANO_RP2040_CONNECT 用です。

### NINAとは？
NINAは、u-bloxというスイスの会社の NINA-W10 シリーズ(NINA-W101, NINA-W102)というWi-Fi/Bluetooth接続ができるdual core 32bit MCU モジュールのことです。下記のArduino ボードに搭載されているようです。
・Arduino UNO WiFi Rev.2
・Arduino NANO 33 IoT
・Arduino MKR 1010
・Arduino MKR VIDOR 4000 WiFi
・Arduino Nano RP2040 Connect

参考：スイッチサイエンスのページでArduino MKR WiFi 1010が紹介されてます。
　　　https://www.switch-science.com/catalog/7384/

### Arduino Nano RP2040 Connect
RP2040にU-bloxのWi-Fi／Bluetoothモジュール NINA-W102を搭載したこのボードは、2021年5月に発売されました。他に、6軸IMU（慣性計測ユニット）、マイクロフォン、RGB LED なども搭載してラズパイPicoよりも小型のサイズです。

550円と格安のラズパイPicoに比べるとちょっと高価ですが、これだけのものを積んでいるのでコスパは良く、お買い得かもしれません。

参考： Arduino＋Raspberry Pi——「RP2040」を搭載した「Arduino Nano RP2040 Connect」を発表
https://fabcross.jp/news/2021/20210521_arduinonano_rp2040connect.html
![RP2040-RTCライブラリインストール11.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834831/edc1fafd-d718-1135-dadb-91d52ba551a7.jpeg)

# おまけ（というかゴミ）

ところで全くど～～でもＥことだけど、なんか気になる「NINA」ってなに？
（あっ、回文だ。になてなに。小学生レベル）
これ↓かなぁ？？？　気象庁：よくある質問（エルニーニョ/ラニーニャ現象）
https://www.data.jma.go.jp/gmd/cpd/data/elnino/learning/faq/faq4.html