konchangakita

KPSを一番楽しんでいたブログ 会社の看板を背負いません 転載はご自由にどうぞ

ラズパイとサーモセンサーで遊ぶ

ようやく手に入ったサーモセンサー(注文から1ヶ月くらい(でも届いたのは3ヶ月前))
この手のサーモセンサー春くらいから大人気アキバでも店舗ではみつけられませんでした
目的も予測がつくようにラズパイにサーモセンサをつけて人の体温やらなんかを感知してなんか表現してみたいのです

今回入手できた2つのサーモセンサー
f:id:konchangakita:20201111170354p:plain:w200
MLX90614非接触温度センサモジュール(amazonへ飛びます)

f:id:konchangakita:20201111170432p:plain:w200
AMG8833 IR 8 * 8サーマルイメージャーアレイ温度センサーモジュール8x8赤外線カメラセンサー(amazonへ飛びます)


それぞれどんな違いあるのかよくわからないまま、とりあえずポチってみました。
とりあえず接続してどんな情報が取得できるのかみていきます

事前準備

しばらく、Splunk や Jetson Nano で遊んでいたので、ひさしぶりの Raspberry Pi 4 Model B を使います
まず、久しぶりに触るときはラズパイのアップデートからやっときましょう

sudo apt update
sudo apt upgrade -y
sudo apt clean
sudo reboot

そしてバージョン確認

$ cat /proc/device-tree/model 
$ uname -a
$ cat /etc/os-release
$ cat /etc/debian_version 

=====
Raspberry Pi 4 Model B
Raspbian kernel 5.4
=====

ついでにメモリ容量確認(メガバイト単位でトータル)

pi@titan:~ $ free -mt
              total        used        free      shared  buff/cache   available
Mem:           3776         180        3200          41         395        3417
Swap:          2047           0        2047
Total:         5824         180        5248

4GBモデルっすね
うちにはいつの間にかラズパイが増えたの重要


サーモセンサのはんだ付け

ここで届いたセンサーをみてみましょう
パーツがバラバラで届いたので、まずははんだ付けからやってやる必要があります
f:id:konchangakita:20201111221722p:plain:w220 f:id:konchangakita:20201111210831p:plain:w220

もちろん、はんだごて持ってるわけなもく新しく購入
20年ぶりくらいのはんだ付け\(^o^)/うーん
f:id:konchangakita:20201111211217p:plain


MLX90614ESF セットアップ

まずはセンサー部分がまるい方の安かった方からトライしてみます
MLX90614ESFのデータシート
https://docs.rs-online.com/bc45/A700000006488813.pdf

ラズパイと結線

「VIN, GND, SCL, SDA」をそれぞれ「3.3V, GND, SCL, SDA」とケーブリング
f:id:konchangakita:20201111212311p:plain:w220 f:id:konchangakita:20201111212539p:plain:w220

ラズパイの本体設定

ラズパイに電源を入れ、I2C(IIC)機器を扱うためのセットアップを行います
(IICがなんぞやってのはググってください)
Raspberry Pi の設定から I2CSPI を有効にする(デフォルト無効になっている)
f:id:konchangakita:20201110223139p:plain:w300
f:id:konchangakita:20201111171550p:plain

そして、リブート

I2Cの認識

リブート後、ラズパイ側で接続されているバス番号を確認

$ ls /dev/i2c*
/dev/i2c-1

I2Cデバイスをラズパイで扱うには、そのi2c機器固有のデバイスアドレスが必要になります
下記コマンドを叩いてアドレス検索します
(I2Cを有効にするとこのコマンド使えるはず)

$ 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: -- -- -- -- -- -- -- -- -- -- 5a -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

バイスアドレス = 0x5a というのが分かります

このアドレスをもって Python からセンサーからの情報を取得します
python で I2C通信には、smbusライブラリを使います
コネクションオブジェクト取得:smbus.SMBus(バス番号)
センサーデータ読み込みwrite_i2c_block_data(デバイスアドレス, コマンド, バイト数)
<コマンド>
 ・周辺温度 (0x06)
 ・赤外線センサ (0x07)

こんな感じで何らかの数値が出力されればOK

$ python3
>>> import smbus
>>> i2c = smbus.SMBus(1)  #バス番号
>>> i2c.read_i2c_block_data(0x5a,0x6,3) 
[106, 58, 193]


温度の取得

絶対温度(よくわかってない)で読み出されているので。摂氏℃に直すために、0.02を掛けて273.15を引きます

ラスパイ上でこんな感じの python プログラム を実行すれば、温度がとれます

Ambient Temp(外気温)、Object Temp(対象物温度)

