NFCに書込みとこれまでの修正——Raspberry Pi × RC-S380 NFCタグ

Raspberry Pi Zero /W/WH

先日、3回に分けてSONY製カードリーダーRS-S380とキャラクタLCDを使いLCDにIDを表示することができました。

今回は、NFCへの書き込みをしてみたいと思います。全てにおいて簡単にできるよう考えていますけど、分からない、間違えている箇所はお気軽にコメント欄にお知らせください。出来る範囲でご対応しています。

今回の環境

  • Raspbian Stretch Lite
  • SSH接続でモニターレス

今回使った物

書き込み用Pythonコード

単純に書き込みは、

record = nfc.ndef.TextRecord("Coffee")

というカタチで書き込みます。この場合はCoffeeというテキストです。

ネットの諸氏から集めたコードやサンプルを参考にして、これで書き込めたのでヨシとしています。突っ込まれると思うので、先にごめんなさい。適時直してくださいね。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import nfc
import nfc.ndef

def startup(targets):
print "waiting for new NFC tags..."
return targets


def connected(tag):
if not tag.ndef or not tag.ndef.is_writeable:
print("not a writeable nfc tag")
return False
print("old message:")
print(tag.ndef.message.pretty())

if tag.ndef:
record = nfc.ndef.TextRecord("Coffee")
new_message = nfc.ndef.Message(record)
print str(record.pretty())
#return true

if len(str(new_message)) > tag.ndef.capacity:
print "too long message"
return True

if tag.ndef.message == new_message:
print "already same record"
return True

tag.ndef.message = new_message
print("new message:")
print(tag.ndef.message.pretty())

return True

def released(tag):
print("released:")
if tag.ndef:
print(tag.ndef.message.pretty())


clf = nfc.ContactlessFrontend('usb')
print(clf)
if clf:
while clf.connect(rdwr={
'on-startup': startup,
'on-connect': connected,
'on-release': released,
}):
pass

※インデント無視なので、コピペの際は気をつけてください。すみません(いずれ対応します・・・)

(Pythonではどうかまだ知りませんけど)書き込む文字列はインプット形式で入力待ちにして、都度入力した方が実用的でしょう。同じ物を書き込むなら1回作れば何回でもコマンドで実行できます。

読み込んでみると正しく表示されない?

前回のコードではそのままだとエラーが出るかも知れません。LCDへの表示もおかしな文字が出るかも知れません。

読み込んでみると、以下のように文字列などが表示されました。

LCDにも正しく表示されません。ひとつは文字コードの問題もあるでしょう。見直しました。他にもありました。

x02en

Print文でTag type、IDなど5つ表示させています。

下から2行目の「? TenCoffee」がCoffeeというテキストです。しかし、おかしいですよね? その一つ上にをご覧ください。レコードの項目のdata=部分が実際の文字列です。

\x02enCoffee

これはテキストに付随するヘッダーと書き込んだテキストが繋がっている状態です。これ、LCDに表示させるのに、テキストだけにしたいと思っても、最初はどういう理由か分かりませんでした。

私と同じように分からなくて質問している人をなんとか1人見付けました! 居るもんですねー。(結構、探した!)

Reading and Parsing NFC tag on iOS 11

For the plain text tag, typeNameFormat isnfcWellKnown. Let’s assume identifier, payload and type are all UTF-8 string. After we convert Data to string and print them out, we will see identifier is empty, type is “T”, payload is “enhello”. Obviously “T” means Text. But why is there “en” before “hello”?

(意訳)プレーンテキストタグの場合、NFCのtypeNameFormatは周知されています。識別子、ペイロード、および型式がすべてUTF-8文字列であるとしましょう。 Dataを文字列に変換して印刷した後、識別子が空、typeが“ T”、payloadが“ enhello”になります。 明らかに「T」はテキストを意味します。 しかし、なぜ「こんにちは」の前に「en」があるのでしょうか?

同じ環境ではないのですけど、同じNFCについての記述がありました。

恐らくプログラマーの人は当たり前ですけど、データにヘッダーが付いていることで色々と操作できるので、フォーマットって決まっていますよね。バーコードとかプリンター制御もそうだし、何かのデータセットだと何byteかは意味がありますよね。

詳しくは以下のサイトをご覧ください。結構詳しく書いてありました。

Austin Blackstone Engineering

取り出し方を変えた

結局、どうやってうまく表示させたのかというと、データの取り出し方を変えました。nfcpyのリファレンスともにらめっこでした。

しかし、以下の記事が正解でしたね・・・。遠回りしたぞ。

https://qiita.com/nofrmm/items/96eba75085ea2987e28e

