10.T-WatchのDeepSleepからの復帰


10.T-WatchのDeepSleepからの復帰

説明

注意:この機種は技適が通っていません。中国で動作確認したスケッチとメモを日本で整理してブログ発信しています。

常時表示では数時間しかバッテリーがもたないので、なるべくoffするようにしました(変更1)。しかし、アラーム設定時刻が消えてしまうので、電源offの前にアラーム時刻をflash(ROM)に保存するようにしました。(変更2)

再起動直後の画面
現在時刻と再起動前に設定したアラーム設定時刻が表示されています。

変更1

時計画面を表示していたら20秒後にDeep Sleepします。時計画面以外では 電源はoffしません。電源off時は、ダブルクリック or 傾きで復帰します。以前の "05.T-Watchのセンサー復帰" を組合わせました。

変更2

再起動で復帰時に現在時刻はRTCで表示できますが、アラーム設定時刻は消えてしまうので、almHとalmMを設定時にflash(ROM)に保存して、起動時に呼出します。
SPIFFSを使用しますが、
Arduino-IDE > ツールには、"..... 3.6MB SPIFFS"
と表示されていて、使用できる事がわかります。

変更内容

almHとalmMは、設定したら
・flashWrite();
の関数に書込み。起動したら
・flashRead();
の関数から読込みます。

void appalarmSet() で時計画面へ戻る前に
・flashWrite();
を追加します。

void setup() に
・SPIFFS.format();
・SPIFFS.begin();
・flashRead();
を追加します。SPIFFS.format() は、1回目のみ実行させます。ここではプログラム動作はしません。2回目からは注釈にして使用します。

関数一覧

このスケッチで作成した関数です。
void SetFont() // Font等初期化関数
void printBT() // バッテリー残量表示関数
void RTCread() // RTCのデータを読込む
void SetBMA423() // 3軸加速度センサーのオプション設定と機能を有効
void Dsleep() // 復帰はext1でdeep sleep
void flashRead() // flashのデータ読込関数
void flashWrite() // flashにデータ書込関数
void appWatch() // Mcase=0 時計表示
void appMenu() // Mcase=10 アイコンメニュー
void appalarmSet() // Mcase=1 アラーム時刻設定
void apptimeSet() // Mcase=2 時刻合わせ 手動
void app3() // Mcase=3 未作成
void app4() // Mcase=4 未作成
void app5() // Mcase=5 未作成
void app6() // Mcase=6 未作成
void app7() // Mcase=7 未作成
void app8() // Mcase=8 未作成
void appReturn() // Mcase=9 時計画面へ戻る
void setup() // setup
void loop() // loop

スケッチ

"icon9.h"も同一ホルダに必要です

// 10touchWakeup.ino
// 時計画面なら20秒後にdeep sleep、ダブルクリックor傾きで復帰
// almHとalmMは再起動時に消えるので、flashに保存
#include "icon9.h"  // 3x3アイコンpng1枚
// 1:目覚まし時計,2:時計+手,3:袋,4:時計+wifi
// 5:太陽,6:歯車,7:トレイ,8:風車,9:戻る

#define LGFX_AUTODETECT                 // 機種の自動認識
#include <LovyanGFX.hpp>                // ヘッダをinclude
#include <LGFX_AUTODETECT.hpp>          // クラス"LGFX"を用意
static LGFX lcd;                        // LGFXのインスタンスを作成
#define LILYGO_WATCH_2020_V3            // T-Watch2020v3を使用
#define LILYGO_WATCH_HAS_MOTOR          // 振動モータを使用
#include <LilyGoWatch.h>                // LilyGoWatchを使用
#include <FS.h>                         // ファイル操作
#include <SPIFFS.h>                     // Flashにデータ保存
TTGOClass *ttgo;                        //
AXP20X_Class *power;                    // 電源管理 AXP202
PCF8563_Class *rtc;                     // PCF853 RTC(Real-Time Clock)
BMA *sensor;                            // 3軸加速度センサー BMA423
extern const unsigned char img[];       // 表示png画像1枚
uint8_t Mcase = 0;                      // メニュー番号
int16_t x, y;                           // タッチ位置変数
int8_t mmonth, dday, week, hh, mm, ss;  // 時分秒等の変数 0-255
int16_t yyear;                          // 年は16bit整数 0-65535
int8_t almH, almM;                      // アラーム時分
char dayWeek[7][4] = { "土", "日", "月", "火",
                       "水", "木", "金" };  // 曜日
