あっきぃ日誌

鉄道ブログのような技術系ブログのようななにか

コインセレクター・アゲイン

ラズピッピアドベントカレンダー24日目です。

adventar.org

今週は私以外の方にたくさん参加いただきました。ありがとうございましたー!Pi 5貯金箱がめちゃすきです。

コインセレクター・アゲイン

2年前に断念していた、コミケのレジへのコインセレクター導入をリトライしてみます。

akkiesoft.hatenablog.jp

断念したのは「筐体に100円玉を当てこするとカウントが増える」という、サージが発生する問題とまでは認識していましたが、今になって考えると、アクティブローにしていれば良いんでわと思いました。当時は多分このへん理解してなかったと思う。Picoで色々やっててやっと気がついた気がします。遅い。

さて早速レジアプリに組み込もうとしましたが、今のレジアプリの運用はディスプレイにHyperPixelを使っているので、GPIOに空きがありませんでした。しまったな。

Raspberry Pi Picoで作るコインセレクターカウンター

コインセレクターの制御はRaspberry Pi Picoにやってもらうことにして、金額の指示と、指示された金額が投入され終わったことの通知は、Picoの入出力をPySerialでやることで対応しました。

Pico側はこんなコードになりました。

import board
coin_sw = digitalio.DigitalInOut(board.GP0)
coin_sw.switch_to_input(pull=digitalio.Pull.UP)
while True:
    coin_count = 0
    balance = input("put balance: ")
    if balance == "":
        continue
    try:
        balance = int(balance)
        if balance < 100:
            continue
    except:
        continue
    print("please insert coin")
    while balance:
        if not coin_sw.value:
            coin_count += 100
            balance -= 100
            time.sleep(0.2)
    print("OK")
    time.sleep(1)

コードとしてはこんな流れ。やってることとしては普通。コインセレクターの入力に0.2秒のスリープを入れているのは、入れないと1コインで4回くらい入力が来てしまうため。

  • input()で金額を受け取り
  • GP0(コインセレクター)からの入力が金額に達するまでループ
  • 金額に達したらループを抜けてOKを週力して次ぐの金額受け取りに戻る

シリアル接続してスクリプトを実行すると、以下のようになります。いやまじでかんたんですね。

put balance: 400 ←400を入力
please insert coin ←GP0を4回ショートさせる
OK
put balance:   ←次の入力待ち

レジアプリ側では、次のようなコードでPicoでやり取りをします。

import time
import serial

serial_port = '/dev/ttyACM0'
serial = serial.Serial(serial_port, 115200)
serial.timeout= 1

# 400円を指示する例
serial.write(str.encode("%s\r\n" % 400))

# 実際のレジアプリはguizeroのリピートを使っているけど、
# PicoからOKが来るのを待つループ
while True:
    result = serial.readline().decode(encoding='utf-8').rstrip()
    if result == "OK":
        print("まいどあり")
        break
    time.sleep(1)
# 以降、支払い完了の処理

もしレジアプリで100円払いの画面に行ってから戻る場合は、Ctrl+CとCtrl+Dを送ってPicoをリセットします。

serial.write(b'\x03')
serial.write(b'\x04')

するとPico側ではKeyboardInterruptとなってREPLに戻り、さらにCtrl+Dでリロードされて、金額入力に戻るというワケです。

put balance: Traceback (most recent call last):
  File "code.py", line 1, in <module>
  File "coin_counter.py", line 20, in <module>
KeyboardInterrupt: 

Code done running.
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

Press any key to enter the REPL. Use CTRL-D to reload.
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
put balance: 

かざりつけ

Picoのスクリプトでは入力中の金額が把握できるので、PimoroniのFour Letter pHAT*1で投入中の金額を表示するように味付けしました。もちろんこいつはふつうのラズピッピ用なので、uHAT Porter Picoを使っています(スイッチサイエンスさんで委託中!地味に売れてて嬉しい!)。さらに、GPIOがモジュールで埋まる問題がこちらでも発生してしまうため、Nano HAT Hacker(formerly known as Pico HAT Hacker)で対応します。レジアプリのほうはこれをやってもHyperPixelが全部のGPIOを使っているのでだめなんですね。


そしてこうなった

1分で収まるしShortsにしてみた

www.youtube.com

レジとレシートはサークル向き、コインセレクターは通路向きに設置して、買い手の決済方法が100円玉だったら投入してもらうという感じになります。

レシート発行は、従来の金額入力とキャッシュレス決済ではボタン操作が必要でしたが、コイン投入の場合は、投入が終わったら勝手に発行してくれます。レシートちぎりとお渡しはサークル側作業になりますが、セミルフレジって感じでいいですね。

サージの問題については、1回再現したような気がしますが、それ以降は再現していないので、なんとなく大丈夫そうな気がしています。が、誤作動が多そうなら引っ込めて対応予定ですし、毎回セレクターに入ったコインの目視確認は行います。それ意味あんの?って言われそうですけど、これはロマンだから……。

あと多分、持ち運びが面倒なので今回しかやらないと思います。

コードはこちら

そろそろ自分で読めなくなってきているし、当時からコードの分割をしたかったので、そろそろなんとかしたい。けど、今からいじって壊したくないので、今回はこのままで行く。というのを繰り返している。

github.com

追記

サージ再現しました。サージでカウントが増えたらごめんなさいの精神で今回は持って行って、一回使ったらいよいよ捨てるか

*1:終売