# NFCタグに埋めたtextを読む
records = tag.ndef.records

ほぼ、こちらの記事から修正し直しました! @nofrmmさん、記事をありがとう! 私の記事よりも参考になります。というか、コードはそのままでOKだと思います。

\ Raspberry Pi 4はメモリー8GBが最新 /

【セット概要】「データーベース」「Webサーバー」「NAS」「AI処理」「4K画像での2画面処理」などの高負荷がかかる処理を、長時間稼働させるのに必要な負荷テスト行い、当社で厳選した高品質なパーツを組み合わせたセットです。高品質なAnker製USB電源の採用、トラブルの原因になりやすい電源周りをデジタルモニターリングできるをType-Cケーブル、Raspberry財団認定モデル 高速タイプ 100MB/sec 128GB MicroSD、静音FANによる強制冷却など、高負荷運用でも長期に渡る安定稼働が可能です。また単品でご購入いただくよりお得です。

修正したコード

先の3つの記事では、メインのmymain.py、書き込むWite2tag.py、そしてLCD表示用にi2clcda.pyの3つのファイルと、nfcpyのファイル群で構成しています。

nfc_all_file

修正した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...'
msg0 = "...scan?"
#LCDに表示
lcd_string(msg0,LCD_LINE_1)

# USBに接続されたNFCリーダに接続してインスタンス化
clf = nfc.ContactlessFrontend('usb')

mydict = {}
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

records = tag.ndef.records
for record in records :
print 'record.text = ' + record.text
key = str(record.text)
mydict[key] = key

msg1 = str(tag.identifier).encode('hex').upper()
msg2 = key

#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)

コード類は参考程度にご利用ください。

次は別に価格表を作り、ID毎にデータを取り出してみます。
最終的にNFCタグを物に貼って、オママゴトのレジに出来たらと思っています! 子供ってレジが好きですよねー。

NFCタグの読み込み
ラズパイダ

ラズパイダ

学べる楽しむ便利になる。小さいくせにヤケにパワフル。そんなRaspberry Pi をまだ知らない人に伝えたい。様々な場所で利用されているRaspberry Pi を知って「あっ、これもラズパイだっ!」だからラズパイダ!

関連記事

特集記事

コメント

この記事へのコメントはありません。

最近の記事 はじめて向け
  1. Pimoriniからシンプルスーパースリムな「Audio DAC SHIM」

  2. Raspberry Pi OS のバージョンアップ方法とaptについて

  3. 遊び半分、学び半分でRaspberry Piを活用しよう!

  4. Raspberry Pi Imager更新、イメージ選択数を計測のためデータ収集も

  5. 「fre:ac」はラズパイでもmp3やFLACに変換できる無料のオーディオコンバーター

  1. 【初心者向け】Raspberry Pi 4との接続方法(電源、HDMI)

  2. 【初心者向け】はじめてRaspberry Pi OS をダウンロードする人へ

  3. Raspberry Pi OS のインストールは、公式ツール1つだけでOK

おすすめの記事

  1. Raspberry Pi 4のOSをデスクトップPCとして使うためにUbuntuMATEをインストールしてみた

  2. 正式にUbuntuがラズパイ4に対応(Ubuntu 20.10)

  3. TwisterOSで懐かしのWindows、最新macOSの見た目でラズパイを使う

  4. ラズパイ(Raspberry Pi)を使ってできるメディアセンター3選

  5. ラズパイ4をデスクトップPCライクに使えるOSとして個人的に急浮上中のEndlessOS

  6. 期待が高まるWindowsに似ている新しいLinuxのフレーバー「Endless OS」がRaspberry Pi 4用に登場予定

今月の人気記事

  1. 1

    Raspberry Pi で動く様々なOS一覧まとめ13種類!

  2. 2

    ラズパイ4をUSB接続のSSDから起動する方法(USBブート)

  3. 3

    初心者でもラズパイでNASサーバーを作ってみよう!

  4. 4

    Raspberry Pi 4の初期設定2020年版

  5. 5

    Raspbian のWi-Fi設定(Raspberry Pi 初期設定)

  6. 6

    ラズパイ4とOMV5(openmediavault5)で作る自宅NASサーバーの設定方法

  7. 7

    Raspberry Pi 4を起動したのにモニターに画面が映らない対処法

  8. 8

    ラズパイで使うmicroSDカードの選び方

  9. 9

    Raspberry Pi 4のOSをデスクトップPCとして使うためにUbuntuMATEをインストールしてみた

  10. 10

    ラズパイ4はPCライクな性能になったけどPCではないよという話

記事ランキングページ

TOP