uint8_t timeSetNo = 1;                      // 1:年,2:月,3:日,4:時,4:分
uint8_t touchNo;                            // 1:+1,2:SET,3:-1,10:+10,30:-10
uint32_t Stime, Ctime, period = 20 * 1000;  //開始時間,現在時間,判定時間(mS)
String flashF = "/flashData.txt";           // flashに保存するtxtファイル
int8_t flashD[2];                           // flashに保存する変数 almH,almM

void SetFont() {                            // Font等初期化関数
  ttgo = TTGOClass::getWatch();             // ttgoに略します
  ttgo->begin();                            // 本体の初期化
  lcd.init();                               // LCDの初期化
  lcd.setRotation(2);                       // 画面回転 0-3 (4-7で上下反転)
  lcd.setBrightness(128);                   // バックライト輝度 0-255(実際は256通りの輝度ではない)
  lcd.fillScreen(TFT_BLACK);                // 全画面黒
  lcd.setFont(&fonts::lgfxJapanGothic_28);  // 固定幅ゴシック体 8,12,16,20,24,28,32,36,40
  lcd.setTextColor(TFT_GREEN, TFT_BLACK);   // (緑字,黒地)
  lcd.setTextSize(1);                       // 文字サイズの倍数
  lcd.setTextWrap(true);                    // 自動折返し
}

void printBT() {                                // バッテリー残量表示関数
  lcd.setCursor(185, 0);                        // カーソル位置
  lcd.setTextSize(0.7);                         // 文字サイズ(倍)
  uint8_t per = power->getBattPercentage();     // 電池%測定
  if (power->isChargeing()) {                   // 充電中の時
    lcd.setTextColor(TFT_CYAN, TFT_BLACK);      // (水字,黒地)
    lcd.print("充");                            // 画面表示
  } else {                                      // 充電中でない時
    lcd.print(" ");                            // 画面表示
    if (per <= 20) {                            // 0-20%時
      lcd.setTextColor(TFT_RED, TFT_BLACK);     // (赤字,黒地)
    } else if (per <= 40) {                     // 21-40%
      lcd.setTextColor(TFT_YELLOW, TFT_BLACK);  // (黄字,黒地)
    } else if (per <= 80) {                     // 41-80%時
      lcd.setTextColor(TFT_GREEN, TFT_BLACK);   // (緑字,黒地)
    } else {                                    // 81-100%時
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);   // (白字,黒地)
    }
  }
  lcd.printf("%3d%%", per);  // 電池%表示
  lcd.setTextSize(1);        // 文字サイズを戻す
}

void RTCread() {                             // RTCのデータを読込む
  RTC_Date tnow = ttgo->rtc->getDateTime();  // 現在のデータを取得
  yyear = tnow.year;                         // 年
  mmonth = tnow.month;                       // 月
  dday = tnow.day;                           // 日
  hh = tnow.hour;                            // 時
  mm = tnow.minute;                          // 分
  ss = tnow.second;                          // 秒

  uint16_t yearA = yyear;  //ツェラーの公式 年月日から曜日weekを求める
  uint8_t monthA = mmonth;
  if (monthA < 3) {
    monthA += 12;
    yearA--;
  }
  uint16_t year1 = yearA / 100;
  uint16_t year2 = yearA % 100;
  week = (dday + (int)(26 * (monthA + 1) / 10) + year2 + (int)(year2 / 4)
          + (5 * year1) + (int)(year1 / 4))
         % 7;
}

