SJK が 2021年02月27日16時15分37秒 に編集
初版
タイトルの変更
M5StickC plusとNCIR hatでポータブル非接触体温計を作る
タグの変更
M5StickC
体温計
NCIR
MLX90614
Arduino_IDE
秋葉原2021
メイン画像の変更
本文の変更
**1. 概要** コロナ禍で毎日の検温が必須になった昨今、朝の忙しい時間帯に家族全員分迅速に体温を計測するために、半田付けなしですぐに温度測定ができる、NCIRハットとM5StickC-plusで非接触体温計を作ってみました。 **2. 使用したモジュール** - M5StickC plus https://www.switch-science.com/catalog/6470/ ![M5StickC plus](https://camo.elchika.com/8a19ff4a24b9e18b88b007eebb8e8c09b72e7d98/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f35386366623661372d613337392d343635322d383130622d6464656637363663303337632f36356465356138632d313737612d343964632d616466352d306666636664623761336466/) - M5StickC 非接触温度センサ Hat(MLX90614搭載) https://www.switch-science.com/catalog/6067/ ![NCIR hat](https://camo.elchika.com/c994f69ba0e4a004e3551adce7a1e08c5afd3d5c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f35386366623661372d613337392d343635322d383130622d6464656637363663303337632f30663439343030382d663437382d346463302d396461352d383762623661383665303364/) (※現在、m5stack.comでもOut Of Stockとなっております。使用されているセンサーのMLX90614自体が品薄のようです) **3. 開発環境** 開発環境は、サンプルスケッチもあるArduino IDEで行いました。サンプルスケッチを書き込んだらすぐに計測できたので、こりゃ簡単だと思ったのですが、計測するたびに値がばらつきすぎる。というわけで、主に計測開始の温度しきい値と積算でその辺をカバーしました。 **4. 実装したこと** - 計測値31℃以下で待機モード(M5StickCの赤色LEDを点灯) - 100回温度計測を行いその平均を求める - 体温の他に、簡易のバッテリー残量表示 - 複数人が連続使用することを考慮し、ディープスリープと"M5"ボタンでスリープから復帰 **5. スケッチ** ```arduino:体温測定用スケッチ #include <M5StickCPlus.h> #include <Wire.h> #include <WiFi.h> #include <Adafruit_MLX90614.h> Adafruit_MLX90614 mlx = Adafruit_MLX90614(); void setup() { M5.begin(); setCpuFrequencyMhz(10); //電池を持たせるために動作周波数を落とす Wire.begin(0, 26); WiFi.mode( WIFI_OFF ); 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() { } ``` **6. 実際に使ってみて** しきい値と積算である程度測定値のばらつきは抑えられました。おでこで測るのでやや低めに出ます(そもそもNCIRハットに使われているMLX90614は医療用グレードではないようです)。使い方を覚えれば小学生低学年でも測れるので、朝の検温タイムは著しく短縮できました。 ![キャプションを入力できます](https://camo.elchika.com/72a6c700e7fa8eecee7d8d7ae8d9be37a27877b2/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f35386366623661372d613337392d343635322d383130622d6464656637363663303337632f38663437313636342d646362662d343934622d616165642d353430356163636633346462/)