TJBot
ケース
形状データをダウンロードできる。
とりあえず、プリントしてみよう。
3Dプリンター不調で頓挫・・・しましたが、調整し直してプリントしました。 パーツ
組んで
組んで
こうなる
スケルトンだと、ターミネーターみたいで、なんか怖い。
特に目が!
カメラ
カメラの向き
youtube を見る限り、そして、実際にはめ込んでみたぴったり感からして、どうやら上下逆向きに(ケーブルを上向きに)設置するようだ。
逆向きに刺そうとすると、どうしてもリボンケーブルのコネクタが鑑賞して刺さらないのだ。
なので、撮影の際などには、-vf, --vflip : Set vertical flip
オプションを付ける。
カメラの動作確認
$ raspistill -w 480 -h 360 -n -vf -o mod.jpg
サーボモーター(腕)
とりあえず動かしてみよう。
以前書いたコードをそのまま使ってみた。
SG92.py
#!/usr/bin/python # coding: utf-8 import RPi.GPIO as GPIO import time import signal import sys gp_out = 21 def exit_handler(signal, frame): print("\nExit") servo.ChangeDutyCycle(2.5) time.sleep(0.5) servo.stop() GPIO.cleanup() sys.exit(0) signal.signal(signal.SIGINT, exit_handler) GPIO.setmode(GPIO.BCM) GPIO.setup(gp_out, GPIO.OUT) # pwm = GPIO.PWM([チャンネル], [周波数(Hz)]) servo = GPIO.PWM(gp_out, 50) servo.start(0.0) val = [2.5,3.6875,4.875,6.0625,7.25,8.4375,9.625,10.8125,12] servo.ChangeDutyCycle(val[0]) time.sleep(0.5) servo.ChangeDutyCycle(val[8]) time.sleep(0.5) servo.ChangeDutyCycle(val[0]) time.sleep(0.5) while True: for i, dc in enumerate(val): servo.ChangeDutyCycle(dc) print("Angle:" + str(i*22.5)+" dc = %.4f" % dc) time.sleep(0.5) for i, dc in enumerate( reversed(val) ): servo.ChangeDutyCycle(dc) print("Angle:" + str(180 - i*22.5)+" dc = %.4f" % dc) time.sleep(0.5)
フルカラーLED
フルカラーLEDを触るのが今回が初めてです。
手元にあるのは カソードコモン
のフルカラーLEDです。
左から、緑、青、共通カソード、赤 ですね。
挿して、520Ωの抵抗を付けました。
グラデーションさせるテスト
https://making.mrlittlebig.com/raspberry-pi-2-フルカラーledをグラデーション-5e4916fda419
こちらのコードを、中断できるように改変させていただきました。
#!/usr/bin/python # coding: utf-8 import RPi.GPIO as GPIO import time import signal import sys def exit_handler(signal, frame): print("\nExit") red.stop() green.stop() blue.stop() time.sleep(0.5) GPIO.cleanup() sys.exit(0) signal.signal(signal.SIGINT, exit_handler) Rpin = 13 Bpin = 19 Gpin = 26 GPIO.setmode(GPIO.BCM) GPIO.setup(Rpin,GPIO.OUT) GPIO.setup(Bpin,GPIO.OUT) GPIO.setup(Gpin,GPIO.OUT) red = GPIO.PWM(Rpin, 50) green = GPIO.PWM(Gpin, 50) blue = GPIO.PWM(Bpin, 50) red.start(0) green.start(0) blue.start(0) blue.ChangeDutyCycle(100) COUNT = 100 T = 0.04 I = 0 time.sleep(0.5) for _ in xrange(0, COUNT): red.ChangeDutyCycle(I) blue.ChangeDutyCycle(100 - I) time.sleep(T) I+=1 I = 0 for _ in xrange(0, COUNT): red.ChangeDutyCycle(100-I) green.ChangeDutyCycle(I) I+=1 time.sleep(T) I = 0 for _ in xrange(0, COUNT): green.ChangeDutyCycle(100 - I) blue.ChangeDutyCycle(I) I+=1 time.sleep(T) time.sleep(0.5) red.stop() green.stop() blue.stop() GPIO.cleanup()
拡散キャップをかぶせました。
マイク
$ lsusb $ lsusb Bus 001 Device 004: ID 8086:0808 Intel Corp. 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
Intel Corp とのだけ認識されているけど、大丈夫かな?
$ arecord -l **** ハードウェアデバイス CAPTURE のリスト **** カード 1: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio] サブデバイス: 1/1 サブデバイス #0: subdevice #0
録音テスト
$ arecord -D plughw:1,0 -d 5 test.wav 録音中 WAVE 'test.wav' : Unsigned 8 bit, レート 8000 Hz, モノラル kiyo@raspberrypi:~ $ aplay -D plughw:0,0 test.wav 再生中 WAVE 'test.wav' : Unsigned 8 bit, レート 8000 Hz, モノラル
なお、スピーカーが片方しかない状態(アナログout の2局のうち片方しか配線して居ない状態)なので、モノラルで進めています。
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)
たとえば、 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 で正規化しました。
この2つの画像では、真っ赤(右下)なら、カメラより+80度高く、真っ黒(左上)なら、カメラより10度低い事になります。
映像としては、面白みが無い。
熱湯が入ったカップを持って、撮影してみました。
室温は20度なので、おそらくカメラも20度前後。
お湯は電気ポットから出したばかりです。
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 いわく
カメラ内部温度
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
カメラデバイスの組み込み
カメラモジュールを、breakout board に、突起の向きに注意しながら刺す。
ワイヤリング
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
・・・ドキュメントにもある、エーラ状態が出た。
原因とその後
何をやっても動かないので、I2Cが動いていないのではないかと色々考えているうちに、3時間経過し、ふと気が付きました。
基盤の上下が逆だ!
久しぶりに触ったので、上下(どっちがPin1か)を間違えていました・・・。
んで、結果がこれ。
その後、何度か起動しようとしますが、エラー画面になる。
何が原因なのだろうか。
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 からの設定
ログイン後、必要に応じて startx
する。
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
- Interface options
- P3 VNC
から、有効にする。
それから、デスクトップの右上のVNCアイコンから、
VNC Options ->Troubleshooting -> Enable experimental direct capture mode
そして、再起動。
windows の vnc viewer で、IPを設定して接続すると、ログイン画面からちゃんと出てきました。
スクリーンショットを撮る
vnc viewer で、 Properties > Options > keys の Pass special keys directly to VNC Server
を OFF にすれば、Print Screen のボタンが Windows サイドで動くみたいです。
FLiR Dev Kit を試す その1
FLiR Dev Kit を試します。
これなに?
FLiR とは、前方監視型赤外線(forward looking infra-red)の略称らしいです。
モノ
スイッチサイエンスから購入しました。
電源電圧: 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らしい。(未確認)
NFCリーダーライター PaSoRi を試す
手元にあるのは RC-S370で、現在は生産が終了しているモデルですね。
認識
$ lsusb Bus 001 Device 004: ID 041e:323d Creative Technology, Ltd Bus 001 Device 005: ID 054c:02e1 Sony Corp. FeliCa S330 [PaSoRi] 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. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Sony Corp. FeliCa S330 [PaSoRi]
と認識されています。
nfcpy
nfcpy を使います。
ドキュメントはこちら
Getting started — nfcpy 0.13.0 documentation
インストール
$ sudo pip install nfcpy ・・・ Successfully installed nfcpy ndeflib pydes libusb1 Cleaning up...
動作確認
$ python -m nfc This is the 0.13.0 version of nfcpy run in Python 2.7.9 on Linux-4.9.28-v7+-armv7l-with-debian-8.0 I'm now searching your system for contactless devices ** found usb:054c:02e1 at usb:001:005 but access is denied -- the device is owned by 'root' but you are 'kiyo' -- also members of the 'root' group would be permitted -- you could use 'sudo' but this is not recommended -- better assign the device to the 'plugdev' group sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"02e1\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules' sudo udevadm control -R # then re-attach device I'm not trying serial devices because you haven't told me -- add the option '--search-tty' to have me looking -- but beware that this may break other serial devs Sorry, but I couldn't find any contactless device
指示が出ているので従う。
$ sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"02e1\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules' $ sudo udevadm control -R
もう一度・・・
$ python -m nfc This is the 0.13.0 version of nfcpy run in Python 2.7.9 on Linux-4.9.24-v7+-armv7l-with-debian-8.0 I'm now searching your system for contactless devices I'm not trying serial devices because you haven't told me -- add the option '--search-tty' to have me looking -- but beware that this may break other serial devs Sorry, but I couldn't find any contactless device
おや?
RC-S380/P でやりなおす
特に対応から外れているわけでも無いので、手元にあるPaSoRiが壊れていのかもしれない、、、ということで、新しい PaSoRi を買い直しました。
RC-S380/P を刺して、、、
This is the 0.13.0 version of nfcpy run in Python 2.7.9 on Linux-4.9.28-v7+-armv7l-with-debian-8.0 I'm now searching your system for contactless devices ** found SONY RC-S380/P NFC Port-100 v1.11 at usb:001:010 I'm not trying serial devices because you haven't told me -- add the option '--search-tty' to have me looking -- but beware that this may break other serial devs
よし。
やはり、手元の S370 は、古くて壊れていたのかな?
git のサンプルを動かす
スイカを乗せて・・・
$ git clone https://github.com/nfcpy/nfcpy.git $ cd nfcpy $ python examples/tagtool.py [nfc.clf] searching for reader on path usb [nfc.clf] using SONY RC-S380/P NFC Port-100 v1.11 at usb:001:010 ** waiting for a tag ** Type3Tag 'FeliCa Standard (RC-S915)' ID=*** PMM=*** SYS=***
データを読み書きする
まず、メディア?を入手します。
アマゾンで買ったこれは、素直に動いてくれました。
先に書くと、フォーマットをして、NDEF 対応にしないと NDEF のやり取りが来ません。
NDEFフォーマットに成功したメディア達
フォーマット
format.py
import nfc def on_connect(tag): print("format:", tag.format()) clf = nfc.ContactlessFrontend('usb') if clf: print("Clf: {}".format(clf)) clf.connect(rdwr={ 'on-connect': on_connect }) clf.close()
実行
$ python format.py Clf: SONY RC-S380/P on usb:001:010 ('format:', True)
データの読み取り
messageに入っているデータを読み込みます。
フォーマットしただけだと、空っぽです。
import nfc def on_startup(targets): print("on_startup()") return targets def on_connect(tag): print("Tag: {}".format(tag)) print("Tag type: {}".format(tag.type)) #print '\n'.join(tag.dump()) if tag.ndef: print tag.ndef.message.pretty() #return True def on_release(tag): print("on_release()") if tag.ndef: print(tag.ndef.message.pretty()) clf = nfc.ContactlessFrontend('usb') if clf: print("Clf: {}".format(clf)) clf.connect(rdwr={ 'on-startup': on_startup, 'on-connect': on_connect, 'on-release': on_release }) clf.close()
実行
$ python 001.py Clf: SONY RC-S380/P on usb:001:010 on_startup() Tag: Type3Tag 'FeliCa Lite-S (RC-S966)' ID=_ID_ PMM=_PMM_ SYS=88B4 Tag type: Type3Tag record 1 type = '' name = '' data = ''
書き込み
書き込んで、確認してみる。
import nfc def on_startup(targets): print("on_startup()") return targets def on_connect(tag): print("Tag: {}".format(tag)) print("Tag type: {}".format(tag.type)) #print '\n'.join(tag.dump()) if tag.ndef: record = nfc.ndef.TextRecord("Hello World!") tag.ndef.message = nfc.ndef.Message(record) print tag.ndef.message.pretty() #return True def on_release(tag): print("on_release()") if tag.ndef: print(tag.ndef.message.pretty()) clf = nfc.ContactlessFrontend('usb') if clf: print("Clf: {}".format(clf)) clf.connect(rdwr={ 'on-startup': on_startup, 'on-connect': on_connect, 'on-release': on_release }) clf.close()
実行
$ python 002.py Clf: SONY RC-S380/P on usb:001:010 on_startup() Tag: Type3Tag 'FeliCa Lite-S (RC-S966)' ID=__ID__ PMM=__PMM__ SYS=88B4 Tag type: Type3Tag record 1 type = 'urn:nfc:wkt:T' name = '' data = '\x02enHello World!'
今回は、いつ買ったわからない RC-370 が動かなかったけれども、買い直した RC-S380/P では動いた点、
フォーマットしないと NDEF でのやり取りができない点でつまずきました!