06.T-Watch S3 plusで時刻設定テスト(手動)
06.T-Watch S3 plusで時刻設定テスト(手動)
現在時刻(2026/月/日 時:分)を設定します。ほとんどは前回と同じです。2026年は固定です。
スケッチ
// 現在時刻セット画面
// examples/others/observer/lv_example_observer_3.c 参照
#include <LilyGoLib.h> // LilyGoLib 0.1.0(最新)を使用
#include <LV_Helper.h> // LVGL 9.2.2(固定)を使用
static lv_subject_t month_subject; // 月 値が変わると、登録コールバックが呼ばれます
static lv_subject_t day_subject; // 日
static lv_subject_t hour_subject; // 時
static lv_subject_t minute_subject; // 分
static lv_subject_t time_subject; // 上4つが入るグループ
static lv_subject_t *time_group_array_subject[] = { &month_subject, &day_subject, &hour_subject, &minute_subject }; // グループにする
const char *month_options =
"1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12"; // 月 1-12
const char *day_options = // 日 1-31
"1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31";
const char *hour_options = // 時 0-23
"0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23";
const char *minute_options = // 分 0-59
"0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59";
int32_t nowMonth, nowDay, nowHour, nowMinute; // set_btnで引き渡す月&日&時&分
static void time_observer_cb(lv_observer_t *observer, lv_subject_t *subject) { // ローラーの値をlabelに表示
int32_t month = lv_subject_get_int(lv_subject_get_group_element(subject, 0)) + 1;
int32_t day = lv_subject_get_int(lv_subject_get_group_element(subject, 1)) + 1;
int32_t hour = lv_subject_get_int(lv_subject_get_group_element(subject, 2));
int32_t minute = lv_subject_get_int(lv_subject_get_group_element(subject, 3));
// lv_subject_get_int( )は、整数Subjectの現在の値を取得(Subjectへのpointer)、戻り値:現在の値
// lv_subject_get_group_element( )は、
// Subject Groupのリストから要素を取得(Group型のSubjectへのpointer,取得する要素のインデックス)
// 戻り値:リスト内のインデックス付Subjectへのpointer インデックスが範囲外の場合はNULL
nowMonth = month; // set_btnをクリックしたら引き渡す 月
nowDay = day; // 日
nowHour = hour; // 時
nowMinute = minute; // 分
lv_obj_t *label = (lv_obj_t *)lv_observer_get_target(observer);
// Observerのターゲットを取得(Observerへのpointer)、戻り値:保存されたターゲットへのpointer
lv_label_set_text_fmt(label, "2026/%" LV_PRId32 "/%" LV_PRId32 " %" LV_PRId32 " : %02" LV_PRId32, month, day, hour, minute); // ローラーの値
}
static void set_btn_clicked_event_cb(lv_event_t *e) { // set_btnを押したら呼出される関数
lv_obj_t *set_btn = lv_event_get_target_obj(e);
// イベントの元のターゲットobjを取得(イベント記述子へのpointer)、戻り値:event_codeの元のターゲットへのpointer
Serial.printf("2026/%d/%d %2d:%02d", nowMonth, nowDay, nowHour, nowMinute); // シリアルモニタに年/月/日 時:分 を表示
}
static void cxl_clicked_event_cb(lv_event_t *e) { // cxl_btnを押したら
// そのまま時計画面に戻る予定
}
void setup() {
Serial.begin(115200); // シリアルモニタの通信速度
instance.begin(); // LilyGoLibを初期化
beginLvglHelper(instance); // LVGLを初期化
lv_task_handler();
instance.setBrightness(100); // 明るさ0-255
lv_subject_init_int(&month_subject, 2); // 初期値 3月(1からスタートなので-1する)
lv_subject_init_int(&day_subject, 14); // 初期値 15日(1からスタートなので-1する)
lv_subject_init_int(&hour_subject, 12); // 初期値 12時
lv_subject_init_int(&minute_subject, 30); // 初期値 30分
//整数型のSubjectを初期化(Subjectへのpointer,初期値)
lv_subject_init_group(&time_subject, time_group_array_subject, 4);
// グループ型サブジェクトを初期化(グループ型サブジェクトへのpointer,
// 他のサブジェクトアドレスのリスト,list[]内の要素数)
// キャンセルボタン ------------------------------
lv_obj_t *cxl_btn = lv_button_create(lv_screen_active()); // cxl_btnを作成
lv_obj_set_pos(cxl_btn, 2, 5); // btnの位置
lv_obj_t *cxl_label = lv_label_create(cxl_btn); // cxl_btnにlabelを作成
lv_obj_set_style_text_font(cxl_label, &lv_font_montserrat_24, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_label_set_text(cxl_label, "Cancel"); // labelのtextを設定
// ラベル ------------------------------
lv_obj_t *time_label = lv_label_create(lv_screen_active()); // time_labelを作成
lv_obj_set_style_text_font(time_label, &lv_font_montserrat_28, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_subject_add_observer_obj(&time_subject, time_observer_cb, time_label, NULL);
// ウィジェットのサブジェクトにオブザーバーを追加(サブジェクトへのポインタ,
// 通知コールバック,ウィジェットへのpointer,オプションのユーザーデータ)
// 戻り値:新しく作成されたオブザーバーへのpointer
// ウィジェットが削除されると、オブザーバーはサブジェクトから自動的に登録解除。
// 注:この方法で作成されたオブザーバーは呼出さない。
// これらのオブザーバーは、次のいずれかの方法でのみクリーンアップしてください。
// lv_observer_remove()ウィジェットを削除するか、
// すべてのオブザーバーを適切に分離して削除するには、lv_subject_deinit() を呼出す。
lv_obj_set_pos(time_label, 0, 60); // ラベルの位置 70,20
// セットボタン ------------------------------
lv_obj_t *set_btn = lv_button_create(lv_screen_active()); // set_btnを作成
lv_obj_set_pos(set_btn, 120, 5); // btnの位置
lv_obj_set_width(set_btn, 115); // btn幅
lv_obj_add_event_cb(set_btn, set_btn_clicked_event_cb, LV_EVENT_CLICKED, NULL); // set_btnを押したらコールバック関数へ
lv_obj_t *set_label = lv_label_create(set_btn); // btnにlabelを作成
lv_obj_set_style_text_font(set_label, &lv_font_montserrat_24, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_label_set_text(set_label, " Set"); // labelのtextを設定
// 月ローラー ------------------------------
lv_obj_t *month_roller = lv_roller_create(lv_screen_active()); // 画面に翌日用ローラーを作成
lv_roller_set_options(month_roller, month_options, LV_ROLLER_MODE_INFINITE); // 永久スクロール
lv_roller_bind_value(month_roller, &month_subject); // 関連付
lv_obj_set_pos(month_roller, 0, 105); // rollerの位置
lv_obj_set_style_text_font(month_roller, &lv_font_montserrat_28, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_obj_set_width(month_roller, 60); // 幅
// 日ローラー ------------------------------
lv_obj_t *day_roller = lv_roller_create(lv_screen_active()); // 画面に翌日用ローラーを作成
lv_roller_set_options(day_roller, day_options, LV_ROLLER_MODE_INFINITE); // 永久スクロール
lv_roller_bind_value(day_roller, &day_subject); // 関連付
lv_obj_set_pos(day_roller, 60, 105); // rollerの位置
lv_obj_set_style_text_font(day_roller, &lv_font_montserrat_28, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_obj_set_width(day_roller, 60); // 幅
// 時ローラー ------------------------------
lv_obj_t *hour_roller = lv_roller_create(lv_screen_active()); // 画面に時用ローラーを作成
lv_obj_add_flag(hour_roller, LV_OBJ_FLAG_FLEX_IN_NEW_TRACK);
// 1つ以上のフラグを設定(objへのpointer, 設定する値のOR演算)
// LV_OBJ_FLAG_FLEX_IN_NEW_TRACK:このアイテムで新しいFlexトラックを開始
lv_roller_set_options(hour_roller, hour_options, LV_ROLLER_MODE_INFINITE); // 永久スクロール ...22,23,0,1,...
// ローラーのオプションを設定(ローラーobjへのpointer,\nで区切られた文字列,
// or LV_ROLER_MODE_NORMAL LV_ROLLER_MODE_INFINITE)
// LV_ROLLER_MODE_NORMAL:ローラーはオプションの最後で停止
// LV_ROLLER_MODE_INFINITE:ローラーは永久にスクロール
lv_roller_bind_value(hour_roller, &hour_subject);
// 整数SubjectをRollerの値に関連付(Rollerへのpointer,Subjectへのpointer)
// 戻り値:新しく作成されたObserverへのpointer
lv_obj_set_pos(hour_roller, 120, 105); // rollerの位置
lv_obj_set_style_text_font(hour_roller, &lv_font_montserrat_28, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_obj_set_width(hour_roller, 60); // 幅
// 分ローラー ------------------------------
lv_obj_t *min_roller = lv_roller_create(lv_screen_active()); // 画面に分用のローラーを作成
lv_roller_set_options(min_roller, minute_options, LV_ROLLER_MODE_INFINITE); // 永久スクロール 上と同様
lv_roller_bind_value(min_roller, &minute_subject); // 関連付け 上と同様
lv_obj_set_pos(min_roller, 180, 105); // rollerの位置
lv_obj_set_style_text_font(min_roller, &lv_font_montserrat_28, 0); // 英数文字サイズ24,28,32,36,40,44,48
lv_obj_set_width(min_roller, 60); // 幅
}
void loop() {
lv_task_handler();
delay(5); // 5mS待つ
}
flash memory(3.1Mbyte)のうち、スケッチが31%使用。RAM(327kbyte)のうち、global変数が7%使用、local変数で301kbyte使用可能。(1000byte=1kbyteで計算)LilyGoLib 0.1.0
FFat 3.3.5
FS 3.3.5
Wire 3.3.5
SensorLib 0.3.3
SPI 3.3.5
RadioLib 7.1.0
TinyGPSPlus 1.1.0
ESP_I2S 3.3.5
XPowersLib 0.3.1
lvgl 9.2.2
esptool v5.1.0
