M5StickC PLUS2に日付・時刻、温度・湿度・気圧を表示する（忘備録）

## はじめに
M5StickC PLUS２について、日付・時刻、温度・湿度・気圧を同時に表示するガジェットを作成しました。センサには「ENV.IV SENSOR」を使用しました。

## やり方
本サイトの「参考」に載っている、「日付・時刻」と「温度・湿度・気圧」のスケッチを組み合わせました。

## 作成したスケッチ
```
#include "M5StickCPlus2.h"
#include "time.h"
#include <WiFi.h>
#include <M5Unified.h>

#include <SensirionI2cSht4x.h>
#include <Adafruit_BMP280.h>
#include "Adafruit_Sensor.h"

Adafruit_BMP280 bmp;      // 気圧センサBMP280用のインスタンスを作成
SensirionI2cSht4x sht4x;  // 温湿度センサSHT40用のインスタンスを作成
M5Canvas canvas(&M5.Lcd); // 液晶表示用、メモリ描画領域表示（スプライト）のインスタンスを作成

// wifiの設定
const char* ssid = "**************";
const char* password = "*************";
unsigned long setuptime; // スリープ開始判定用（ミリ秒）

// 変数宣言
float temperature, pressure, humidity;  // 測定値格納用
uint16_t error;         // SHT40エラー格納用
char errorMessage[256]; // SHT40エラーメッセージ格納用

void setup()
{
  // put your setup code here, to run once:
  //M5.begin();
  //M5.Lcd.setRotation(3);
  //M5.Lcd.fillScreen(BLACK);
    
  auto cfg = M5.config();  // 本体初期設定
  StickCP2.begin(cfg);  
    
  Wire.begin(32, 33);  // I2C通信初期化　SDA=32, SCL=33
  Serial.begin(9600);  // シリアル通信初期化
  while (!Serial) {
    delay(100);
  }

  // ベース画面の初期設定
  M5.Lcd.fillScreen(BLACK); // 背景色
  M5.Lcd.setRotation(1);    // 画面向き設定（USB位置基準 0：下/ 1：右/ 2：上/ 3：左）
  M5.Lcd.setTextSize(1);    // 文字サイズ（整数倍率）

  canvas.setTextWrap(true); // 改行をする（画面をはみ出す時自動改行する場合はtrue。書かないとtrue）
  canvas.createSprite(M5.Lcd.width()-10, M5.Lcd.height()); // canvasサイズ（メモリ描画領域）設定（画面サイズに設定）
  canvas.setCursor(0, 0);   // 表示座標
  canvas.setFont(&fonts::Font4); // フォント

  // connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");

  // Set ntp time to local
  configTime(3600L * 9, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");

  // 起動ごとに時刻同期するために同期タイミングを一時的に変更
  auto default_interval = sntp_get_sync_interval(); // ミリ秒単位
  sntp_set_system_time(1, 0);                       // 1秒

  // Set RTC
  struct tm timeInfo;
  if (getLocalTime(&timeInfo)) {
    M5.Rtc.setDateTime(timeInfo);
  }

  sntp_set_system_time(default_interval * 1000, 0); // 同期タイミングを戻す

  // disconnect WiFi
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);

  // 気圧センサ BMP280初期化
  while (!bmp.begin(0x76)) {  // 通信失敗でエラー処理
    Serial.println("BMP280 fail"); // シリアル出力
    canvas.setCursor(0, 0);        // 液晶表示
    canvas.println("BMP280 fail");
    canvas.pushSprite(&M5.Lcd, 10, 15); // 画面を指定座標に一括表示実行
    delay(1000);
  }
  
  // BMP280のサンプリングレートとフィルタ設定
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,   // モード：ノーマル
                  Adafruit_BMP280::SAMPLING_X2,   // 温度サンプリングレート：2倍
                  Adafruit_BMP280::SAMPLING_X16,  // 圧力サンプリングレート：16倍
                  Adafruit_BMP280::FILTER_X16,    // フィルタ：16倍
                  Adafruit_BMP280::STANDBY_MS_500);  // 待ち時間：500ms
  Serial.println("BMP280 OK!");

  // 温湿度センサ SHT40初期化
  sht4x.begin(Wire, 0x44);
  uint32_t serialNumber;                     // シリアルナンバー格納用
  error = sht4x.serialNumber(serialNumber);  // シリアルナンバー取得実行
  if (error) {  // シリアルナンバー取得失敗でエラー処理
    Serial.print("SHT40 Error: ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  } else {      // シリアルナンバー取得成功で準備完了
    Serial.println("SHT40 OK!");
    Serial.print("Serial Number: ");
    Serial.println(serialNumber);
  }
}

void loop()
{
  // LCD表示設定
  canvas.fillScreen(BLACK); // 画面初期化
  canvas.setFont(&fonts::lgfxJapanGothicP_20);  // フォント
  canvas.setCursor(0, 0);   // メモリ描画領域の表示座標指定

  // 圧力データ取得
  pressure = bmp.readPressure();

  // 温湿度データ取得、エラー処理
  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {  // trueならエラー処理
    errorToString(error, errorMessage, 256); // エラーを文字列に変換
    Serial.print("SHT40 Error: "); // シリアル出力
    Serial.println(errorMessage);
    canvas.setFont(&fonts::Font4); // 液晶表示
    canvas.printf("SHT40 Error:\n");
    canvas.print(errorMessage);
  } else {      // falseで測定データ表示実行
    //Serial.printf("%04d.%02d.%02d, ", M5.Rtc.getDate().year, M5.Rtc.getDate().month, M5.Rtc.getDate().date); // シリアル出力
    //Serial.printf("%02d:%02d:%02d, ", M5.Rtc.getTime().hours, M5.Rtc.getTime().minutes, M5.Rtc.getTime().seconds); // シリアル出力
    Serial.printf("%.0f, %.1f, %.1f\n", pressure/100, temperature, humidity); // シリアル出力
    canvas.printf("%04d.%02d.%02d  ", M5.Rtc.getDate().year, M5.Rtc.getDate().month, M5.Rtc.getDate().date);
    canvas.printf("%02d:%02d:%02d\n", M5.Rtc.getTime().hours, M5.Rtc.getTime().minutes, M5.Rtc.getTime().seconds);
    canvas.printf("気圧：%.0fhPa\n", pressure / 100); // 液晶表示
    canvas.printf("温度：%.1f℃\n", temperature);
    canvas.printf("湿度：%.1f％\n", humidity);
    canvas.printf("電池残量：%3d％\n", M5.Power.getBatteryLevel());
  }
  canvas.pushSprite(&M5.Lcd, 10, 15);  // 画面を指定座標に一括表示実行
  delay(1000);  // 遅延時間
}
```

## 作成したガジェット
![20250104_152909.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/bb578de5-8175-1f09-9c74-367916bae6c7.jpeg)

## 参考

https://qiita.com/uduki-oh-yeah/items/10864dbb4f39b0430efa

https://logikara.blog/env-iv/