Raspberry Pi 備忘録 / Mbedもあるよ!

Raspberry Pi であれこれやった事の記録

FLiR Dev Kit を試す その5

せっかくなので、ストリーミングしたい。

f:id:pongsuke:20171211181007p:plain

そこで、今までは Mjepg-streamer などを使ってきましたが、自分でゴリゴリいじるので、Python で実装しているサンプルを探したところ、有った!

Simple Python Motion Jpeg (mjpeg server) from webcam. Using: OpenCV,BaseHTTPServer · GitHub

まずは、USBカメラなどをさして、ストリームのチェックを行う。

おっけー

f:id:pongsuke:20171211175152p:plain

Lepton 向けに改変する

これは、 Mr Igor のスクリプトを書き換えています。

Simple Python Motion Jpeg (mjpeg server) from webcam. Using: OpenCV,BaseHTTPServer · GitHub

これね。

#!/usr/bin/python
from pylepton import Lepton

import cv2
import numpy as np
from PIL import Image
import threading
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from SocketServer import ThreadingMixIn
import StringIO
import time

class CamHandler(BaseHTTPRequestHandler):
        def do_GET(self):
                if self.path.endswith('.mjpg'):
                        self.send_response(200)
                        self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
                        self.end_headers()
                        try:
                                with Lepton() as l:
                                        while True:
                                                data_buffer, rc = l.capture()
                                                if not rc:
                                                        continue

                                                cv2.normalize(data_buffer, data_buffer, 0, 255, cv2.NORM_MINMAX)
                                                img = cv2.cvtColor(data_buffer, cv2.COLOR_GRAY2BGR)
                                                img[:, :, 0:2] = 0
                                                img = cv2.resize(img, (320,240))

                                                imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
                                                jpg = Image.fromarray(np.uint8(np.asarray(imgRGB)))
                                                tmpFile = StringIO.StringIO()
                                                jpg.save(tmpFile,'JPEG')
                                                self.wfile.write("--jpgboundary")
                                                self.send_header('Content-type','image/jpeg')
                                                self.send_header('Content-length',str(tmpFile.len))
                                                self.end_headers()
                                                jpg.save(self.wfile,'JPEG')
                                                time.sleep(0.2)

                        except Exception as e:
                                print('Exception', e.args);
                                brak

                if self.path.endswith('.html'):
                        self.send_response(200)
                        self.send_header('Content-type','text/html')
                        self.end_headers()
                        self.wfile.write('<html><head></head><body>')
                        self.wfile.write('<img src="http://127.0.0.1:8080/cam.mjpg"/>')
                        self.wfile.write('</body></html>')
                        return


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
        """Handle requests in a separate thread."""

def main():
        global img
        try:
                server = ThreadedHTTPServer(('localhost', 8080), CamHandler)
                print "server started"
                server.serve_forever()
        except KeyboardInterrupt:
                server.socket.close()

if __name__ == '__main__':
        main()

結果

f:id:pongsuke:20171211181007p:plain

TJBot

ケース

Watson Maker Kits

形状データをダウンロードできる。

とりあえず、プリントしてみよう。

FLiR Dev Kit を試す その4

画像を表示するだけなら今のままでも良いのですが、温度の算出をしたいので、Output frame に触れましょう。

触れたあとに、加工して、最後には画像にしたい、、、ので、Python + Opencv がお手軽ではないかと思っていたところ、素敵なサンプルコードを発見しました。

Python から キャプチャするコード

GitHub - groupgets/pylepton: Quick and dirty pure python library for interfacing with FLIR lepton

サンプルコード

import numpy as np
import cv2
from pylepton import Lepton

with Lepton() as l:
  a,_ = l.capture()
cv2.normalize(a, a, 0, 65535, cv2.NORM_MINMAX) # extend contrast
np.right_shift(a, 8, a) # fit data into 8 bits
cv2.imwrite("output.jpg", np.uint8(a)) # write it!

