02.M5Unifiedで温湿度・気圧測定
02.M5Unifiedで温湿度・気圧測定
温湿度・気圧測定で"01.M5StickC+で簡易熱中症計"のスケッチを修正し4機種で動作するようにしました。温度等の取得は共通でできますが、画面構成は共通ではできないので、位置は比例計算し、文字サイズは実物合わせで拡大縮小しました。
説明
元画面のM5StickC+は、240x135なので320x240は、1.33倍(=x320/240)x1.78倍(=x240/135)
200x200は、0.83倍(=x200/240)x1.48倍(=x200/135)
128x128は、0.53倍(=x128/240)x0.95倍(=x128/135)
です。
長辺幅WWの320,240,200,128で4機種を区別しました。
1.画面サイズを取得
2.横長に回転し
3.画面サイズから比例でカーソル位置を計算
4.画面5行目の温湿度・気圧測定値が1行に収まるフォントサイズに変更
5.行間は、文字の縦サイズを変更
フォントサイズ
switch (WW) { // 機種ごとの画面設定
case 128: // ATOMS3
M5.Display.setFont(&fonts::lgfxJapanGothic_12); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 2.0); // テキストサイズ(倍) 縦を伸ばす
break;
case 200: // CoreInk
M5.Display.setFont(&fonts::lgfxJapanGothic_20); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 1.2); // テキストサイズ(倍) 縦を伸ばす
break;
case 240: // M5StickCPlus
M5.Display.setFont(&fonts::lgfxJapanGothic_24); // ゴシック(8,12,16,20,24,28,32,36,40)
break;
case 320: // M5Stack Basic
M5.Display.setFont(&fonts::lgfxJapanGothic_32); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 0.8); // テキストサイズ(倍) 縦を縮める
break;
default: // それ以外
break;
}
バッテリー
ATOMS3はバッテリーが無く、バッテリー残量取得で、マイナス値が出るので、別表示としました。
if (WW == 128) { // ATOMS3はバッテリーが無いので
M5.Display.print("BT---%%"); // 表示 バッテリ残量
} else {
batP = M5.Power.getBatteryLevel(); // バッテリー残量値を取得(0-100)
M5.Display.printf("BT%3d%%", batP); // 表示 バッテリ残量
}
・M5Stack Basic・CoreInk
・M5StickCPlus
・ATOMS3
flash memory
CoreInkは標準ではArduino-IDE > ツール > Partition Scheme "Default 4MB with spiffs(1.2MB APP/1.5MB SPIFFS)"
で
"スケッチが大きすぎます。"
と表示されるので
"8M with spiffs(3MB APP/1.5MB SPIFFS)"
に変更しましたがエラー無しで書込みはするが、何も表示しないので、
"No OTA (2MB APP/2MB SPIFFS)"
に変更しました。表示は、
最大2097152バイトのフラッシュメモリのうち、スケッチが1470461バイト(70%)を使っています。最大327680バイトのRAMのうち、グローバル変数が26800バイト(8%)を使っていて、ローカル変数で300880バイト使うことができます。
通常時の電源on/off
・M5Stack Basicon :電源ボタンをクリック
off:USBを外して、電源ボタンをダブルクリック
・CoreInk
on :PWRボタンを2秒長押し
off:背面のRSTボタン
・M5StickCPlus
on :PWRボタンを2秒押す
off:PWRボタンを6秒押す
・ATOMS3 TailBat(190mAh)を接続した状態
on :TailBatのボタンをクリック
off:TailBatのボタンをダブルクリック
書込待機モード:ATOMS3のRSTボタンを2秒長押し、緑LEDが点灯したら離す
スケッチ
// AirPressureM5Unified.ino
// 温湿度・気圧・室内簡易暑さ指数・不快指数の表示
// 暑さ指数:(温度:四捨五入で整数,湿度:切上げで5の倍数の整数) 表による
// 不快指数:式は測定値そのもので計算
// 電源on:電源ボタンを2秒, 電源off:6秒
// Adafruit BMP280 Library と Adafruit SHT31 Library が必要
// 90秒で電源が切れるプログラムなので、更新中に電源onか注意必要
#include <M5Unified.h> // M5Unifiedライブラリを使用
#include <Adafruit_SHT31.h> // 温湿度センサを使用
#include <Adafruit_BMP280.h> // 気圧センサを使用
Adafruit_SHT31 sht = Adafruit_SHT31(&Wire); // sht定義
Adafruit_BMP280 bme = Adafruit_BMP280(&Wire); // bmp定義だがbmeとする
unsigned long startTime, currentTime; // 開始時間,現在時間 mS
unsigned long period = 90 * 1000; // 目標経過時間 mS
int32_t WW, HH, batP; // 画面幅,高さ,バッテリー残量(0-100)
int16_t tmp, pre; // 10倍の温度,気圧 -32768~32767
int8_t hum, thi, wbgt; // 湿度,不快指数,暑さ指数
int8_t tmpIndex, humIndex, RemainingT; // 温度配列,湿度配列.残り秒
int32_t xx, yy, xxx, yyy; // xy計算
// ℃ % 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100% 暑さ指数表ver4
int8_t wbgtT[20][17] = { { 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21 }, //21℃
{ 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 20, 21, 21, 22, 22 }, //22
{ 15, 16, 16, 17, 18, 18, 19, 19, 20, 20, 20, 21, 21, 22, 22, 23, 23 }, //23
{ 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24 }, //24
{ 17, 17, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25 }, //25
{ 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 }, //26
{ 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27 }, //27
{ 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28 }, //28
{ 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 28, 29, 29 }, //29
{ 21, 21, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 30 }, //30
{ 21, 22, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 30, 31, 31 }, //31
{ 22, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 32 }, //32
{ 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 30, 31, 31, 32, 33, 33 }, //33
{ 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 31, 32, 32, 33, 34, 34 }, //34
{ 24, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 33, 34, 34, 35 }, //35
{ 25, 26, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 34, 35, 35, 36 }, //36
{ 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36, 37 }, //37
{ 27, 28, 29, 29, 30, 31, 32, 33, 33, 34, 35, 35, 36, 36, 37, 37, 38 }, //38
{ 27, 28, 29, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, 38, 39 }, //39
{ 28, 29, 30, 31, 32, 33, 34, 34, 35, 36, 36, 37, 38, 38, 39, 39, 40 } }; //40
void SetDisplay() { // 初期画面設定関数
M5.Display.fillScreen(TFT_BLACK); // 全画面黒
WW = M5.Display.width(); // 画面幅を取得
HH = M5.Display.height(); // 画面高さを取得
if (WW == HH) { // 画面を横長にする
M5.Display.setRotation(0); // 0度回転
} else {
M5.Display.setRotation(1); // 90度回転
}
if (HH > WW) { // 横長なので交換 横:WW,縦:HHにする
int32_t HHWW = HH;
HH = WW;
WW = HHWW;
}
M5.Display.setFont(&fonts::lgfxJapanGothic_24); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1); // テキストサイズ(倍)
M5.Display.setBrightness(100); // バックライト輝度(0-255)実際は数段階
M5.Display.setTextColor(TFT_GREEN, TFT_BLACK); // 色設定(文字色[,背景色])
}
void setup() {
auto cfg = M5.config(); // M5設定用の構造体を代入
M5.begin(cfg); // M5本体の初期化
startTime = millis(); // 開始時間
SetDisplay(); // 初期画面設定関数へ
while (!sht.begin(0x44)) { // shtのアドレスで開始できない時
M5.Display.println("エラー SHT3X未接続"); // 表示
}
while (!bme.begin(0x76)) { // BMP280のアドレスで開始できない時
M5.Display.println("エラー BMP280未接続"); // 表示
}
switch (WW) { // 機種ごとの画面設定
case 128: // ATOMS3
M5.Display.setFont(&fonts::lgfxJapanGothic_12); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 2.0); // テキストサイズ(倍) 縦を伸ばす
break;
case 200: // CoreInk
M5.Display.setFont(&fonts::lgfxJapanGothic_20); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 1.2); // テキストサイズ(倍) 縦を伸ばす
break;
case 240: // M5StickCPlus
M5.Display.setFont(&fonts::lgfxJapanGothic_24); // ゴシック(8,12,16,20,24,28,32,36,40)
break;
case 320: // M5Stack Basic
M5.Display.setFont(&fonts::lgfxJapanGothic_32); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1, HH / 135.0 * 0.8); // テキストサイズ(倍) 縦を縮める
break;
default: // それ以外
break;
}
}
void loop() {
currentTime = millis(); // 現在時間
if (currentTime - startTime < period) { // 指定表示時間以内なら
tmp = int16_t(sht.readTemperature() * 10.0 + 0.5); // センサーで10倍の温度を読取る
M5.Display.setTextColor(TFT_GREEN, TFT_BLACK); // (文字色{,背景色})
yy = (int32_t)(108 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(0, yy); // 表示位置(x,y) 5行目
M5.Display.printf("%5.1f℃", tmp / 10.0); // 表示 温度
hum = int8_t(sht.readHumidity() + 0.5); // センサーで湿度を読取る
M5.Display.setTextColor(TFT_CYAN, TFT_BLACK); // (字,地)
M5.Display.printf("%3d%%", hum); // 表示 湿度
pre = int16_t(bme.readPressure() / 100.0 + 0.5); // センサーで気圧を読取る
M5.Display.setTextColor(TFT_PINK, TFT_BLACK); // (字,地)
M5.Display.printf("%5dhPa\n", pre); // 表示 気圧
tmpIndex = int8_t(tmp / 10.0 + 0.5) - 21; // 四捨五入で整数 配列温度番号
humIndex = (hum - 16) / 5; // 配列湿度番号
wbgt = wbgtT[tmpIndex][humIndex]; // wbgtを表から読む
xx = (int32_t)(2 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(28 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(xx, yy); // 表示位置(x,y) 2行目
yyy = (int32_t)(107 * HH / 135.0 + 0.5); // y座標計算
if (wbgt < 21) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_BLUE); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_WHITE, TFT_BLUE); // (字,地)
M5.Display.println("ほぼ安全"); // 表示
} else if (wbgt < 25) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_CYAN); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_BLACK, TFT_CYAN); // (字,地)
M5.Display.println("注意"); // 表示
} else if (wbgt < 28) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_YELLOW); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_BLACK, TFT_YELLOW); // (字,地)
M5.Display.println("警戒"); // 表示
} else if (wbgt < 31) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_ORANGE); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_BLACK, TFT_ORANGE); // (字,地)
M5.Display.println("厳重警戒"); // 表示
} else if (wbgt < 33) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_RED); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_WHITE, TFT_RED); // (字,地)
M5.Display.println("危険"); // 表示
} else if (wbgt < 35) {
M5.Display.fillRect(0, 0, 320, yyy, TFT_VIOLET); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_WHITE, TFT_VIOLET); // (字,地)
M5.Display.println("警戒アラートレベル"); // 表示
} else {
M5.Display.fillRect(0, 0, 320, yyy, TFT_BLACK); // 四角塗潰(x,y,w,h,色)
M5.Display.setTextColor(TFT_WHITE, TFT_BLACK); // (字,地)
M5.Display.println("特別警戒アラートレベル"); // 表示
}
yy = (int32_t)(2 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(0, yy); // 表示位置(x,y) 1行目
M5.Display.printf("(暑さ指数%d)\n", wbgt); // 表示 wbgt
// 不快指数
thi = int8_t(0.081 * tmp + 0.01 * hum * (0.099 * tmp - 14.3) + 46.3 + 0.5);
yy = (int32_t)(55 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(0, yy); // 表示位置(x,y) 3行目
M5.Display.printf("(不快指数%2d)\n", thi); // 表示 不快指数
xx = (int32_t)(2 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(81 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(xx, yy); // 表示位置(x,y) 4行目
if (thi < 50) { // 不快指数の感じ方
M5.Display.println("寒くてたまらない"); // 表示 すべて8文字以下
} else if (thi < 55) {
M5.Display.println("寒い");
} else if (thi < 60) {
M5.Display.println("肌寒い");
} else if (thi < 65) {
M5.Display.println("何も感じない");
} else if (thi < 70) {
M5.Display.println("快適");
} else if (thi < 75) {
M5.Display.println("不快感の人がいる");
} else if (thi < 80) {
M5.Display.println("半数以上が不快感");
} else if (thi < 85) {
M5.Display.println("93%が不快感");
} else {
M5.Display.println("暑くてたまらない");
}
xx = (int32_t)(165 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(2 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(xx, yy); // 表示位置(x,y) 1行目
if (WW == 128) { // ATOMS3はバッテリーが無いので
M5.Display.print("BT---%%"); // 表示 バッテリ残量
} else {
batP = M5.Power.getBatteryLevel(); // バッテリー残量値を取得(0-100)
M5.Display.printf("BT%3d%%", batP); // 表示 バッテリ残量
}
RemainingT = (startTime + period - currentTime) / 1000; // 残り秒数
xx = (int32_t)(200 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(55 * HH / 135.0 + 0.5); // y座標計算
M5.Display.setCursor(xx, yy); // 表示位置(x,y) 3行目
M5.Display.printf("%3d", RemainingT); // 電源offまでの秒数
yy = (int32_t)(54 * HH / 135.0 + 0.5); // y座標計算
M5.Display.drawFastHLine(0, yy, 320, TFT_BLACK); // 水平線(x,y,w,色)不快指数の上線
xx = (int32_t)(164 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(1 * HH / 135.0 + 0.5); // y座標計算
xxx = (int32_t)(74 * WW / 240.0 + 0.5); // w計算
yyy = (int32_t)(26 * HH / 135.0 + 0.5); // h計算
M5.Display.drawRect(xx, yy, xxx, yyy, TFT_BLACK); // 四角枠 (x,y,w,h,色) バッテリー枠
xx = (int32_t)(198 * WW / 240.0 + 0.5); // x座標計算
yy = (int32_t)(56 * HH / 135.0 + 0.5); // y座標計算
xxx = (int32_t)(40 * WW / 240.0 + 0.5); // w計算
yyy = (int32_t)(21 * HH / 135.0 + 0.5); // h計算
M5.Display.drawRect(xx, yy, xxx, yyy, TFT_BLACK); // 四角枠 (x,y,w,h,色) 残秒枠
delay(5000); // 5秒待つ
} else {
M5.Power.powerOff(); // 電源off
}
}
* M5CoreInkで"2MB APP"に設定の時、flash memory(2.1Mbyte)のうち、スケッチが70%使用。RAM(328kbyte)のうち、global変数が8%使用、local変数で301kbyte使用可能。(1000byte=1kbyteで計算)