void SetBMA423() {                                 // 3軸加速度センサーのオプション設定と機能を有効
  Acfg cfg;                                        // BMA423パラメータの構造
  cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;           // BMA423の出力データレート(0_78~1600)
  cfg.range = BMA4_ACCEL_RANGE_2G;                 // BMA423の±重力範囲(2~16)
  cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;          // BMA423の平均化サンプル数2^x x=4の時2^4=16サンプルの平均値
  cfg.perf_mode = BMA4_CONTINUOUS_MODE;            // BMA423のフィルター性能モード 平均化無し
  sensor->accelConfig(cfg);                        // BMA423で上記の設定
  sensor->enableAccel();                           // BMA423を有効
  sensor->enableFeature(BMA423_STEP_CNTR, false);  // 歩数割込機能isStepCounterを無効にする
  sensor->enableFeature(BMA423_TILT, true);        // 傾き割込機能isTiltを有効にする
  sensor->enableFeature(BMA423_WAKEUP, true);      // クリック割込機能isDoubleClickを有効にする
}

void Dsleep() {                                // 復帰はext1でdeep sleep
  ttgo->displaySleep();                        // 画面とタッチをスリープする
  power->setPowerOutPut(AXP202_LDO3, false);   // LDO3出力off 使用禁止
  power->setPowerOutPut(AXP202_LDO4, false);   // LDO4出力off MAX98357A Audio
  power->setPowerOutPut(AXP202_LDO2, false);   // LCD_VDD出力off バックライト
  power->setPowerOutPut(AXP202_EXTEN, false);  // (この電源チャンネルは不使用 使用禁止)
  power->setPowerOutPut(AXP202_DCDC2, false);  // (この電源チャンネルは不使用)
  //esp_sleep_enable_ext0_wakeup((gpio_num_t)BMA423_INT1, HIGH);        // 外部復帰はext0を使用の時
  esp_sleep_enable_ext1_wakeup(GPIO_SEL_39, ESP_EXT1_WAKEUP_ANY_HIGH);  // BMA423外部復帰はext1を使用
  esp_deep_sleep_start();                                               // deep sleep開始
}

void flashRead() {                                       // flashのデータ読込関数
  fs::File flashF = SPIFFS.open("/flashData.txt", "r");  // ファイルを読込モードで開く
  if (flashF) {                                          // ファイルが開けば
    for (uint8_t i = 0; i < sizeof(flashD); i++) {       // すべて読込む
      flashD[i] = flashF.read();                         // 読込んだデータを配列に保存
    }
    flashF.close();    // ファイルをclose
    almH = flashD[0];  // almHに代入
    almM = flashD[1];  // almMに代入
  } else {             // ファイルが開かないなら
    almH = 0;          // 0にする
    almM = 0;          // 0にする
  }
}

void flashWrite() {                                      // flashにデータ書込関数
  fs::File flashF = SPIFFS.open("/flashData.txt", "w");  // ファイルを書込モードで開く
  if (!flashF) {                                         // ファイルが開けなければ
    lcd.println("Flash 書込 Error");                     // 表示
    return;                                              // 戻る
  }                                                      // ファイルが開けば
  flashF.write(almH);                                    // almHを書込む
  flashF.write(almM);                                    // almMを書込む
  flashF.close();                                        // ファイルをclose
}