Lepton() で何が手に入って、Lepton.capture() で何が返ってくるのかを見ましょう。

  def capture(self, data_buffer = None, log_time = False, debug_print = False, retry_reset = True):
    """Capture a frame of data.
    Captures 80x60 uint16 array of non-normalized (raw 12-bit) data. Returns that frame and a frame_id (which
    is currently just the sum of all pixels). The Lepton will return multiple, identical frames at a rate of up
    to ~27 Hz, with unique frames at only ~9 Hz, so the frame_id can help you from doing additional work
    processing duplicate frames.
    Args:
      data_buffer (numpy.ndarray): Optional. If specified, should be ``(60,80,1)`` with `dtype`=``numpy.uint16``.
    Returns:
      tuple consisting of (data_buffer, frame_id)
    """

読みやすく改変

001.py

#!/usr/bin/env python
# -*- coding: utf-8 -*
import sys
import copy
import numpy as np
import cv2
from pylepton import Lepton

def main():
        with Lepton() as l:
                data_buffer, frame_id = l.capture()

        print("---data_buffer---")
        print(data_buffer[59:, 75:])
        print(data_buffer.shape)
        print(type(data_buffer))
        data_1d = data_buffer.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        # 変数のコピー
        data_8bit       = copy.deepcopy(data_buffer)
        data_normalized = copy.deepcopy(data_buffer)

        # data_normalized を正規化
        cv2.normalize(data_buffer, data_normalized, 0, 65535, cv2.NORM_MINMAX) # extend contrast
        # fit to 8 bit
        np.right_shift(data_8bit, 8, data_8bit)
        np.right_shift(data_normalized, 8, data_normalized)

        print("----data_8bit----")
        print(data_8bit[59:, 75:])
        print(data_8bit.shape)
        data_1d = data_8bit.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        print("---data_normalized---")
        print(data_normalized[59:, 75:])
        print(data_normalized.shape)
        data_1d = data_normalized.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        image_original  = np.uint8(data_8bit)
        image_gray              = np.uint8(data_normalized)
        image_rgb               = cv2.cvtColor(image_gray, cv2.COLOR_GRAY2BGR)
        image_org_rgb   = cv2.cvtColor(image_original, cv2.COLOR_GRAY2BGR)

        image_rgb[:, :, 0:2] = 0
        image_org_rgb[:, :, 0:2] = 0

        print("---image_rgb---")
        print(image_rgb[59:, 75:])
        print(image_rgb.shape)

        print("---image_org_rgb---")
        print(image_org_rgb[59:, 75:])
        print(image_org_rgb.shape)

        # リサイズ
        image_original  = cv2.resize(image_original, None, fx=4, fy=4)
        image_gray              = cv2.resize(image_gray, None, fx=4, fy=4)
        image_rgb               = cv2.resize(image_rgb, None, fx=4, fy=4)
        image_org_rgb   = cv2.resize(image_org_rgb, None, fx=4, fy=4)

        cv2.imshow("Leption original", image_original)
        cv2.imshow("Leption normalize", image_gray)
        cv2.imshow("Leption RGB", image_rgb)
        cv2.imshow("Leption org RGB", image_org_rgb)

        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == '__main__':
        main()

やってみる。

$ ./001.py 
---data_buffer---
[[[7915]
  [7916]
  [7919]
  [7908]
  [7904]]]
(60, 80, 1)
<type 'numpy.ndarray'>
MAX:8327, MIN:7671
----data_8bit----
[[[30]
  [30]
  [30]
  [30]
  [30]]]
(60, 80, 1)
MAX:32, MIN:29
---data_normalized---
[[[95]
  [95]
  [96]
  [92]
  [90]]]
(60, 80, 1)
MAX:255, MIN:0
---image_rgb---
[[[ 0  0 95]
  [ 0  0 95]
  [ 0  0 96]
  [ 0  0 92]
  [ 0  0 90]]]
(60, 80, 3)
---image_org_rgb---
[[[ 0  0 30]
  [ 0  0 30]
  [ 0  0 30]
  [ 0  0 30]
  [ 0  0 30]]]
(60, 80, 3)

f:id:pongsuke:20171208152356p:plain

f:id:pongsuke:20171208152401p:plain

f:id:pongsuke:20171208152410p:plain

