SONY非接触型カードリーダーRC-S380とraspberry piの連携記事も3回目です。
集めたコードを利用してNFCタグを読み込んで、そのIDをLCDに表示させます。
経緯は前回までの記事を追っかけてください。
非プログラマーなので記事内のコードはアテにしないでください。一応動きますが。
メインプログラムの作成
先に結論としてハマった箇所があります。それはプログラムを書くのはいいけど、どういう環境・形式で作れば良いのかということです。
NFCはnfcpyで実行します。これはこれで単体の.pyファイルです。LCDの表示もサンプルファイルのi2clcda.pyを参考にコマンドを記述していきます。
Python以外のプログラム言語と同じように、他のpyファイルというかライブラリというか、そういう物を読み込んで実行するのだろうと、多少の経験と書籍からは理解しています。
しかし、実際にどうやって記述するのか皆目見当も尽きません。
特にディレクトリの構成がよく分かりません。全部が同じディレクトリなら分かり易いのですけど、nfcなどもディレクトリにまとまっていますし、場所が全部別なので・・・。

一応、画像のようにホームにまとめています。(Pimoroniは使っていません)
集めたコードから読み解いてみました。前回に書いたようにほぼ元となるコードでトライアンドエラーしてみました。必要無い部分を自分なりに削除して動く所までにしました。
それがこちら。
mymain.py
説明します。間違っていたらどなたか教えてください。一応動作します。
#!/usr/bin/env python #おまじない
# coding:UTF-8 #UTF8
import nfc #nfcのmoduleを読み込む
import binascii #IDの文字列取るのに利用するため
from i2clcda import * #これ微妙・・・
import time #参考コードの利用そのまま
from threading import Thread, Timer #参考コードの利用そのまま
LCDに表示させるmoduleは、名前?を無視できるので利用しました。本当は別のカタチで実現するのでしょうけど、分からないので全部?の意味で読み込んでいます。
多分、クラスの継承のことなんですけど、まだ理解できていません。
from i2clcda import *
とても参考になりました。ただ結局、これは使いませんでした。
LCDに表示するコードは今回のプログラムmymain.pyの中に書きました。
# 読み取り待ち受けの1サイクル秒 TIME_cycle = 10.0 #この感覚は別に1.0でも良いと思う # 待ち受けの反応インターバル秒 TIME_interval = 0.2 # タッチされてから次の待ち受けを開始するまで無効化する秒 TIME_wait = 3 # NFC接続リクエストのための準備 # 212F(FeliCa)で設定 #テストでFeliCa残してあります。 target_req_felica = nfc.clf.RemoteTarget("212F") # 106A(NFC type A)で設定 target_req_nfc = nfc.clf.RemoteTarget("106A")
これらは、参考先をほぼそのまま使っています。
LCDへの表示
今回、LCDの表示もしたいので、その部分を追加します。
def check_NFC(): print 'NFC waiting...' # USBに接続されたNFCリーダに接続してインスタンス化 clf = nfc.ContactlessFrontend('usb') mydict = {} while True: target_res = clf.sense(target_req_nfc,target_req_felica, iterations=int$ if not target_res is None: tag = nfc.tag.activate(clf, target_res) print 'TAG type: ' + tag.type #購入したNFC Type2Tagのidを取得し表示 print str(tag.identifier).encode('hex').upper() #そのIDを代入 t2id = str(tag.identifier).encode('hex').upper() mmes = "I got it!" #2行目に文字列用意 #LCDの1行目にID、2行目に上記のメッセージを表示させる lcd_string(t2id,LCD_LINE_1) lcd_string(mmes,LCD_LINE_2) break for dic in mydict : print(dic) clf.close() check_NFC()
以下の記述方法でtagのIDを取得しています。
print str(tag.identifier).encode('hex').upper()
参考:nfcpyでType2Tag NXP NTAG213のIDを取得する方法
上記の「#購入したNFC Type2Tagのidを取得し表示」の部分で利用し、変数に代入しています。そして、前回の記事の通り、lcd_string(t2id,LCD_LINE_1)でLCDに表示させています。
コード全文
最終的なコードは以下になりました。
nfcpyはインストールされたライブラリみたいに利用する?ので、インポートして、timeなどはシステムライブラリ?なので、それもインポートです。
LCDへの表示は、mymain.pyに直接記述しています。
上からNFC関係、LCD関係にして、「def main():」行から読み取ったタグIDを表示させています。まだ無駄な部分や意味の無い部分はあると思いますが、これで一旦はOKにします。
これらをmymain.pyとして保存しました。(※以下コードはスペースのインデントがありません。コピペは気をつけてください)
#!/usr/bin/env python
# coding:UTF-8
import nfc
import binascii
import time
from threading import Thread, Timer
import smbus
import sys
# 読み取り待ち受けの1サイクル秒
TIME_cycle = 3.0
# 待ち受けの反応インターバル秒
TIME_interval = 0.2
# タッチされてから次の待ち受けを開始するまで無効化する秒
TIME_wait = 3
# NFC接続リクエストのための準備
# 212F(FeliCa)で設定
target_req_felica = nfc.clf.RemoteTarget("212F")
# 106A(NFC type A)で設定
target_req_nfc = nfc.clf.RemoteTarget("106A")
# Define some device parameters
I2C_ADDR = 0x27 # I2C device address, if any error, change this address to 0x3f
LCD_WIDTH = 16 # Maximum characters per line
# Define some device constants
LCD_CHR = 1 # Mode - Sending data
LCD_CMD = 0 # Mode - Sending command
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line
LCD_BACKLIGHT = 0x08 # On
#LCD_BACKLIGHT = 0x00 # Off
ENABLE = 0b00000100 # Enable bit
# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005
#Open I2C interface
#bus = smbus.SMBus(0) # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1
def lcd_init():
# Initialise display
lcd_byte(0x33,LCD_CMD) # 110011 Initialise
lcd_byte(0x32,LCD_CMD) # 110010 Initialise
lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
lcd_byte(0x01,LCD_CMD) # 000001 Clear display
def lcd_byte(bits, mode):
# Send byte to data pins
# bits = the data
# mode = 1 for data
# 0 for command
bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
bits_low = mode | ((bits<<4) & 0xF0) | LCD_BACKLIGHT
# High bits
bus.write_byte(I2C_ADDR, bits_high)
lcd_toggle_enable(bits_high)
# Low bits
bus.write_byte(I2C_ADDR, bits_low)
lcd_toggle_enable(bits_low)
def lcd_toggle_enable(bits):
# Toggle enable
time.sleep(E_DELAY)
bus.write_byte(I2C_ADDR, (bits | ENABLE))
time.sleep(E_PULSE)
bus.write_byte(I2C_ADDR,(bits & ~ENABLE))
time.sleep(E_DELAY)
def lcd_string(message,line):
# Send string to display
message = message.ljust(LCD_WIDTH," ")
lcd_byte(line, LCD_CMD)
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
# Main program block
def main():
# Initialise display
lcd_init()
print 'NFC waiting...'
# USBに接続されたNFCリーダに接続してインスタンス化
clf = nfc.ContactlessFrontend('usb')
while True:
target_res = clf.sense(target_req_nfc,target_req_felica, iterations=int(TIME_cycle//TIME_interval)+1 , interval=TIME_interval)
if not target_res is None:
tag = nfc.tag.activate(clf, target_res)
print 'TAG type: ' + tag.type
print str(tag.identifier).encode('hex').upper()
msg1 = str(tag.identifier).encode('hex').upper()
msg2 = "I got it!"
#LCDに表示
lcd_string(msg1,LCD_LINE_1)
lcd_string(msg2,LCD_LINE_2)
print 'sleep ' + str(TIME_wait) + ' seconds'
time.sleep(TIME_wait)
clf.close()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
# LCD_BACKLIGHT = 0x00
lcd_byte(0x01, LCD_CMD)
sys.exit(0)
Pythonってインデントが面倒くさい・・・。インデントのエラーでハマって何をしているのか分からなくなって時間掛かってしまいました。慣れるしかないですね。
エラーメッセージも分かり易いし、これまで僅かな知識があるプログラム言語よりも理解し易いと思いました。
動作テスト
こんな感じで実行できました。
——実行結果——

ここまでで、基本動作はOKですね。後は、NFCタグにメッセージが入れられますので、何かを書き込んで読み込むか、IDはユニーク(固有の)番号ですから、このままIDによって動作を変更させるプログラムを追加していきたいと思います。
NFCタグ内には少ない情報しか書き込めないので、プログラムの条件文のように何かのトリガーにするのが望ましいですね。
何かできたらまたご紹介します。
非接触型のカードリーダー、LCDキャラクタディスプレイも非常に安価で手に入ります。試してみてください。
Pythonで私でも分かりやすかった本
コメント