//-------------------------------------------------// 0 時計
void appWatch() {             // Mcase=0 時計表示
  Stime = millis();           // 開始時間(mS)
  lcd.fillScreen(TFT_BLACK);  // 全画面黒
  do {
    RTCread();                                // RTCデータを読み込む
    lcd.setTextColor(TFT_GREEN, TFT_BLACK);   // (字,地)
    lcd.setFont(&fonts::lgfxJapanGothic_28);  // 固定幅ゴシック体 8,12,16,20,24,28,32,36,40
    lcd.setTextSize(1, 1.8);                  // 文字サイズ(倍)
    lcd.setCursor(0, 66 * 0 + 43 + 5);        // カーソル位置 [AM/PM]
    uint8_t hhh;                              // hhの12時間用
    if (hh > 12) {                            // PM時
      hhh = hh - 12;                          // 12時間表示
      lcd.print("PM");                        // 表示
    } else {                                  // AM時
      hhh = hh;                               // そのまま
      lcd.print("AM");                        // 表示
    }
    lcd.setTextSize(1);  // 文字サイズ(倍)

    lcd.setCursor(60, 66 * 0 + 43);    // カーソル位置
    lcd.setFont(&fonts::Font7);        // Font 7セグ
    lcd.printf("%02d:%02d", hhh, mm);  // 時:分を表示

    lcd.setCursor(60, 66 * 1 + 43);       // カーソル位置
    lcd.printf("%02d:%02d", almH, almM);  // アラーム時:分を表示

    lcd.setFont(&fonts::lgfxJapanGothic_28);  // 固定幅ゴシック体 8,12,16,20,24,28,32,36,40
    lcd.setTextSize(2.3, 2);                  // 文字サイズ 倍(横,縦)
    lcd.setCursor(70, 66 * 2 + 43 - 5);       // カーソル位置
    int16_t mmm = almH * 60 + almM
                  - hh * 60 - mm;  // 残り分計算
    if (mmm < -60) mmm = 0;        // 60分以上前は0とする
    if (mmm <= 0) {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (白字,地)
    } else if (mmm <= 5) {
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (赤字,地)
    }
    lcd.printf("%4d", mmm);                  // 残り分を表示
    lcd.setTextColor(TFT_GREEN, TFT_BLACK);  // (字,地)

    lcd.setFont(&fonts::lgfxJapanGothic_28);  // 固定幅ゴシック体 8,12,16,20,24,28,32,36,40
    lcd.setTextSize(0.7, 1.6);                // 文字サイズ(倍)
    lcd.setCursor(0, 66 * 1 + 43 + 5);        // カーソル位置 [アラーム時:分]
    lcd.print("設定");                        // 表示

    lcd.setCursor(0, 66 * 2 + 43 + 5);  // カーソル位置 [残り分]
    lcd.print("あと");                  // 表示

    lcd.setCursor(200, 66 * 2 + 43);  // カーソル位置 [残り分]
    lcd.print("分");                  // 表示
    lcd.setTextSize(1);               // 文字サイズ戻す

    printBT();                   // バッテリー残量表示関数へ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 10;                // メニューへ
    }

    int16_t x0 = 210, y0 = 85, dy = 4;                         // 一番下の横線の書始めx,yと線間の刻み
    if (ss < 5) {                                              // 5秒未満なら 5秒ごとに横線を引く
      lcd.fillRect(x0, y0 - dy * 11, 30, dy * 11, TFT_BLACK);  // 四角塗潰(x,y,w,h,色)
      lcd.drawFastHLine(x0, y0 - dy * 0, 30, TFT_DARKGREY);    // 水平線(X,y,W,色)
    } else if (ss < 10) {                                      // 5秒以上10秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 1, 30, TFT_DARKGREY);    // 水平線(X,y,W,色)
    } else if (ss < 15) {                                      // 10秒以上15秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 2, 30, TFT_BROWN);       // 水平線(X,y,W,色)
    } else if (ss < 20) {                                      // 15秒以上20秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 3, 30, TFT_BROWN);       // 水平線(X,y,W,色)
    } else if (ss < 25) {                                      // 20秒以上25秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 4, 30, TFT_RED);         // 水平線(X,y,W,色)
    } else if (ss < 30) {                                      // 25秒以上30秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 5, 30, TFT_RED);         // 水平線(X,y,W,色)
    } else if (ss < 35) {                                      // 30秒以上35秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 6, 30, TFT_ORANGE);      // 水平線(X,y,W,色)
    } else if (ss < 40) {                                      // 35秒以上40秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 7, 30, TFT_ORANGE);      // 水平線(X,y,W,色)
    } else if (ss < 45) {                                      // 40秒以上45秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 8, 30, TFT_YELLOW);      // 水平線(X,y,W,色)
    } else if (ss < 50) {                                      // 45秒以上50秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 9, 30, TFT_YELLOW);      // 水平線(X,y,W,色)
    } else if (ss < 55) {                                      // 50秒以上55秒未満なら
      lcd.drawFastHLine(x0, y0 - dy * 10, 30, TFT_GREEN);      // 水平線(X,y,W,色)
    } else {                                                   // 55秒以上なら
      lcd.drawFastHLine(x0, y0 - dy * 11, 30, TFT_GREEN);      // 水平線(X,y,W,色)
    }

    Ctime = millis();               // 現在時間
    if (Ctime - Stime >= period) {  // 判定時間が経過したら
      Dsleep();                     // deep sleep
    }
  } while (Mcase == 0);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 10
