#1. 作成の経緯
私が所属している団体では毎年大学祭で何かしらのモノづくりをすることになっているで現在の情勢を踏まえて非接触式体温計をつくってみることにしました。
#2.仕様
仕様としてはまず初めの3秒で外気温を計測し、腕を近づけて腕と温度センサの距離が12cmになると体温を計測し、LCDに表示する仕様になっています。
温度センサと腕の距離は超音波センサを用いて計測をしました。
図1. 体温計の仕様
図2. 回路図(適当でごめんなさい......)
#3. 使ったもの
・Arduino Uno R3 (https://www.amazon.co.jp/dp/B008GRTSV6/)
・MLX90614非接触赤外線温度センサ (https://www.amazon.co.jp/dp/B074HV53XP/)
・1602 LCD (https://www.amazon.co.jp/dp/B07WTMXRTQ/r)
・超音波センサHC-SR04 (https://www.amazon.co.jp/dp/B00YQZEVIW)
・ブレッドボード (https://www.amazon.co.jp/dp/B00DSKCS68)
・1kΩ抵抗2個
・ジャンパワイヤー(オスオス、オスメス数本ずつ)
#3.1. そもそもMLX90614とは
MLX90614という非接触式赤外線温度センサは物体から発生する赤外線から得られたエネルギーを変換して温度を計測するという素子です。
すなわち外気の温度と腕を近づけたときの温度の差から温度を逆算することができれば体温の測定ができるのではないかというものです。
ここでMLX90614の性能をチェックするべく以下の実験をしてみることにしました。
#####① 自身の体温の測定をおでこでおこなう。(ドリテック 非接触体温計 TO-401NWT)。
#####② センサから腕を5,10,15cmと距離をとり体温を1秒ごとに測定する。
#####③ 適当な秒数その位置でキープし、その秒数における体温との一致率Aをグラフに表す。
またこの時の一致率Aについて
A=\frac{温度センサの測定値}{体温計での測定値} ×100 \left( % \right)
で表すものとします。
この結果として以下のようなものが得られました。
図3. 計測時間における一致率の推移
最初の低いところが外気温で、上昇しているのか腕を近づけてからの一致率になります。
恐ろしいことに10~5cm、特に10cmでは常に横ばいで一致率が約65%で推移することが分かりました。しかも開始数秒で横ばいになる位置まで......
このことを踏まえて、距離を10cm前後、であれば計測時間が短時間でも、十分な性能を得られると推測しました。
##4.実際のプログラム
実際に作成したプログラムは以下の通りです。(※1)
:Temperature.c
#include <Adafruit_MLX90614.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define echoPin 2 // Echo Pin
#define trigPin 3 // Trigger Pin
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
double T_env=0;
double T_true=0;
double Duration = 0; //受信した間隔
double Distance = 0; //距離
int flag=0;
int a= 0;
void setup() {
mlx.begin();
Serial.begin(9600);
pinMode( echoPin, INPUT );
pinMode( trigPin, OUTPUT );
lcd.init();
lcd.backlight();
}
void loop() {
//LCDの測定
if(a==0){
lcd.setCursor(0, 0);
lcd.print("Just a minute...");
lcd.setCursor(0, 1);
lcd.print("(^^)");
}else{
}
//環境温度の測定
if(T_env>1){
//一度環境温度を測定したらスキップする
}else{
for(a=0;a<3;a++){
T_env+=mlx.readAmbientTempC();
delay(500);
Serial.println("wait");
}
T_env=T_env/3;
}
if(a==3){
Serial.println("Approach your arm.");
//LCDの表示
lcd.clear(); //必ずクリアする
lcd.setCursor(0, 0);
lcd.print("OK");
delay(200); //文字反映用の待機時間
a++;
}else{
//一度表示したらスキップする
}
//距離の測定
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite( trigPin, HIGH ); //超音波を出力
delayMicroseconds( 10 ); //
digitalWrite( trigPin, LOW );
Duration = pulseIn( echoPin, HIGH ); //センサからの入力
if (Duration > 0) {
Duration = Duration/2; //往復距離を半分にする
Distance = Duration*(331.5+0.61*T_env)*100/1000000; // 音速を温度で補正(1)
//Serial.print("Distance:");
//Serial.print(Distance);
//Serial.println(" cm");
flag=Distance;
if(flag==12){
// 表面温度の表示
Serial.print("Temperature : ");
Serial.println((((mlx.readObjectTempC()-(T_env))/0.95)+T_env)*100/65);//(2)
//LCDへの表示
lcd.clear(); //必ずクリアする
lcd.setCursor(0, 0);
lcd.print("Temperature");
lcd.setCursor(0, 1);
lcd.print((((mlx.readObjectTempC()-(T_env))/0.95)+T_env)*100/65,1);
lcd.print("[C]");
delay(5000);
}else{
}
}
}
ここで、補足として、コメントの部分に記載した(1)について、超音波センサの音速というのは外気温によって変化するので簡単な音速の補正を行っています。
また(2)については外気温と計測後の差が、人体によって温まったものであり、皮膚から放射されることから放射率0.95(※2)をかけて、元の外気温と足し合わせて補正してあります。(※3)さらに、先ほどの実験を踏まえて、一致率65%の再現を行いました。
また、そもそもなぜ腕で計測するかと言いますとまた、李(1995)(※4)によれば、(論文中Fig3,10に該当)は標準偏差は特別大きくも小さくもなく(Fig5参照)ということで特に問題なく計測できると判定したところにあります。
これにて完成ということではありますが、体温という一様分布ではないものを扱う都合上、精度をあげるにはさらに細かい外気の様子や放射率の補正が必要なのではないかと考えられます。
##5. 今後の課題
今回の作成において挙がった課題について、次のようなものがあります。
#####① 服や外気によって体表面が変化していた場合、正しい計測ができない。
#####② 連続使用で素子の温度が上昇し、適切な外気温が測定できないこと。
#####③ Arduinoに供給する電圧を上昇させると素子の温度が上昇する。(要検証)
の3点があります。
1点目に関しては非接触利用の体温計では宿敵となりますが、調べた範囲では現状解決する方法がなさそうに見えました。一応自身の計測ではできるだけそのようなことがないように配慮しましたが、外から入ってきた人に対して有効に扱うことができないので、それなりの補正が必要であると考えられます。
2点目に関しては「連続使用はやめてくれ!」としか言えないです。悲しいね。
3点目はまだ仮説の段階で実証ができていないので、今後調べるとしたら......ということになります。
##引用
※1:非接触温度センサで体温計測(一部引用)
(https://qiita.com/kz1017/items/549067cbd5d29f183b06)
※2:ウシオ電機株式会社
(https://www.ushio.co.jp/jp/)
※3:非接触温度センサ(MLX90614)
(https://denshikousakusenka.jimdofree.com)
※4:人体表面 の 温度点分布 (第 1 報)冷点分布密度の 部位差
(https://www.jstage.jst.go.jp/article/jhesj/2/1/2_KJ00007029734/_pdf)