$ python3 MLX90614ESF.py 
Ambient Temp: 23.29  Object Temp: 27.35
Ambient Temp: 23.31  Object Temp: 25.55
Ambient Temp: 23.27  Object Temp: 25.41
Ambient Temp: 23.29  Object Temp: 34.15
Ambient Temp: 25.25  Object Temp: 34.45
Ambient Temp: 25.27  Object Temp: 34.01

これくらい近づけてようやく 34℃
f:id:konchangakita:20201111210338p:plain

少々離したしても、安定した数値がとれるので、キャリブレーションして非接触温度計として使えそう


離れたとこの温度測定用にこんなオプションもあるんだなー
たっかいけど
f:id:konchangakita:20201208231522p:plain
Amazon.co.jp: GY-906-DCI


AMG8833サーモセンサ

次は高かった方(約3倍)の AMG8833 では、どんなことができるか確認していきます
データシートを確認してみますと、Panasonic製なんだーって初めて知る
https://www.mouser.jp/datasheet/2/315/panasonic_04262016_AMG88-1480161.pdf

基本的に接続方法は、上で先ほど試した MLX90614ESF と同じ接続で OK の模様
f:id:konchangakita:20201112225208p:plain:w400

データ取得のためのライブラリをインストール

まずはセンサーデータを読み込む為に追加のライブラリをインストールします

busio ライブラリをインストール

$ pip3 install adafruit-blinka
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting adafruit-blinka
  Downloading https://www.piwheels.org/simple/adafruit-blinka/Adafruit_Blinka-5.7.0-py3-none-any.whl (136kB)
    100% |████████████████████████████████| 143kB 114kB/s 
Collecting Adafruit-PlatformDetect>=2.18.1 (from adafruit-blinka)
  Downloading https://www.piwheels.org/simple/adafruit-platformdetect/Adafruit_PlatformDetect-2.21.0-py3-none-any.whl
Collecting pyftdi>=0.40.0 (from adafruit-blinka)
  Downloading https://files.pythonhosted.org/packages/b8/d4/5f8215300b1c8849ae3b614a3126edd6f940571f1ce24c175b6ccad8c3df/pyftdi-0.52.0-py3-none-any.whl (150kB)
    100% |████████████████████████████████| 153kB 404kB/s 
Requirement already satisfied: RPi.GPIO in /usr/lib/python3/dist-packages (from adafruit-blinka) (0.7.0)
Collecting Adafruit-PureIO>=1.1.7 (from adafruit-blinka)
  Downloading https://www.piwheels.org/simple/adafruit-pureio/Adafruit_PureIO-1.1.7-py3-none-any.whl
Collecting rpi-ws281x>=4.0.0 (from adafruit-blinka)
  Downloading https://files.pythonhosted.org/packages/66/03/bda698d5429b918e1ef5acfb3d745d3a12c8fec8078925f10e571aa0a8e2/rpi_ws281x-4.2.5-cp37-cp37m-linux_armv7l.whl (115kB)
    100% |████████████████████████████████| 122kB 521kB/s 
Collecting sysv-ipc (from adafruit-blinka)
  Downloading https://www.piwheels.org/simple/sysv-ipc/sysv_ipc-1.0.1-cp37-cp37m-linux_armv7l.whl (68kB)
    100% |████████████████████████████████| 71kB 13kB/s 
Requirement already satisfied: pyserial>=3.0 in /usr/lib/python3/dist-packages (from pyftdi>=0.40.0->adafruit-blinka) (3.4)
Collecting pyusb>=1.0.0 (from pyftdi>=0.40.0->adafruit-blinka)
  Downloading https://www.piwheels.org/simple/pyusb/pyusb-1.1.0-py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 19kB/s 
Installing collected packages: Adafruit-PlatformDetect, pyusb, pyftdi, Adafruit-PureIO, rpi-ws281x, sysv-ipc, adafruit-blinka
Successfully installed Adafruit-PlatformDetect-2.21.0 Adafruit-PureIO-1.1.7 adafruit-blinka-5.7.0 pyftdi-0.52.0 pyusb-1.1.0 rpi-ws281x-4.2.5 sysv-ipc-1.0.1


adafruit-circuitpython-amg88xx ライブラリのインストール

$ pip3 install adafruit-circuitpython-amg88xx
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting adafruit-circuitpython-amg88xx
  Downloading https://www.piwheels.org/simple/adafruit-circuitpython-amg88xx/adafruit_circuitpython_amg88xx-1.2.4-py3-none-any.whl
Collecting adafruit-circuitpython-register (from adafruit-circuitpython-amg88xx)
  Downloading https://www.piwheels.org/simple/adafruit-circuitpython-register/adafruit_circuitpython_register-1.9.1-py3-none-any.whl