void appMenu() {                                  // Mcase=10 アイコンメニュー
  lcd.drawPng((std::uint8_t *)img, 34644, 7, 7);  // png表示 (配列名,サイズ,x,y)
  delay(1);                                       // 1mS待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたらx,yを読取る
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      if (y < 80) {              // 1行目なら
        if (x < 80) {            // 1行1列目なら
          Mcase = 1;             // 1へ
        } else if (x < 160) {    // 1行2列目なら
          Mcase = 2;             // 2へ
        } else {                 // 1行3列目なら
          Mcase = 3;             // 3へ
        }
      } else if (y < 160) {    // 2行目なら
        if (x < 80) {          // 2行1列目なら
          Mcase = 4;           // 4へ
        } else if (x < 160) {  // 2行2列目なら
          Mcase = 5;           // 5へ
        } else {               // 2行3列目なら
          Mcase = 6;           // 6へ
        }
      } else {                 // 3行目なら
        if (x < 80) {          // 3行1列目なら
          Mcase = 7;           // 7へ
        } else if (x < 160) {  // 3行2列目なら
          Mcase = 8;           // 8へ
        } else {               // 3行3列目なら
          Mcase = 9;           // 9へ
        }
      }
    }
  } while (Mcase == 10);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 1
void appalarmSet() {                       // Mcase=1 アラーム時刻設定
  RTCread();                               // RTCデータを読込む
  lcd.setCursor(40, 0);                    // カーソル位置
  lcd.setTextColor(TFT_GREEN, TFT_BLACK);  // (字,地)
  lcd.setTextSize(0.9);                    // 文字サイズの倍数
  lcd.print("アラーム設定");               // 表示 タイトル
  lcd.setTextSize(1.6);                    // 文字サイズの倍数
  lcd.setCursor(20, 85);                   // カーソル位置 タッチ表示用
  lcd.print("+10  -10");                 // 表示
  lcd.setCursor(30, 165);                  // カーソル位置 タッチ表示用
  lcd.print("+ SET -");                  // 表示
  lcd.setTextSize(1);                      // 文字サイズの倍数
  timeSetNo = 4;                           // 時から始める

  do {
    delay(100);                              // 100mS待つ
    lcd.setTextSize(1.6);                    // 文字サイズの倍数
    lcd.setCursor(60, 30);                   // カーソル位置 時:分
    if (timeSetNo == 4) {                    // 時
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", hh);                  // 表示 時
    lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    lcd.print(":");                          // 表示
    if (timeSetNo == 5) {                    // 分
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", mm);  // 表示 分
    lcd.setTextSize(1);      // 文字サイズの倍数

    if (ttgo->getTouch(x, y)) {  // タッチしたらx,yを読取る
      delay(100);                // 100mS待つ
      if (y < 150) {             // タッチ上段
        if (x < 120) {           // 上段左側
          touchNo = 10;          // +10
        } else {                 // 上段右側
          touchNo = 30;          // -10
        }
      } else {                 // タッチ下段
        if (x < 80) {          // 下段左側
          touchNo = 1;         // +1
        } else if (x < 160) {  // 下段中央
          touchNo = 2;         // SET
        } else {               // 下段右側
          touchNo = 3;         // -1
        }
      }
    }
    switch (timeSetNo) {                // する動作の場所
      case 4:                           // 時
        if (touchNo == 1) hh++;         // +は1up
        if (touchNo == 3) hh--;         // -は1down
        if (touchNo == 10) hh += 10;    // +10は10up
        if (touchNo == 30) hh -= 10;    // -10は10down
        if (hh > 23) hh = 23;           // ~23時とする
        if (hh < 0) hh = 0;             // 0時~とする
        if (touchNo == 2) timeSetNo++;  // SETは次の設定
        break;
      case 5:                         // 分
        if (touchNo == 1) mm++;       // +は1up
        if (touchNo == 3) mm--;       // -は1down
        if (touchNo == 10) mm += 10;  // +10は10up
        if (touchNo == 30) mm -= 10;  // -10は10down
        if (mm > 59) mm = 59;         // ~59分とする
        if (mm < 0) mm = 0;           // 0分~とする
        if (touchNo == 2) {           // SET
          almH = hh;                  // アラーム時
          almM = mm;                  // アラーム分
          flashWrite();               // flashにデータ書込関数へ
          Mcase = 0;                  // 時計画面へ
        }
        break;
      default:  // それ以外
        break;
    }                    // 表示
    touchNo = 0;         // 勝手にループしないように
  } while (Mcase == 1);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 2 時刻設定
void apptimeSet() {                        // Mcase=2 時刻合わせ 手動
  RTCread();                               // RTCデータを読込む
  lcd.setCursor(70, 0);                    // カーソル位置
  lcd.setTextColor(TFT_GREEN, TFT_BLACK);  // (字,地)
  lcd.setTextSize(0.9);                    // 文字サイズの倍数
  lcd.print("時刻設定");                   // 表示タイトル
  lcd.setTextSize(1.6);                    // 文字サイズの倍数
  lcd.setCursor(20, 165);                  // カーソル位置 タッチ表示用
  lcd.print("+ SET -");                  // 表示
  lcd.setTextSize(1);                      // 文字サイズの倍数
  timeSetNo = 1;                           // 年から始める
  do {
    delay(100);                              // 100mS待つ
    lcd.setTextSize(1.6);                    // 文字サイズの倍数
    lcd.setCursor(10, 40);                   // カーソル位置 年月日
    if (timeSetNo == 1) {                    // 年(変更場所)
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%4d", yyear);                // 表示 年
    lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    lcd.print("/");                          // 表示
    if (timeSetNo == 2) {                    // 月
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", mmonth);              // 表示 月
    lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    lcd.print("/");                          // 表示
    if (timeSetNo == 3) {                    // 日
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", dday);                // 表示 日
    lcd.setCursor(60, 90);                   // カーソル位置 時分
    if (timeSetNo == 4) {                    // 時
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", hh);                  // 表示 時
    lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    lcd.print(":");                          // 表示
    if (timeSetNo == 5) {                    // 分
      lcd.setTextColor(TFT_RED, TFT_BLACK);  // (字,地)
    } else {
      lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    }
    lcd.printf("%02d", mm);  // 表示 分
    lcd.setTextSize(1);      // 文字サイズの倍数

    if (ttgo->getTouch(x, y)) {  // タッチしたらx,yを読取る
      delay(100);                // 100mS待つ
      if (x < 80) {              // 左側
        touchNo = 1;             // +
      } else if (x < 160) {      // 中央
        touchNo = 2;             // SET
      } else {                   // 右側
        touchNo = 3;             // -
      }
      switch (timeSetNo) {                   // する動作の場所
        case 1:                              // 年
          if (touchNo == 1) {                // +
            yyear++;                         // 1up
            if (yyear > 2026) yyear = 2026;  // ~2026年とする
          } else if (touchNo == 3) {         // -
            yyear--;                         // 1down
            if (yyear < 2024) yyear = 2024;  // 2024年~とする
          } else {                           // SET
            timeSetNo++;                     // 次の設定
          }
          break;
        case 2:                            // 月
          if (touchNo == 1) {              // +
            mmonth++;                      // 1up
            if (mmonth > 12) mmonth = 12;  // ~12月とする
          } else if (touchNo == 3) {       // -
            mmonth--;                      // 1down
            if (mmonth < 1) mmonth = 1;    // 1月~とする
          } else {                         // SET
            timeSetNo++;                   // 次の設定
          }
          break;
        case 3:                        // 日
          if (touchNo == 1) {          // +
            dday++;                    // 1up
            if (dday > 31) dday = 31;  // ~31日とする
          } else if (touchNo == 3) {   // -
            dday--;                    // 1down
            if (dday < 1) dday = 1;    // 1日~とする
          } else {                     // SET
            timeSetNo++;               // 次の設定
          }
          break;
        case 4:                       // 時
          if (touchNo == 1) {         // +
            hh++;                     // 1up
            if (hh > 23) hh = 23;     // ~23時とする
          } else if (touchNo == 3) {  // -
            hh--;                     // 1down
            if (hh < 0) hh = 0;       // 0時~とする
          } else {                    // SET
            timeSetNo++;              // 次の設定
          }
          break;
        case 5:                                                       // 分
          if (touchNo == 1) {                                         // +
            mm++;                                                     // 1up
            if (mm > 59) mm = 59;                                     // ~59分とする
          } else if (touchNo == 3) {                                  // -
            mm--;                                                     // 1down
            if (mm < 0) mm = 0;                                       // 0分~とする
          } else {                                                    // SET
            ttgo->rtc->setDateTime(yyear, mmonth, dday, hh, mm, 30);  // RTCに書込む
            Mcase = 0;                                                // 時計画面へ
          }
          break;
        default:  // それ以外
          break;
      }
    }
  } while (Mcase == 2);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 3
void app3() {                              // Mcase=3 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー3");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 3);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 4
void app4() {                              // Mcase=4 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー4");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 4);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 5
void app5() {                              // Mcase=5 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー5");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 5);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 6
void app6() {                              // Mcase=6 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー6");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 6);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 7
void app7() {                              // Mcase=7 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー7");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 7);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 8
void app8() {                              // Mcase=8 未作成
  lcd.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
  lcd.print("メニュー8");                  // 表示
  delay(1000);                             // 1秒待つ
  do {
    delay(100);                  // 0.1秒待つ
    if (ttgo->getTouch(x, y)) {  // タッチしたら
      ttgo->motor->onec();       // モータを振動(0.2秒程度)
      delay(250);                // 250mS待つ 連続:-200 不連続:250-
      Mcase = 0;                 // 時計画面へ
    }
  } while (Mcase == 8);  // Mcaseが変わるまでループ
}

//-------------------------------------------------// 9 時計画面へ
void appReturn() {  // Mcase=9 時計画面へ戻る
  Mcase = 0;        // 時計画面へ
}

//-------------------------------------------------//
void setup() {
  SetFont();            // Font等初期化関数へ
  ttgo->motor_begin();  // 振動モータの初期設定
  ttgo->motor->onec();  // モータを振動(0.2秒程度)
  power = ttgo->power;         // 簡単に書けるようにオブジェクトを受取る
  sensor = ttgo->bma;          // 簡単に書けるようにオブジェクトを受取る
  SetBMA423();                 // 3軸加速度センサーの設定
  sensor->resetStepCounter();  // 割込機能のリセット
  //sensor->enableStepCountInterrupt(); // 歩数による割込を有効にする しない
  sensor->enableTiltInterrupt();    // 傾きによる割込を有効にする
  sensor->enableWakeupInterrupt();  // ダブルクリックによる割込を有効にする
  //////////////////// //////////////////// ////////////////////
  //SPIFFS.format();  // 初回のみ有効、プログラム動作はしません。次回からは注釈にする
  //////////////////// //////////////////// ////////////////////
  if (!SPIFFS.begin()) {          // SPIFFSの初期化ができなければ
    lcd.println("SPIFFS Error");  // エラー表示
  }
  flashRead();  // flashのデータ読込関数へ almH,almM
}

void loop() {
  switch (Mcase) {  // 表示状態
    case 0:
      appWatch();  // 0.時計へ
      break;
    case 1:
      appalarmSet();  // 1.アラーム時分設定
      break;
    case 2:
      apptimeSet();  // 2.時刻合わせ
      break;
    case 3:
      app3();  // 3.未作成
      break;
    case 4:
      app4();  // 4.未作成
      break;
    case 5:
      app5();  // 5.未作成
      break;
    case 6:
      app6();  // 6.未作成
      break;
    case 7:
      app7();  // 7.未作成
      break;
    case 8:
      app8();  // 8.未作成
      break;
    case 9:
      appReturn();  // 9.時計画面へ戻る
      break;
    case 10:
      appMenu();  // 10.メニュー画面へ
      break;
    default:  // それ以外
      break;
  }
  delay(100);                 // 100mS待つ
  lcd.fillScreen(TFT_BLACK);  // 全画面黒
}
* flash memory(6.5Mbyte)のうち、スケッチが14%使用。RAM(4.5Mbyte)のうち、global変数が0%使用、local変数で4.5Mbyte使用可能。(1000byte=1kbyteで計算)