最近は、新型コロナの影響で体温を測る機会が増えてきました。人との接触を最小限にして、短時間で検温するには、赤外線を使った検温システムが必要になると思い、赤外線アレイセンサ(AMG8833)を使って、非接触型の体温計に挑戦したので紹介します。
システム構成
今回の考えたシステム構成は以下です。
赤外線アレイセンサは、安価で入手しやすさを考慮して「AMG8833(愛称:Grid-EYE)」を使用しました。顔認証用のカメラとサーモセンサの表示を組み合わせて、面白いシステムができないかと考えてみました。
赤外線アレイセンサを使った非接触体温計システムの構成
基板配線図
AMG8833とラズパイの基板配線は以下です。
AMG8833端子 | ラズパイ(GPIO端子) |
VDD | 1番ピン (3.3V) |
GND | 6番ピン (GND) |
INT | ー |
SCL | 5番ピン (GPIO3) |
SDA | 3番ピン (GPIO2) |
AMG8833とラズパイの接続図
AMG8833のデータシートに記載されたいた推奨回路です。今回購入した基板には、AD_SELECTの端子はなかったので、スレーブアドレスは0x68固定のようです。
ちなみに、AD_SELECT端子があると、接続をVDD/GNDに切り替えることで、スレーブアドレスを選択できるようです。
・スレーブアドレス:0x68の場合(AD_SELECT端子がGNDに接続)
・スレーブアドレス:0x69の場合(AD_SELECT端子がVDDに接続)
ラズパイ側の設定&インストール
まずは、ラズパイのI2C端子を有効にします。
$ sudo raspi-config
「5 Interfacing Options」⇒「P5 I2C」⇒「はい」の順に選択します。
赤外線アレイセンサ(AMG8833)を接続して、i2cdetect コマンドを使って接続確認を行います。スキャン対象のアドレスを指定しない場合は、スレーブアドレスの0x03~0x77までをスキャンして応答があったものを表示してくれます。0x68か0x69アドレスの応答が返ってくると思います。
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
Adafruit社から提供されている「adafruit-circuitpython-amg88xx」をダウンロードしてインストールします。
$ sudo pip3 install adafruit-circuitpython-amg88xx
以上でラズパイ側の設定&インストールは完了です。
赤外線アレイセンサ(AMG8833)の確認
データシートからAMG8833のブロック図を見てみました。
さっと見てみると、サーミスタレジスタと温度レジスタの変換方法が記載されていました。
0x0E, 0x0F番地がサーミスタの出力値が入っています。
サーミスタ温度は、出力値×0.0625℃で温度データに換算できるようです。
$ python Python 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import smbus >>> i2c = smbus.SMBus(1) >>> temp = i2c.read_word_data(0x68, 0x0E) >>> temp * 0.0625 28.375
0x80番地以降に各画素の温度データが入っています。
温度レジスタは、出力値×0.25℃で温度データに換算できるようです。
$ python Python 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import smbus >>> i2c = smbus.SMBus(1) >>> temp = i2c.read_word_data(0x68, 0x80) >>> temp * 0.25 22.75
なんか、いい感じの値(温度データ)になっていますね。
ただ、距離が離れると若干低い温度になるようです。ここらあたりのキャリブレーションが必要そうです・・・
「adafruit-circuitpython-amg88xx」を使うと、この値を計算して、温度データとして配列に格納してくれるみたいです。
せっかくなので、このライブラリを使って、GUI画面で確認できるようにしてみました。
左側にサーモグラフィ、右側にカメラ映像を表示して、映像を見ながらサーモセンサからの温度を確認できます。
使用したプログラムは以下です。
# -*t coding: utf-8 -*-
import time
import busio
import board
import cv2
import numpy as np
from PIL import Image
import adafruit_amg88xx
import matplotlib.pyplot as plt
plt.ion()
plt.subplots(figsize=(8, 4))
# I2Cバスの初期化
i2c_bus = busio.I2C(board.SCL, board.SDA)
# カメラ設定
cam = cv2.VideoCapture(0)
# 画像サイズを設定(640x480)
cam.set(3, 640) # set video widht
cam.set(4, 480) # set video height
try:
while True:
# センサーの初期化:I2Cスレーブアドレス(0x68)
sensor = adafruit_amg88xx.AMG88XX(i2c_bus, addr=0x68)
# センサーの初期化待ち
time.sleep(.1)
# 画像の読み込み
ret, img =cam.read()
# matplotlibで表示のためBGR画像をRGBに変換
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#img = cv2.flip(img, -1) # 映像を上下左右反転
## 8x8センサアレイ内の最大温度を取得
max_temp = max(max(sensor.pixels))
# 画面の左側にサーモグラフィを表示
plt.subplot(1,2,1)
plt.imshow(sensor.pixels, cmap="inferno", interpolation="bicubic",vmin=25,vmax=37)
plt.colorbar()
plt.show
# 画面の右側にカメラ映像をを表示
plt.subplot(1,2,2)
plt.imshow(img)
plt.text(0, 0, str(max_temp) + 'deg',size = 14, color = "red")
plt.draw()
plt.pause(0.01)
plt.clf()
except KeyboardInterrupt:
print("finish")
サーモセンサの画角調整や、温度データのキャリブレーション方法を検討しないといけないですね。
ちょっと思案中・・・・