f:id:pongsuke:20171208152415p:plain

たとえば、 output frame は 7904 でした。

0.026 * ( 7903 - 8192 ) + カメラの温度 = -7.488度 + カメラの温度

ってことかな?

正規化しないと、最小値が29で、最大値が32 なので、画像とはなりえない。ほぼ一色。
どこかのフォーラムにも書いてあったけど、範囲を決めて(摂氏 -20 ~ +100度など?)、その範囲外は 0 と 255 とみなして、120度の中範囲で 255 を使用したほうが良いかもしれない。
-20度 と +100度 における正規化 かな?

そうすれば、画像として見られたものに成って、かつ、出番の多そうな温度も拾える、、、かな?

やってみないとわからない。

-10度 +80度 を入れてみる

やってみた

強引ですが、output buffer を書き換えて、常に -10 と +80 が登場するようにして、それを 0~255 で正規化してみました。

左上の白と右上の黒が、それです。

#!/usr/bin/env python
# -*- coding: utf-8 -*
import sys
import copy
import numpy as np
import cv2
from pylepton import Lepton

def main():
        with Lepton() as l:
                data_buffer, frame_id = l.capture()

        print("---data_buffer---")
        print(data_buffer[59:, 75:])
        print(data_buffer.shape)
        print(type(data_buffer))
        data_1d = data_buffer.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        # 変数のコピー
        data_8bit       = copy.deepcopy(data_buffer)
        data_normalized = copy.deepcopy(data_buffer)

        # -10 +80 で上書き:基準値は 8192
        data_8bit[0,0,0]        = 7807 # -10度
        data_8bit[59,79,0]      = 11268 # +80度

        # 正規化
        cv2.normalize(data_8bit, data_8bit, 0, 255, cv2.NORM_MINMAX) # extend contrast
        cv2.normalize(data_normalized, data_normalized, 0, 255, cv2.NORM_MINMAX) # extend contrast

        print("----data_8bit----")
        print(data_8bit[59:, 75:])
        print(data_8bit.shape)
        data_1d = data_8bit.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        print("---data_normalized---")
        print(data_normalized[59:, 75:])
        print(data_normalized.shape)
        data_1d = data_normalized.ravel()
        print( 'MAX:%d, MIN:%d' % (np.max(data_1d), np.min(data_1d) ))

        image_original  = np.uint8(data_8bit)
        image_gray              = np.uint8(data_normalized)
        image_bgr               = cv2.cvtColor(image_gray, cv2.COLOR_GRAY2BGR)
        image_org_bgr   = cv2.cvtColor(image_original, cv2.COLOR_GRAY2BGR)

        image_bgr[:, :, 0:2] = 0
        image_org_bgr[:, :, 0:2] = 0

        print("---image_bgr---")
        print(image_bgr[59:, 75:])
        print(image_bgr.shape)

        print("---image_org_bgr---")
        print(image_org_bgr[59:, 75:])
        print(image_org_bgr.shape)

        # リサイズ
        image_original  = cv2.resize(image_original, None, fx=4, fy=4)
        image_gray              = cv2.resize(image_gray, None, fx=4, fy=4)
        image_bgr               = cv2.resize(image_bgr, None, fx=4, fy=4)
        image_org_bgr   = cv2.resize(image_org_bgr, None, fx=4, fy=4)

        cv2.imshow("Leption original", image_original)
        cv2.imshow("Leption normalize", image_gray)
        cv2.imshow("Leption RGB", image_bgr)
        cv2.imshow("Leption org RGB", image_org_bgr)
        # 保存
        cv2.imwrite("001.image_original.png", image_original)
        cv2.imwrite("001.image_gray.png", image_gray)
        cv2.imwrite("001.image_bgr.png", image_bgr)
        cv2.imwrite("001.image_org_bgr.png", image_org_bgr)

        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == '__main__':
        main()

最初から 255 で正規化しました。

f:id:pongsuke:20171208161207p:plain

f:id:pongsuke:20171208161212p:plain

この2つの画像では、真っ赤(右下)なら、カメラより+80度高く、真っ黒(左上)なら、カメラより10度低い事になります。

