【Raspberry Pi】キャッシュレスレジおもちゃの作り方

つくってみた
つくってみた

つくった経緯

ムスコ
ムスコ

いらっしゃいませー

のぼさん
のぼさん

トミカショップに行って以来、最近お買物ごっこにハマってるみたい。

最近セルフレジもやりたがるようになったし、レジおもちゃつくってみようかな。

ってな感じでレジおもちゃつくることにしました。

つくるもの

WANWANカードによる電子マネー?のみのレジです。

必要なもの

秋月電子通商、Amazon、100円均一などで購入しました。

Raspberry Pi 2 Model B

4が欲しいです。。。

FeliCa Lite-S:1枚

WAONカードユーザーなので、それっぽいデザインをcanvaで作成、印刷したものを両面テープで貼り付けて使っています。犬のアイコンはICOOON MONO様の柴犬のイラスト2を使わせていただきました。

USB 1Dバーコードスキャナー

NFC通信リーダー PaSoRi RC-S380/S:1個

Raspberry Pi キャラクタ液晶ディスプレイモジュール完成品:850円

USB ミニスピーカー:1個(300円)

ダイソーの300円商品です。

ブレッドボード EIC-801:1個(270円)

3mm赤色LED 325nm 70度 OSR5JA3Z74A:1個(10円)

タクトスイッチ(黒色) TS-0606-F-N-BLK:1個(10円/個)

カーボン抵抗(炭素被膜抵抗)1/2 330Ω:1個(100円/100個入り)

カーボン抵抗(炭素皮膜抵抗)1/4W 1kΩ:1個(100円/100個入り)

ジャンパーワイヤー(オス-メス):5本

USBケーブル(タイプAオスーマイクロB)

ACアダプター

チャージ用バーコード

バーコードどころ様で適当な数字を打って作成させていただきました。

プラダン(黒):1枚

プラダン(白):2枚

写真を撮り忘れてしまいました。。。↑のプラダンの色違いです。

配線する

ディスプレイ、LED、タクトスイッチ、LED用抵抗(330Ω)、タクトスイッチプルダウン用抵抗(1kΩ)をそれぞれ配線します。

USBポートには以下の3つを接続します。

  • PaSoRi
  • バーコードリーダー
  • スピーカー

イヤホンジャックにスピーカーも接続します。

プログラム

素人が書いているのでいろいろと間違えているかもしれません💦

4つのファイルで構成しています。

  • list.csv:バーコード、商品名、値段を記載したcsvファイル
  • LCD.py:ディスプレイを表示させるプログラム
  • shopping.py:全体のプログラム
  • dog.mp3:会計完了時に鳴らす犬の鳴き声のmp3ファイル

犬の鳴き声は効果音ラボ様の犬の鳴き声1を使わせていただきました。

list.csvについて

左からバーコード、商品名、値段をカンマ区切りで書いてあります。

LCD.pyについて

"""
This code is licensed under the MIT license. 
<https://opensource.org/licenses/MIT>

Copyright © 2022 nobo

Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or 
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

#必要なモジュールをインポート
import pandas as pd
import smbus
from time import sleep
lcd=smbus.SMBus(1)

#接続したI2C(lcd)のアドレス
ADDR=0x3e

#初期設定
def initial_set():
	initial_list=[0x38,0x39,0x14,0x70,0x56,0x6C,0x38,0x0C,0x01]
	for command in initial_list:
		lcd.write_byte_data(ADDR,0x00,command)
		sleep(0.2)

#ディスプレイクリア
def clear_display():
    clear_list=[0x38,0x0C,0x01]
    for clear in clear_list:
        lcd.write_byte_data(ADDR,0x00,clear)
        sleep(0.2)

#改行
#0x00:first,0x40:next,0x46:en
def line(num):
    lcd.write_byte_data(ADDR,0x00,0x80+num)
    sleep(0.2)

#ディスプレイへ文字の書き込み
def write_lcd(text):
    texts=str(text)
    encode_text=texts.encode("cp932")
    for message in encode_text:
        lcd.write_byte_data(ADDR,0x40,message)
        sleep(0.2)

#まとめてディスプレイに表示;1行目に商品名、2行目左詰めに値段、2行目右詰めでエン表示       
def display(text,cost,en="エン"):
    clear_display()
    write_lcd(text)
    line(0x40)
    write_lcd(cost)
    line(0x46)
    write_lcd(en)

#動作確認
if __name__=="__main__":
    df=pd.read_csv("list.csv",index_col=0)
    z=input("what_num")
    a=df.index.get_loc(int(z))
    b=df.iloc[a]["product"]
    c=df.iloc[a]["cost"]
    initial_set()
    display(b,c)

初期設定はデータシートの推奨そのままです。こちらのサイト様がデータシートについて非常にわかりやすくまとめてくださっており、助かりました。

shopping.pyについて

"""
This code is licensed under the MIT license. 
<https://opensource.org/licenses/MIT>

Copyright © 2022 nobo

Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or 
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

#必要なモジュールをインポート
import smbus
from time import sleep
import RPi.GPIO as GPIO
import nfc
from playsound import playsound
import pandas as pd
import LCD

#GPIOの番号の指定方法をGPIO番号に指定
GPIO.setmode(GPIO.BCM)

#ピンにわかりやすい名前をつける
switch=21
LED=26

