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