Thermography AMG8833의 데이터를 Python으로 실시간으로 시각화

소개



이 기사는, 8x8의 적외선 어레이 센서 「AMG8833」을 Arduino로부터 이용해, 그 데이터를 리얼타임에 PC에 송신해 Python(PyQt5, PyQtGraph)로 가시화했을 때의 기록입니다.

아래 이미지와 같은 느낌으로 실시간으로 시각화하고 있습니다.

Arduino



Arduino는 열화상 데이터를 검색하고 PC (Python)에 직렬 통신으로 전송합니다.

AMG8833



이번에는 스위치 과학 Conta™ 써모그래피 AMG8833 탑재을 사용하고 있습니다.

스위치 과학에 따르면

각 소자마다의 온도 측정 범위는 0℃~80℃입니다. 측정 영역은 센서 정면(상하 좌우 약 60도)의 사각추로, 이 영역을 8x8픽셀로 분할한 2차원 화상을 얻을 수 있습니다.

또한 AMG8833을 쉽게 사용할 수 있도록 Conta™ 베이스 실드을 이용하고 있습니다.

데이터 획득 및 전송



스위치 과학 페이지에는 AMG8833 라이브러리가 포함되어 있지만 SparkFun SparkFun_GridEYE_Arduino_Library을 사용합니다. 다음 프로그램은 샘플 프로그램을 약간 변경했습니다.

시리얼 통신에서는, 8x8=64개의 온도 데이터를 「,」단락의 캐릭터 라인으로서 송신하고 있습니다.

amg8833-serial.ino
#include <SparkFun_GridEYE_Arduino_Library.h>
#include <Wire.h>

float pixelTable[64];

GridEYE grideye;

void setup() {
  Wire.begin();
  // スイッチサイエンスのAMG8833のアドレスはデフォルトでは0x68に設定されている.
  grideye.begin(0x68);
  Serial.begin(115200);
}

void loop() {
  // 8x8=64個のピクセルに対して温度を取得しgrideyeに保存する.
  for(unsigned char i = 0; i < 64; i++){
    pixelTable[i] = grideye.getPixelTemperature(i);
  }
  // すべてのピクセルの温度を","で区切り1行に並べてシリアル通信で送信する.
  for(unsigned char i = 0; i < 64; i++){
    Serial.print(pixelTable[i]);
    if(i != 63){
      Serial.print(",");
    }
  }
  Serial.println();
  delay(50);
}

파이썬



Arduino에서받은 온도 데이터를 기반으로 히트 맵을 실시간으로 표시합니다.

도서관


  • pyserial - 직렬 통신
  • numpy
  • pyqt5
  • pyqtgraph - 실시간 드로잉
  • (matplotlib) - 컬러 맵

  • 파이썬에서 데이터 시각화라고하면 matplotlib이지만 matplotlib로 실시간으로 화면을 업데이트하기에는 너무 무겁다는 단점이 있습니다. 따라서 matplotlib가 아닌 경량 pyqtgraph이라는 라이브러리를 사용합니다.

    이번에는 온도 데이터를 색상 (RGBA)으로 변환하기 위해 matpotlib의 일부를 사용합니다. pyqtgraph에서도 가까울 수는 있지만, 그 경우는 스스로 컬러 맵에 사용하는 색을 지정할 필요가 있는 것 같습니다. 여기서는 기본적으로 컬러 맵을 제공하는 matplotlib을 사용합니다.

    데이터 수신 및 히트맵 표시



    heatmap.py
    from pyqtgraph.Qt import QtGui, QtCore
    import matplotlib.cm as cm
    import matplotlib as mpl
    import pyqtgraph as pg
    import numpy as np
    import serial
    
    # ヒートマップを見やすくするためにTEMP_MAX=40.0に設定
    TEMP_MIN = 0.0
    TEMP_MAX = 40.0
    
    app = QtGui.QApplication([])
    
    win = pg.GraphicsLayoutWidget(show=True, title="AMG8833")
    win.resize(600,600)
    win.setWindowTitle('AMG8833')
    pg.setConfigOptions(antialias=True)
    
    view = win.addViewBox()
    view.setAspectLocked(True)
    
    img = pg.ImageItem(border='w')
    view.addItem(img)
    
    # 温度を色に変換するためのColor Map
    norm = mpl.colors.Normalize(vmin=TEMP_MIN, vmax=TEMP_MAX)
    cmap = cm.jet
    m = cm.ScalarMappable(norm=norm, cmap=cmap)
    
    # シリアル通信
    ser = serial.Serial("COM13", 115200, timeout=1)
    
    # 8x8の温度データ
    data = np.zeros((8, 8))
    
    def get_data():
        global data, ser
        if ser.in_waiting:
            # Arduinoからデータ受信
            # データ取得時には何かとエラーが出るので簡単に例外処理
            try:
                line = ser.readline().decode().strip()
                temps = [float(t) for t in line.split(",")]
                data = np.array(temps).reshape((8, 8))
            except:
                pass
    
    def update_plot():
        global img, data
        img.setImage(m.to_rgba(data))
    
    # 50msごとにデータ受信
    timer1 = QtCore.QTimer()
    timer1.timeout.connect(get_data)
    timer1.setInterval(50)
    timer1.start()
    
    # 100msごとにヒートマップ更新  
    timer2 = QtCore.QTimer()
    timer2.timeout.connect(update_plot)
    timer2.setInterval(100)
    timer2.start()
    
    if __name__ == '__main__':
        import sys
        if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
            QtGui.QApplication.instance().exec_()
    

    위 프로그램은 데이터 수신과 히트 맵 업데이트를 다른 QTimer로 나눕니다. 데이터를 수신 할 때마다 히트 맵을 업데이트하는 경우 히트 맵 업데이트가 시간에 맞지 않을 수 있습니다. 이를 방지하기 위해 별도로 데이터 수신과 히트 맵 업데이트를 개별적으로 할 수 있도록하고 있습니다.

    참고 링크


  • AMG8833의 데이터를 간이 서모그래피와 같이 브라우저로 시각화 (전편)
  • 좋은 웹페이지 즐겨찾기