#switchピンを入力、LEDピンを出力に
GPIO.setup(switch,GPIO.IN)
GPIO.setup(LED,GPIO.OUT)

#I2C初期化
lcd=smbus.SMBus(1)

#接続したI2C(lcd)のアドレス
ADDR=0x3e

#nfcpy初期設定
clf = nfc.ContactlessFrontend('usb')

#felicaカードの読み込み
def read_felica():
    tag = clf.connect(rdwr={'on-connect': lambda tag: False})
    sc1 = nfc.tag.tt3.ServiceCode(0, 0x0B)
    bc1 = nfc.tag.tt3.BlockCode(0, service=0)
    return tag.read_without_encryption([sc1], [bc1])

#felicaカードへ書き込み    
def write_felica(data):
    tag = clf.connect(rdwr={'on-connect': lambda tag: False})
    sc1 = nfc.tag.tt3.ServiceCode(0, 0x09)
    bc1 = nfc.tag.tt3.BlockCode(0, service=0)
    write_data = tag.write_without_encryption([sc1], [bc1],data)

#チャージ
#カード読み込み->intに変換->チャージ額1000を加算->16バイト列に変換->カード書き込み->チャージOK表示->残額表示->LED消灯
#チャージ額上限の場合チャージNG表示
def charge(charge_money):
    global max_charge
    read_data=read_felica()
    read_data=int.from_bytes(read_data,"little")
    data=read_data+charge_money
    if data > max_charge:
        LCD.display("チャージNG",cost="",en="")
        return
    else:
        write_data = data.to_bytes(16,'little')
        write_felica(write_data)
        LCD.display("チャージOK",cost="",en="")
        LCD.display("ノコリ",data)
        GPIO.output(LED,False)
        return  
        
#スイッチ押した後の動作
#合計金額表示->会計
#会計:カード読み込み->intに変換->合計額を減算->犬の鳴き声*2->残額表示->カード書き込み
#最後にリストを空
#リストが空の場合は何もせずreturn
#残高不足の場合はLED点灯->チャージしてね表示
def callback(switch):
    global total
    if len(total)==0:
        return       
    total_sum=sum(total)
    LCD.display("ゴウケイ",total_sum)
    LCD.display("タッチシテネ",cost="",en="")
    read_data=read_felica()
    read_data=int.from_bytes(read_data,"little")
    data = read_data - total_sum
    if data >= 0:
        for i in range(2):
            playsound("dog.mp3")
        LCD.display("ノコリ",data)
        write_data = int(data).to_bytes(16,'little')
        write_felica(write_data)
        total=[]
        return
    else:
        GPIO.output(LED,True)
        LCD.display("フソク",abs(data))
        LCD.display("チャージシテネ",cost="",en="")
        return

#start
#一度に買えるのは3個まで
#list.csvにないものは一律100円
#チャージ上限額99999円
GPIO.add_event_detect(switch, GPIO.RISING,callback=callback, bouncetime=3000)
LCD.initial_set()
max_charge=99999
total=[]

while True:
    if len(total)>3:
        LCD.display("カイスギダヨ",cost="",en="")
        del total[-1]
        LCD.display("ボタンオシテネ",cost="",en="")
    barcode=input("write_barcode")
    if barcode==str(10009).zfill(8):
        charge_money=1000
        LCD.display("チャージ",charge_money)
        LCD.display("タッチシテネ",cost="",en="")
        data=charge(charge_money)
    elif str(4904810) in barcode:
        df=pd.read_csv("list.csv",index_col=0)
        a=df.index.get_loc(int(barcode))
        b=df.iloc[a]["product"]
        c=df.iloc[a]["cost"]
        LCD.display(b,c)
        total.append(c)
    else:
        LCD.display("ソノタ",100)
        total.append(100)

felicaカードへの読み書き方法の情報が少なく、ひたすら公式ドキュメントとにらめっこでした。忘れないように別の記事でまとめたいと思います。

形状づくり

白プラダンを下図のパーツに切り出してプラスチック用接着剤やセロテープで組み立てます。
弱々しいところはL字型のプラダンをつくって部分的に補強しています。

寸法のサイズが大きかったり小さかったりで見づらくてすみません。FreeCADがまだまだ使いこなせていません・・・。

続いてラズパイやスピーカーを下図の様に配置します。

土台がめちゃくちゃひしゃげていたので、後でプラダンを差し込んで補強しました。

最後に黒プラダンと白プラダンを下図のように切り出し、組み立てた白プラダンに貼り付けます。

I、Jは黒プラダン、Kは白プラダンです。
Jは穴をあけないものと上図のように穴をあけたものの2つを作成し、正面から見て左に穴の開いてるもの、右にあいていないものを貼り付けています。
Kはブレッドボードを隠すためのカバーなのですが、ブレッドボードに乗せただけだとガタガタするので隅にプラダンを3枚重ねたパーツを脚のようにつけました。

完成

3歳の息子には難しかったようで、すぐに飽きてしまいました。。。
バーコードをピッとするのは楽しかったようなので、しばらくはバーコードリーダーだけで遊ぼうと思います~

参考書籍

今回使ったRaspberry Pi キャラクタ液晶ディスプレイモジュール、LED、タクトスイッチの作例が載っています。そのほかにも沢山の作例が載っていて、とても勉強になる1冊です。

スポンサーリンク
スポンサーリンク
のぼをフォローする
のぼさんのブログ
タイトルとURLをコピーしました