Raspberry PiとNFCタグで自宅の消耗品管理の仕組みを作った話

Raspberry PiとNFCタグで自宅の消耗品管理の仕組みを作った話

はじめに

こんにちは。福岡天神拠点の田邉です。

最近、買い物等でポイントを貯めるのにハマっています。系列のWebサービスを利用したりポイントが貯まるクレジットカードに変えたりしているんですが、一番貯めやすいのはネットショッピング。月1回くらいの頻度でポイントが貯まるキャンペーンが開催されるので、そこで消耗品(シャンプーやボディソープなど)をまとめ買いしています。

でもまとめ買いのたびに消耗品の在庫を確認するのが地味に大変。いい機会だったので、以前から興味を持っていたNFCタグを利用した仕組みを作ってみました。

これまで

これまで自宅の消耗品はこのように買い足していました。

  • 「そういえば残り少なくなってたな」と思ったら買いに行く
  • 買い物に行ったついでにふと思い出して買う
  • 使用中のものの近くに交換用(詰替え用)を置いておく
  • 置き場所なかったら適当な棚に乱雑に収納

このような状態だったので十分な在庫があるのに買ってしまうこともよくありました。まとめ買いするようになってからは在庫あるのに買うことは減ったものの、収納場所が分散していて今度は在庫の棚卸しが大変に…。

このあたりをいい感じに管理することを目指します。

どんなものを作るか

まずどんなものを作るか決めます。テレビやWebの記事で特集されていたきっちり在庫管理されたお家を参考に、さらにそれをもう少し便利にと考えた結果、次のような形に落ち着きました。

  • 在庫はそれぞれ箱にいれて1箇所で管理
  • 箱にはラベルを付けて中身と在庫の有無がひと目で把握できるようにする
  • 在庫が切れたらNFCタグをかざして在庫切れを登録する
  • NFCタグの読み取り機は備え付ける
  • 在庫切れの情報はスプレッドシートにまとめる

ここで出てきたNFC(Near Field Communication)ですが、近距離無線通信規格の1つです。NFC対応の非接触型ICチップを利用することでSuicaなどの交通系電子マネーのように専用リーダーにかざすだけで通信できるようになります。これを使って手軽に在庫切れを登録できるようにします。

ハードウェア周りの作成

まずはハードウェア周りを作ります。作る必要があるものは次の2つ。

  • 在庫置き場
  • 在庫切れ登録機

在庫置き場

自宅にちょうどいい棚が空いてたので、そこを在庫置き場にすることにしました。ネットで材料を買い揃えて作成。ラベルはマグネットシートで作り、表面(白い面)にシールタイプのNFCタグを貼り付けています。ただ、マグネットに貼って通信に影響ないのかはちょっと不安…。今はひとまず動いてますが、壊れたらその時考えます。

在庫切れ登録機

Raspberry PiとNFCリーダー を使って在庫切れを登録する機械を作ります。スマホアプリでもいいかなと考えたんですが、アプリ起動の手間が後々気になりそうなのと端末が余ってなかったのでRaspberry Piで自作することに。(電子工作したかったのも理由の一つです。)

Raspberry Piはカードサイズのコンピュータです。大きさがカードサイズと小型ですが、USBポートや無線LANなどが接続されています。またGPIOという汎用入出力ピンがあるため電子回路を手軽に接続できます。今回は次のような構成で組み立てました。

  • Raspberry Pi 3 Model B (OS: Raspberry Pi OS)
  • GPIOに接続
    • LED(赤、緑を1つずつ)
    • 圧電ブザー
  • USBポートに接続
    • NFCリーダー(Sony PaSoRi RC-S380)

ソフトウェアの作り方調査

ハードウェアができたのでソフトウェアを作ります。今回はプログラミング言語としてPython(バージョン3.7.3)を利用しました。といっても初めて触るものが多いので、まずはどう使うのかを調査しました。事前に調べたものは次の通り。

  • LEDを光らせる方法
  • 圧電ブザーを鳴らす方法
  • NFCタグを読み取る方法
  • Googleスプレッドシートの読み書き方法

LEDを光らせる方法

LEDはRaspberry PiのGPIOに接続しており、GPIOをON(5V)にすれば点灯、OFF(0V)にすれば消灯します。GPIOの操作はRPi.GPIOというライブラリを使うと簡単に実現できました。

# 初期設定を行い11番ピンのLEDを点灯させる
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.output(11,True)
GPIO.cleanup()
# 初期設定を行い11番ピンのLEDを点灯させる import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) GPIO.setup(11, GPIO.OUT) GPIO.output(11,True) GPIO.cleanup()
# 初期設定を行い11番ピンのLEDを点灯させる
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.output(11,True)
GPIO.cleanup()

圧電ブザーを鳴らす方法

圧電ブザーもLEDと同様にRaspberry PiのGPIOに接続しています。ただし圧電ブザーはLEDとは異なり、一定周波数でON/OFFを切り替えないと音が鳴りません。プログラムで頑張ってもいいのですが、今回はRaspberry PiのPWM機能を利用しました。