映像としては、面白みが無い。

熱湯が入ったカップを持って、撮影してみました。

室温は20度なので、おそらくカメラも20度前後。
お湯は電気ポットから出したばかりです。

f:id:pongsuke:20171208162047p:plain

f:id:pongsuke:20171208162042p:plain

Output buffer の最大値は 9664 だった。おそらくこれはコップ。

0.026 * (9664 - 8192) = 38.272

室温の20を足すと、 だいたい60度?

こうなってきたら、もうちょっと正確に温度を用意して、キャリブレーション(傾きを算出)してみたくもなる。

でも、正確に温度のわかっている物体って、どこにあるのだろか。

修正

cv2.COLOR_GRAY2RGB を指定しても、出力が BGR に成っていたので、 cv2.COLOR_GRAY2BGR に直しました。

FLiR Dev Kit を試す その3

FLiR Dev Kit を試す その3

まず、メモを残します。

I2C でセンサーから温度を取得する。

LEP_GetSysFpaTemperatureKelvin の返り値が何なのかわからない・・・。

FPA Temp In Kelvin x 100 とあるので、カメラの温度(Kelvin)の100倍の値っぽいのだが、、、。

FFC

フラットフィールド補正モード とは、なんぞや・・・

lepton3 の 国内販売

Lepton, Lepton 3.0, FLIR | コーンズ テクノロジーオンラインショップ

FAQ も有って、全くの無知なので、読むだけで何かしら得られる。

よくあるご質問 | サイトタイトル

データシートいわく

データシートいわく、4種の温度に関係した数字がありそうだ。

4.5.5 SYS AUX Temperature Kelvin
This command returns the Lepton Camera’s AUX Temperature in Kelvin. This value is from a thermistor located on the Lepton housing.

LEP_RESULT LEP_GetSysAuxTemperatureKelvin(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, LEP_SYS_AUX_TEMPERATURE_KELVIN_T_PTR auxTemperaturePtr);

4.5.6 SYS FPA Temperature Kelvin
This command returns the Lepton Camera’s FPA Temperature in Kelvin.

LEP_RESULT LEP_GetSysFpaTemperatureKelvin(LEP_CAMERA_PORT_DESC_T_PTR portDescPtr, LEP_SYS_FPA_TEMPERATURE_KELVIN_T_PTR fpaTemperaturePtr)

そもそも、FPA とは、なんだろうか?

フォーカルプレーンアレイ (Focal Plane Arrays; FPA)

SDK の DOC いわく

How to install FLIR Lepton Thermal Camera and applications on Raspberry Pi - Appropedia: The sustainability wiki

カメラ内部温度

internal temperature of the camera. という表現が出て来る。
カメラ内部の温度かな?

そして、The output frame for the internal temperature is 8192 とある。

カメラの内部温度 = 8192 なので、2の13乗 ですね。

output frame 0 = 0 kelvin なら話は早いんだけど、どうやらそうではなさそう?原点は通らないのかな。

最高温度と最低温度

Lepton Thread.h をよめば、取得方法がわかるよ! とか書いてある。

・・・単純に全てのフレームバッファの最小値・最大値を保存してた。それだけだった。

value = frameBuffer[i];
if(value > maxValue) {
    maxValue = value;
}
if(value < minValue) {
    minValue = value;
}

そして、画像のために、最小値:0 ~ 最大値:255 で、正規化している。
RGG とかにしやすいからかな。

rawデータを取得すると、 pgm フォーマットで、数字がダイレクトに入っている。

MAX Output frame = 最高温度
MIN Output frame = 最低温度

温度の算出

1.センサー自体の温度が手に入り、その温度の Frame を 8192 とする。

2.Experimental な温度と、Frame を手に入れる。

3.その2点で、線形回帰する

のかな?

その、角度ですが、0.0217 だとか、0.026 だとか書いている人がいる。

大体そうだとしたら、

温度 = 0.026 * ( OutputFrame - 8192 ) + カメラの温度

になるのかな???

とあるピクセルの OutputFrame 20000 だとしたら、