Requirement already satisfied: Adafruit-Blinka in ./.local/lib/python3.7/site-packages (from adafruit-circuitpython-amg88xx) (5.7.0)
Collecting adafruit-circuitpython-busdevice (from adafruit-circuitpython-amg88xx)
  Downloading https://www.piwheels.org/simple/adafruit-circuitpython-busdevice/adafruit_circuitpython_busdevice-5.0.1-py3-none-any.whl
Requirement already satisfied: sysv-ipc in ./.local/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (1.0.1)
Requirement already satisfied: Adafruit-PlatformDetect>=2.18.1 in ./.local/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (2.21.0)
Requirement already satisfied: rpi-ws281x>=4.0.0 in ./.local/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (4.2.5)
Requirement already satisfied: pyftdi>=0.40.0 in ./.local/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (0.52.0)
Requirement already satisfied: Adafruit-PureIO>=1.1.7 in ./.local/lib/python3.7/site-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (1.1.7)
Requirement already satisfied: RPi.GPIO in /usr/lib/python3/dist-packages (from Adafruit-Blinka->adafruit-circuitpython-amg88xx) (0.7.0)
Requirement already satisfied: pyserial>=3.0 in /usr/lib/python3/dist-packages (from pyftdi>=0.40.0->Adafruit-Blinka->adafruit-circuitpython-amg88xx) (3.4)
Requirement already satisfied: pyusb>=1.0.0 in ./.local/lib/python3.7/site-packages (from pyftdi>=0.40.0->Adafruit-Blinka->adafruit-circuitpython-amg88xx) (1.1.0)
Installing collected packages: adafruit-circuitpython-register, adafruit-circuitpython-busdevice, adafruit-circuitpython-amg88xx
Successfully installed adafruit-circuitpython-amg88xx-1.2.4 adafruit-circuitpython-busdevice-5.0.1 adafruit-circuitpython-register-1.9.1


AMG8833 の i2c機器固有のデバイスアドレスを確認

$ 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: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --   

バイスアドレス = 0x69

こちらの Example Code を参考にとりあえずテストしてみます
Raspberry Pi Thermal Camera | Adafruit AMG8833 8x8 Thermal Camera Sensor | Adafruit Learning System

$ python3
>>> import time
>>> import busio
>>> import board
>>> import adafruit_amg88xx
>>> 
>>> # I2Cバス、センサーの初期化
... i2c_bus = busio.I2C(board.SCL, board.SDA)
>>> sensor = adafruit_amg88xx.AMG88XX(i2c_bus, addr=0x69)
>>> 
>>> # ちょっと待つ
... time.sleep(.1)
>>> 
>>> sensor.pixels
[[21.25, 21.25, 21.75, 21.5, 21.5, 21.75, 21.75, 22.0], [21.5, 21.25, 21.5, 22.25, 21.5, 21.5, 21.75, 22.0], [22.0, 21.25, 21.25, 21.5, 21.75, 21.75, 21.5, 21.5], [21.5, 21.75, 21.25, 21.5, 21.75, 21.75, 22.0, 21.5], [20.75, 21.25, 21.25, 21.75, 21.0, 22.0, 21.75, 21.75], [21.25, 21.0, 21.25, 21.25, 21.5, 23.25, 22.0, 21.0], [21.25, 21.25, 21.25, 21.5, 24.0, 24.75, 23.0, 20.5], [21.25, 20.5, 21.5, 23.5, 24.25, 22.75, 22.0, 21.0]]
>>> 

8x8 の数字配列が返ってきているので、なんだかいけてるぽい


matplotlib で色つけて可視化してみましょう
ラズパイのデスクトップ上で実行してみます
(グラフ表示するためにはコンソール上で!)

import time
import busio
import board
import adafruit_amg88xx

import matplotlib.pyplot as plt

# I2Cバス、センサーの初期化
i2c_bus = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_amg88xx.AMG88XX(i2c_bus, addr=0x69)

# ちょっと待つ
time.sleep(.1)

# ループ開始
while True:
    # データ取得
    sensordata = sensor.pixels

    # bicubicのデータ
    fig = plt.imshow(sensordata, cmap="inferno", interpolation="bicubic")
    plt.colorbar()

    # wait代わりに pause
    plt.pause(.1)
    plt.clf()

うん、なんだかぽい感じ



取得した温度から max値をグラフ上に追記までの Python プログラム

f:id:konchangakita:20201113225527p:plain

30cmくらい離れると実体温と -10℃くらいの誤差がありますが、こちらも安定した数値が取れるので、距離センサーなどを入れてキャリブレーション(数値の調整)をいれてやれば体温センサーで使えます
KPS でマスク検知モデルと組み合わせて表示させてみようか


ただ、こちらを見るとずっと起動させていると、機器自身が熱をもって少々ブレがある模様ですね
実用化の壁は少しありそ
raspi-katsuyou.com