概要
コロナ禍で毎日の検温が必須になった昨今、朝の忙しい時間帯に家族全員分迅速に体温を計測するために、半田付けなしですぐに温度測定ができる、NCIRハットとM5StickC-plusで非接触体温計を作ってみました。
使用したモジュール
-
M5StickC plus
https://www.marutsu.co.jp/pc/i/2190748/
-
非接触温度センサ Hat(NCIR hat, MLX90614搭載)
https://www.marutsu.co.jp/pc/i/1632335/
(※現在、m5stack.comでもOut Of Stockとなっております。使用されているセンサーのMLX90614自体が品薄のようです) -
接続
モジュールの接続はM5StickC plus上部ピンソケットにNCIR hatの8ピンを接続するだけです。
開発環境
開発環境は、サンプルスケッチもあるArduino IDEで行いました。サンプルスケッチを書き込んだらすぐに計測できたので、こりゃ簡単だと思ったのですが、計測するたびに値がばらつきすぎる。というわけで、主に計測開始の温度しきい値と積算でその辺をカバーしました。
実装したこと
- 計測値31℃以下で待機モード(M5StickCの赤色LEDを点灯)
- 100回温度計測を行いその平均を求める
- 測定終了時にビープ音を鳴らす
- 体温の他に、簡易のバッテリー残量表示
- 複数人が連続使用することを考慮し、ディープスリープと"M5"ボタンでスリープから復帰
スケッチ
体温測定用スケッチ
#include <M5StickCPlus.h>
#include <Wire.h>
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
void setup() {
M5.begin();
setCpuFrequencyMhz(10); //電池を持たせるために動作周波数を落とす
Wire.begin(0, 26);
M5.Beep.setBeep(4000, 500); // ビープ音設定(初期値, 4000Hz, 500msec)
mlx.begin();
M5.Axp.ScreenBreath(10); // 画面の輝度を少し下げる
M5.Lcd.setRotation(1); // 0縦正方向, 1左に画面, 2縦逆, 3右に画面
M5.Lcd.setTextSize(3); // 文字サイズを3にする
M5.Lcd.fillScreen(BLACK); // 背景を黒にする
// 温度データ取得
float temperature = mlx.readObjectTempC() + 0.0;
float int_temperature = mlx.readAmbientTempC();
int lpcnt = 0 ;
while (mlx.readObjectTempC() <= 31.0) //計測値が31℃以下の間は待機
{
pinMode(GPIO_NUM_10, OUTPUT); // LED ON(GPIO_NUM_10 or M5_LED)
digitalWrite(GPIO_NUM_10, LOW);
delay(100);
lpcnt += 1 ;
if (lpcnt > 50) {
ESP.restart();
}
}
//温度センサーの値を読み取る
//センサーの値を100回読み取り平均化する
float avetemp = 0;
float sum = 0;
float rEAD = 0;
sum = 0;
for (int i = 0; i < 100; i++) {
rEAD = mlx.readObjectTempC();
sum = sum + rEAD;
//delay(5);
}
avetemp = (sum / 100 ) + 3.8; //実際の体温との差を取った時、3.8℃ほど低く計測されたのでその補正
// LCD 体温表示
M5.Lcd.setCursor(3, 30, 4);
M5.Lcd.print(avetemp,1);
M5.Lcd.setTextSize(1); // 文字サイズを1にする
M5.Lcd.print("o"); //℃の左肩の丸表記の方法が分からなかったのでoの文字サイズを小さくすることで対応
M5.Lcd.setTextSize(3); // 文字サイズを3にする
M5.Lcd.println("C");
// バッテリー電圧
double vbat = M5.Axp.GetVbatData() * 1.1 / 1000;
// バッテリー残量
// 簡易的に、線形で4.1Vで100%、3.0Vで0%とする
int8_t bat_charge_p = int8_t((vbat - 3.0) / 1.1 * 100);
if (bat_charge_p > 100) {
bat_charge_p = 100;
} else if (bat_charge_p < 0) {
bat_charge_p = 0;
}
// LCDバッテリー残量表示
M5.Lcd.setTextSize(1); // 文字サイズを1にする
M5.Lcd.setCursor(3, 100, 4);
M5.Lcd.printf("Charge: %3d%%", bat_charge_p);
// Beepによる計測完了の通知
//M5.Beep.update(); // tone関数で鳴らした音が指定時間経過していたら止める
M5.Beep.tone(4000, 2000);
delay(1000);
M5.Beep.end(); // beepを止める
delay(3 * 1000);
M5.Axp.ScreenBreath(0); // 画面の輝度OFF
WiFi.mode( WIFI_OFF );
sum = 0;
rEAD = 0;
avetemp = 0;
// GPIO37(M5StickCのHOMEボタン)がLOWになったら起動
pinMode(GPIO_NUM_37, INPUT_PULLUP);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_37, LOW);
// ディープスリープ
esp_deep_sleep_start();
}
void loop() {
}
実際に使ってみて
しきい値と積算である程度測定値のばらつきは抑えられました。おでこで測るのでやや低めに出ます(そもそもNCIRハットに使われているMLX90614は医療用グレードではないようです)。使い方を覚えれば小学生低学年でも測れるので、朝の検温タイムは著しく短縮できました。
2
投稿者の人気記事
-
SJK
さんが
2021/02/27
に
編集
をしました。
(メッセージ: 初版)
-
SJK
さんが
2021/02/27
に
編集
をしました。
-
SJK
さんが
2021/02/27
に
編集
をしました。
-
SJK
さんが
2021/02/27
に
編集
をしました。
-
SJK
さんが
2021/02/27
に
編集
をしました。
-
SJK
さんが
2021/02/27
に
編集
をしました。
-
SJK
さんが
2021/02/28
に
編集
をしました。
ログインしてコメントを投稿する