0.026 * ( 20000 - 8192 ) + カメラの温度 = 307 度 + カメラの温度 かな。

画像のために正規化する前の 生の OutputFrame を見てみないとわからない。

FLiR Dev Kit を試す その2

続きです。

基本的に、下記の記事に従います。

FLIR Lepton Hookup Guide - learn.sparkfun.com

カメラデバイスの組み込み

f:id:pongsuke:20171206180805j:plain

カメラモジュールを、breakout board に、突起の向きに注意しながら刺す。

ワイヤリング

f:id:pongsuke:20171206181132p:plain

Rpi3 と breakout board が、どちらもオスなので、
メス・メスのジャンパー・ケーブルが必要になりますが、あまり持っていないと思います。

私は、QIコネクタとハウジングを持っていたので作りましたが、みんなどうするんだろう。
速攻でハンダ付けするのでしょうか。

本体の設定

SPI, I2C を 有効にする

raspi-config から2つを有効にする。

プログラムの準備

GitHub - groupgets/LeptonModule: Code for getting started with the FLIR Lepton breakout board

からファイルを取得します。

ガイドにzipでダウンロードしたら?的に書いてあるので、従いました。

解凍する。

$ unzip LeptonModule-master.zip

コンパイル

$ cd cd LeptonModule-master/software/raspberrypi_libs/leptonSDKEmb32PUB/
$ make

$ cd ../../raspberrypi_video/
$ qmake && make

動作確認

$ sudo ./raspberrypi_video 
X Error: BadAccess (attempt to access private resource denied) 10
  Extension:    130 (MIT-SHM)
  Minor opcode: 1 (X_ShmAttach)
  Resource id:  0x191
X Error: BadShmSeg (invalid shared segment parameter) 128
  Extension:    130 (MIT-SHM)
  Minor opcode: 5 (X_ShmCreatePixmap)
  Resource id:  0x1a0000b
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x1a0000c
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x1a0000c

エラーが出てしまう。

sudo なしでやってみる。

$ ./raspberrypi_video

・・・ドキュメントにもある、エーラ状態が出た。

f:id:pongsuke:20171207115805p:plain

原因とその後

何をやっても動かないので、I2Cが動いていないのではないかと色々考えているうちに、3時間経過し、ふと気が付きました。

基盤の上下が逆だ!

久しぶりに触ったので、上下(どっちがPin1か)を間違えていました・・・。

んで、結果がこれ。

f:id:pongsuke:20171207135850p:plain

その後、何度か起動しようとしますが、エラー画面になる。
何が原因なのだろうか。

OSの電源を抜いてから起動すると、治ったりする。
reboot コマンドでは治らない)
なんだろうか。

Forum で話題になっているとおり、カメラモジュールのリセットが必要なのかもしれない。

SPIDEV について

各種ファイルで、 spidev が 0 なのか 1 なのかを指定する場所があったりしますが、

私の環境では、/dev/spidev0.0 でした。

久しぶりに Raspbianをインストールしてみる / VNC が改善!

色々変わったと思うので、備忘録を作り直します。

Raspberry pi 3 model b に、Raspbian を入れます。

VNCがちゃんと起動しました。

OSの準備まで

OS img の取得

Download Raspbian for Raspberry Pi

2017-12-06 の時点で RASPBIAN STRETCH WITH DESKTOP Version:November 2017 でした。

ダウンロードした zip を展開して、img ファイルを取得します。

micro sd カードのフォーマット

SD Memory Card Formatter でフォーマットします。

SDメモリカードフォーマッター for Windows Download - SD Association

インストール後のプログラム名は、 SD Card Fromatter です。
Start Menu から起動する場合は注意です。

img を焼く

Win32DiskImager で焼きます。

Win32 Disk Imager download | SourceForge.net

OS起動後

ファームウェアのアップデート

$ sudo rpi-update
$ reboot

パッケージリストの更新、 インストールされてるパッケージの更新

$ sudo apt-get update
$ sudo apt-get upgrade

raspi-config からの設定

  1. piにパスワードを設定する

  2. Boot Option から、起動時に CLI(コマンドライン)自動ログインなし にしておいた。

