13.picoでRTCサンプル動作 Arduino
13.picoでRTCサンプル動作 Arduino
picoの内蔵時計(RTC)のサンプルスケッチ2つを動作させます。
picoにはバッテリバックアップがないので、電源を切ると時間が失われます。よって起動時にRTCを更新する必要があります。
ライブラリをインストール
RP2040_RTChttps://www.arduino.cc/reference/en/libraries/rp2040_rtc/
の、RP2040_RTC Library
https://github.com/khoih-prog/RP2040_RTC
を使用します。
Arduino-IDE > スケッチ > ライブラリをインクルード > ライブラリを管理... > "pico RTC"で検索
RP2040_RCT by Khoi Hoang Ver1.1.0 をインストール > Install all は no protocol でエラーになったので > Install 'RP2040_RTC' only > 閉じる
RP2040_RTCライブラリ
Raspberry Pi Pico C/C++ SDK https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf の、p195 4.1.21.3. Function Documentation と
p260 4.2.17.3. Function Documentation より
Typedef
typedef void(* rtc_callback_t )(void);typedef struct{
int16_t year; // 年(0..4095)
int8_t month; // 月(1..12) 1:1月
int8_t day; // 日(1..28,29,30,31)
int8_t dotw; // 曜日(0..6) 0:日曜日
int8_t hour; // 時(0..23)
int8_t min; // 分(0..59)
int8_t sec; // 秒(0..59)
} datetime_t;
rtc_disable_alarm
void rtc_disable_alarm(void);アクティブならRTCアラームを無効にします
rtc_enable_alarm
void rtc_enable_alarm(void);非アクティブならRTCアラームを有効にします
rtc_get_datetime
bool rtc_get_datetime(datetime_t *t);RTCから現在時刻を取得
t:現在のRTC時刻を受け取るdatetime_t構造体へのポインタ
戻り値:true=日時が有効, false=RTCが実行されていない
rtc_init
void rtc_init(void);RTCシステムを初期化
rtc_running
bool rtc_running(void);RTCは実行していますか?
rtc_set_alarm
void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback);RTCがユーザー提供のコールバックを呼び出す将来時間を設定
t:アラームを発生させる未来の時刻を格納した datetime_t構造体へのポインタを指定。-1に設定された値は、マッチングされない。
user_callback:アラームが発生したときに呼び出す rtc_callback_t へのポインタ。
rtc_set_datetime
bool rtc_set_datetime(datetime_t *t);RTCを指定時間に設定
t:datetime_t構造体へのポインタには、設定する時間が含まれています
戻り値:true=設定されている場合, false=渡された日時が無効
datetime_to_str
void datetime_to_str(char *buf, uint buf_size, const datetime_t *t);datetime_t構造体を文字列に変換。使い勝手が悪い
buf:生成された文字列を受け入れる文字バッファ
buf_size:渡されたバッファのサイズ
t:変換される日時
スケッチ1
Arduino-IDE > ファイル > スケッチ例 > (カスタムライブラリのスケッチ例) RP2040_RTC > Time > RP2040_RTC_Time.inoスケッチには夏時間のライブラリがありましたが、
khoih-prog/Timezone_Generic
https://github.com/khoih-prog/Timezone_Generic
Timezone(夏時間)を削除し、UTC時刻のみの表示に変更しました。スケッチ内で時刻を設定し、10秒ごとに時刻を表示します。なぜか、1番最初の時刻がでたらめです。
スケッチ
"RP2040_RTC_Time.ino"
// RP2040_RTC_Time.ino
// RP2040で内蔵RTCを使用する ESP8266-WiFi、ESP8266-ATモジュール/シールドなど
// https://github.com/khoih-prog/RP2040_RTC
// バッテリーバックアップがないので、電源断で時刻は失われます。よって、起動ごとにNTP時刻を取得必要
// typedef struct{
// int16_t year; // 0..4095
// int8_t month; // 1..12, 1 is January
// int8_t day; // 1..28,29,30,31 depending on month
// int8_t dotw; // 0..6, 0 is Sunday
// int8_t hour; // 0..23
// int8_t min; // 0..59
// int8_t sec; // 0..59
// } datetime_t;
#include "defines.h" // 添付 定義
datetime_t currTime = {2022, 1, 21, 5, 5, 0, 0}; // 2022年1月21日金曜日5:00:00
void printDateTime(time_t t, const char *tz) { // 時刻表示関数(タイムゾーン付)
char buf[32]; // 表示用時刻保存
sprintf(buf, "%d/%.2d/%.2d(%s) %.2d:%.2d:%.2d %s", year(t), month(t), day(t),
dayShortStr(weekday(t)), hour(t), minute(t), second(t), tz); // 時刻文字列作成
Serial.println(buf); // 時刻表示
}
void setup() {
Serial.begin(115200); // システムモニタ初期設定
while (!Serial && millis() < 5000); // モニタを開いてなく起動5秒以内なら待つ
delay(200); // 0.2秒待つ
Serial.print(F("\nRP2040_RTC_Time.ino開始\nボード名= ")); // 表示
Serial.println(BOARD_NAME); // "RASPBERRY_PI_PICO"と表示
Serial.println(RP2040_RTC_VERSION); // "RP2040_RTC v1.1.0"と表示
rtc_init(); // RTCシステムを初期化
rtc_set_datetime(&currTime); // RTCを指定時間に設定
}
void loop() {
static unsigned long displayRTCTime_timeout = 0; // 10秒後のmS
// static変数は 最初に呼出された時にのみ作成と初期化
#define DISPLAY_RTC_INTERVAL 10000L // 10秒ごと表示 デフォルト60
if ((millis() > displayRTCTime_timeout) || (displayRTCTime_timeout == 0)) {
// timeout時間後 or timeout=0(ループ最初の開始時刻)なら
rtc_get_datetime(&currTime); // RTCから現在時刻を取得
DateTime now = DateTime(currTime); // DateTimeライブラリ
time_t utc = now.get_time_t(); // time_t型式に変換?
printDateTime(utc, "UTC"); // time_t形式で時刻表示関数へ ここのみ
displayRTCTime_timeout = millis() + DISPLAY_RTC_INTERVAL; // 次の10秒後の時間設定
}
}
defines.h
// defines.h
// 内蔵RTCを使用するRP2040用 ESP8266-WiFi,ESP8266-ATモジュール/シールドなど
// https://github.com/khoih-prog/RP2040_RTC
#ifndef defines_h // 定義がされてなければ
#define defines_h // 定義する
#include <RP2040_RTC.h> // RP2040_RTCを使用
#endif // defines_h
* フラッシュメモリ(1Mbyte)を、スケッチが4%使用。RAM(262kbyte)を、グローバル変数が2%使用、ローカル変数で254kbyte使用可能。(1000byte=1kで計算)スケッチ2
Arduino-IDE > ファイル > スケッチ例 > (カスタムライブラリのスケッチ例) RP2040_RTC > Alarm > RP2040_RTC_Alarm.ino夏時間は削除しました。スケッチ内で時刻を設定します。10秒(DISPLAY_RTC_INTERVAL)ごとに時刻表示し、各分の05秒時(ALARM_AT_SECONDS)にアラーム処理(ここでは時刻表示)します。一番最初の時刻表示が合っていません。
スケッチ
"RP2040_RTC_Alarm.ino" ("defines.h"は同じ)
// RP2040_RTC_Alarm.ino
// 内蔵RTCを使用するRP2040ベースのボード用
// ESP8266-WiFi,ESP8266-ATモジュール/シールドなど
// https://github.com/khoih-prog/RP2040_RTC
// バッテリーバックアップがないので、電源断で時刻は失われます。起動時にNTP時刻を取得必要
// typedef struct{
// int16_t year; // 0..4095
// int8_t month; // 1..12, 1 is January
// int8_t day; // 1..28,29,30,31 depending on month
// int8_t dotw; // 0..6, 0 is Sunday
// int8_t hour; // 0..23
// int8_t min; // 0..59
// int8_t sec; // 0..59
// } datetime_t;
#include "defines.h" // 添付 定義
datetime_t currTime = {2022, 1, 21, 5, 5, 0, 0};// 2022/1/21 Fri 05:00:00 時計時刻
datetime_t alarmT; // アラーム時刻
volatile bool alarmTriggered = false; // アラームでない
#define ALARM_AT_SECONDS 5 // 5秒時にアラーム
#define ALARM_REPEAT_FOREVER true // 繰返しアラーム,false:1回アラーム
bool setAlarmDone = false; // アラーム内容未設定
void rtcCallback() { // アラーム時動作関数
alarmTriggered = true; // アラームになった
}
void set_RTC_Alarm(datetime_t *alarmTime) { // アラーム時間と動作関数の設定
rtc_set_alarm(alarmTime, rtcCallback);// RTCが設定のコールバックを呼出す将来時間を設定
}
void printDateTime(time_t t, const char *tz) { // 時刻表示関数(タイムゾーン付)
char buf[32]; // 時刻表示文字用
sprintf(buf, "%d/%.2d/%.2d(%s) %.2d:%.2d:%.2d %s", year(t), month(t), day(t),
dayShortStr(weekday(t)), hour(t), minute(t), second(t), tz); // 時刻文字列作成
Serial.println(buf); // 時刻表示
}
void setup() {
Serial.begin(115200); // システムモニタ初期設定
while (!Serial && millis() < 5000); // モニタを開いてなく起動5秒以内なら待つ
delay(200); // 0.2秒待つ
Serial.print(F("\nRP2040_RTC_Alarm.ino開始\nボード名= ")); // 表示
Serial.println(BOARD_NAME); // "RASPBERRY_PI_PICO"と表示
Serial.println(RP2040_RTC_VERSION); // "RP2040_RTC v1.1.0"と表示
rtc_init(); // RTCシステムを初期化
rtc_set_datetime(&currTime); // RTCを指定時間に設定
}
void displayTime() { // 表示設定関数
rtc_get_datetime(&currTime); // RTCから現在時刻を取得
DateTime now = DateTime(currTime); // DateTimeライブラリ
time_t utc = now.get_time_t(); // time_t型式に変換?
printDateTime(utc, "UTC"); // time_t形式で時刻表示関数へ ここのみ
}
void loop() {
static unsigned long displayRTCTime_timeout = 0; // 10秒後のmS
// static変数は 最初に呼出された時にのみ作成と初期化
#define DISPLAY_RTC_INTERVAL 10000L // 10秒ごと表示 デフォルト60
if ((millis() > displayRTCTime_timeout) || (displayRTCTime_timeout == 0)) {
// timeout時間後 or timeout=0(ループ最初の開始時刻)なら
displayTime(); // 表示設定関数へ(開始時と10秒ごと)
displayRTCTime_timeout = millis() + DISPLAY_RTC_INTERVAL; //次の10秒後の時間設定
}
if (!setAlarmDone) { // アラーム内容未設定なら
#if ALARM_REPEAT_FOREVER // 繰返しアラームの設定なら
rtc_get_datetime(&alarmT); //RTCから現在時刻を取得
alarmT.min = alarmT.hour = alarmT.day = -1; // アラームマッチング外
alarmT.dotw = alarmT.month = alarmT.year = -1; // アラームマッチング外
alarmT.sec = ALARM_AT_SECONDS; // アラーム秒代入
set_RTC_Alarm(&alarmT); // アラーム設定関数へ
Serial.print("繰返しアラーム設定秒= "); // 表示
Serial.println(ALARM_AT_SECONDS); // アラーム秒表示
#else // 1回アラームの設定なら
rtc_get_datetime(&alarmT); // RTCから現在時刻を取得
if (ALARM_AT_SECONDS > alarmT.sec) // 設定値が現在以降なら
alarmT.sec = ALARM_AT_SECONDS; // アラームを設定値に設定
else {
alarmT.sec = ALARM_AT_SECONDS; // アラームを設定値に設定するが
alarmT.min += 1; // 1加算 次の分
}
set_RTC_Alarm(&alarmT); // アラーム設定関数へ
Serial.print("1回アラームを設定秒= "); // 表示
Serial.println(ALARM_AT_SECONDS); // アラーム秒数表示
#endif
setAlarmDone = true; // アラーム内容設定済
}
if (alarmTriggered) { // アラームになったら
alarmTriggered = false; // アラームトリガー解除
Serial.println("Alarm ↓"); // 表示
displayTime(); // 表示設定関数へ(アラーム時刻)
}
}
* フラッシュメモリ(1Mbyte)を、スケッチが4%使用。RAM(262kbyte)を、グローバル変数が2%使用、ローカル変数で254kbyte使用可能。(1000byte=1kで計算)