PWM(Pulse Width Modulation)とはパルス幅変調といい、ON/OFFの比率を変えることで様々なもの(LEDの明るさやモーター速度など)を制御する方法です。LEDを光らせるときに使ったRPi.GPIOでPWMも設定できるので、次のようにパラメータを指定して音を鳴らします。

# 初期設定を行い32番ピンの圧電ブザーを1200Hzで0.5秒間だけ鳴らす
# デューティー比は50%(1周期あたりのONの時間:OFFの時間=50:50)
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(32, GPIO.OUT)
buzzer = GPIO.PWM(32, 1200)
buzzer.start(50)
time.sleep(0.5)
buzzer.stop()
GPIO.cleanup()
# 初期設定を行い32番ピンの圧電ブザーを1200Hzで0.5秒間だけ鳴らす # デューティー比は50%(1周期あたりのONの時間:OFFの時間=50:50) import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BOARD) GPIO.setup(32, GPIO.OUT) buzzer = GPIO.PWM(32, 1200) buzzer.start(50) time.sleep(0.5) buzzer.stop() GPIO.cleanup()
# 初期設定を行い32番ピンの圧電ブザーを1200Hzで0.5秒間だけ鳴らす
# デューティー比は50%(1周期あたりのONの時間:OFFの時間=50:50)
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(32, GPIO.OUT)
buzzer = GPIO.PWM(32, 1200)
buzzer.start(50)
time.sleep(0.5)
buzzer.stop()
GPIO.cleanup()

NFCタグを読み取る方法

NFCタグはRaspberry PiのUSBポートに接続したNFCリーダーから読み取ります。読み取りのためのnfcpyというライブラリがあるのでそれを使いました。

# NFCがかざされるまで待機、かざされたらNFCのIDmを表示する
import binascii
import nfc
def on_connect(tag):
idm = binascii.hexlify(tag._nfcid)
print("IDm : " + str(idm))
clf = nfc.ContactlessFrontend('usb')
clf.connect(rdwr={'on-connect': on_connect})
clf.close()
# NFCがかざされるまで待機、かざされたらNFCのIDmを表示する import binascii import nfc def on_connect(tag): idm = binascii.hexlify(tag._nfcid) print("IDm : " + str(idm)) clf = nfc.ContactlessFrontend('usb') clf.connect(rdwr={'on-connect': on_connect}) clf.close()
# NFCがかざされるまで待機、かざされたらNFCのIDmを表示する
import binascii
import nfc
def on_connect(tag):
    idm = binascii.hexlify(tag._nfcid)
    print("IDm : " + str(idm))
clf = nfc.ContactlessFrontend('usb')
clf.connect(rdwr={'on-connect': on_connect})
clf.close()

Googleスプレッドシートの読み書き方法

GoogleスプレッドシートはGoogle Sheets APIを介して読み書きします。このAPIを使うためのライブラリが用意されているのでそれを活用しました。使い方は公式のドキュメントにまとまっていたので、それをそのまま試しました。

https://developers.google.com/sheets/api/quickstart/python

ソフトウェア作成

一通り使い方が分かったので、それらを組み合わせて在庫切れを登録するためのプログラムを作ります。今回は「NFCタグ読み込みプログラム」と「タグ情報送信プログラム」の2つを作りました。ホントは1つにまとめたかったんですが、Googleスプレッドシートの読み書き時間の影響で、NFCタグを連続で読み取れなかったので2つに分けることに。

NFCタグ読み込みプログラム

このプログラムではNFCタグを監視します。NFCタグがかざされるまで待機し、かざされたら音を鳴らしてタグ情報を書き込んだファイルを吐き出す、ということを行います。きちんと動いてることが分かるように、待機中は赤、読み込み中は緑のLEDを点灯させています。

タグ情報送信プログラム

このプログラムは、NFCタグ情報をGoogleスプレッドシートに反映するプログラムです。NFCタグ読み込みプログラムの出力ファイルを定期的に確認して、ファイルが見つかったらファイル内のタグ情報を元にGoogleスプレッドシートの「読み取り日」セルを更新します。Googleスプレッドシートでは在庫補充日より「読み取り日」の方が新しいものを「在庫なし」と表示するようにしているので、このプログラムで送信することで「在庫なし」に切り替わります。

おわりに

Raspberry PiとNFCタグを使って在庫管理する仕組みを作りました。在庫がなくなったときはラベルを登録機にかざすだけ、買い物するときはスプレッドシートを見るだけとなったので、かなり楽になりました。これでポイントたくさん貯めれそうです。

採用情報

メンバーズエッジで最高のチームで最高のプロダクトを作りませんか?

最高のプロダクトをつくる 最高のチームで働く

在宅でも、地方でも、首都圏でも。多様な働き方で最高のチームをつくり、お客様のプロダクトパートナーを目指します。アジャイル開発を通じ、開発現場の第一線で活躍し続けたいエンジニアを募集しています。