ログイン後、必要に応じて startx する。

  1. Localization Options
  2. Change locale Ja_JP.UTF-8 UTF-8
  3. Timezone Asia-tokyo
  4. Change Wi-fi Country - jp

SSH ON

$ sudo systemctl enable ssh
$ sudo systemctl start ssh

root パスワード設定と、新規ユーザー作成、グループ所属、sudoers 設定

危ないので、root のパスワードも変更します。

$ sudo su -
# passwd

また、username が判明しているだけでも嫌なので、pi は使わずに、新規に user を作ります。
その際、各種グループに所属させておかないと、音がならなかったりします。(昔はそうだった)

なお、useradd で作成すると、ログインシェルの設定ファイルなどが作成されないので、adduser が良さそうです。

$ sudo adduser USERNAME

$ groups pi
pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio
$ sudo usermod -G pi,adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,spi,i2c,gpio USERNAME

$ sudo visudo
(末尾に以下を追記)
USERNAME  ALL=NOPASSWD: ALL

IP を固定する

/etc/dhcpcd.conf を編集し、下記を追記します。

interface eth0
static ip_address=192.168.100.88/24
static routers=192.168.100.1
static domain_name_servers=192.168.100.1

音の設定

Control の確認
$ amixer controls
numid=3,iface=MIXER,name='PCM Playback Route'
numid=2,iface=MIXER,name='PCM Playback Switch'
numid=1,iface=MIXER,name='PCM Playback Volume'
numid=5,iface=PCM,name='IEC958 Playback Con Mask'
numid=4,iface=PCM,name='IEC958 Playback Default'
アナログに設定
$ amixer cset numid=3 1
usb で鳴らしてみる

バイスの確認をして、aplay, mpeg321 で試します。
omxplayer は、usbに音をだすことはできなかったはず。

$ lsusb
Bus 001 Device 004: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 005: ID 041e:323d Creative Technology, Ltd 
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$ aplay -D plughw:1,0 /usr/share/scratch/Media/Sounds/Vocals/Singer1.wav

$ sudo apt-get install mpg321
$ mpg321 -o alsa -a hw:1 some.mp3

$ sudo apt-get install mplayer
$ mplayer -ao alsa:device=plughw=1.0 example.mp3
omxplayer
$ omxplayer **.mp4

VNC の設定

raspi-config

  1. Interface options
  2. P3 VNC

から、有効にする。

それから、デスクトップの右上のVNCアイコンから、

VNC Options ->Troubleshooting -> Enable experimental direct capture mode

そして、再起動。

windowsvnc viewer で、IPを設定して接続すると、ログイン画面からちゃんと出てきました。

f:id:pongsuke:20171206172133p:plain

スクリーンショットを撮る

vnc viewer で、 Properties > Options > keys の Pass special keys directly to VNC Server を OFF にすれば、Print Screen のボタンが Windows サイドで動くみたいです。

f:id:pongsuke:20171206172412p:plain

f:id:pongsuke:20171206172430p:plain

FLiR Dev Kit を試す その1

FLiR Dev Kit を試します。

f:id:pongsuke:20171205130719j:plain

f:id:pongsuke:20171205130732j:plain

これなに?

FLiR とは、前方監視型赤外線(forward looking infra-red)の略称らしいです。

モノ

スイッチサイエンスから購入しました。

www.switch-science.com

電源電圧: 3~5V
センサ形式: LWIR(8 ~ 14 μm)
画角: 水平視野51度、対角63.5度
解像度: 80 × 60
最小感度: 50mK
インターフェース(映像): MIPIもしくはSPI
インターフェース(制御): I2C
素早い応答性 (< 0.5 sec)
省電力: 通常150mW、最大160mW未満

メーカのガイド

FLIR Lepton Hookup Guide - learn.sparkfun.com

参考コード

GitHub - groupgets/LeptonModule: Code for getting started with the FLIR Lepton breakout board

斜め読みメモ

動作が不安定でも、モジュールの物理的な抜き差しはしない。
CSの接続先を 40PIN → 38PIN に変えればOKらしい。(未確認)