Amazonのアソシエイトとして、ラズパイダ(raspida.com)は適格販売により収入を得ています。詳しくは当サイトの プライバシーポリシーをご覧ください。
先日、3回に分けてSONY製カードリーダーRS-S380とキャラクタLCDを使いLCDにIDを表示することができました。
[2025年4月30日2025年5月1日
【初心者向け】産業用ラズベリーパイでRFID/NFCタグを読み書きする方法まとめ](https://raspida.com/how2use-nfc-tag/)
[2019年2月1日2023年10月5日
NFCに書込みとこれまでの修正——Raspberry Pi × RC-S380 NFCタグ](https://raspida.com/write2nfc/)
[2019年1月22日2023年10月5日
SONY非接触型カードリーダーRC-S380とraspberry pi(実装編)NFCを読み込んでLCDにID表示まで](https://raspida.com/nfc-s380-finish/)
[2019年1月21日2023年10月5日
SONY非接触型カードリーダーRC-S380とraspberry pi(LCD表示編)](https://raspida.com/sony-s380-rpi0w-lcd/)
今回は、NFCへの書き込みをしてみたいと思います。全てにおいて簡単にできるよう考えていますけど、分からない、間違えている箇所はお気軽にコメント欄にお知らせください。出来る範囲でご対応しています。
今回の環境
- Raspbian Stretch Lite
- SSH接続でモニターレス
今回使った物
- Raspberry Pi Zero WH
- ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380
- LCDディスプレイ:OSOYOO(オソヨー) 電子工作キット (改良版)の一部パーツ
- または、Raspberry Pi 電子回路実験用キット【デラックスセット】などのパーツがたくさん入っている商品
- サンワサプライ NFCタグ(10枚入り) 白 MM-NFCT
書き込み用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回作れば何回でもコマンドで実行できます。
■Pi 5は8GBモデルがオススメ
読み込んでみると正しく表示されない?
前回のコードではそのままだとエラーが出るかも知れません。LCDへの表示もおかしな文字が出るかも知れません。
読み込んでみると、以下のように文字列などが表示されました。
LCDにも正しく表示されません。ひとつは文字コードの問題もあるでしょう。見直しました。他にもありました。

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だと思います。
修正したコード
先の3つの記事では、メインのmymain.py、書き込むWite2tag.py、そしてLCD表示用にi2clcda.pyの3つのファイルと、nfcpyのファイル群で構成しています。

修正した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タグを物に貼って、オママゴトのレジに出来たらと思っています! 子供ってレジが好きですよねー。





