teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

2回答

617閲覧

Python3 ラズベリーパイ

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2023/10/19 07:11

編集2023/10/19 08:56

0

1

実現したいこと

キー入力(enterキー)を押したら、プログラムが終了するようにしたいです。

前提

プログラムを実行すると、カードリーダー(ソニー製 Sー380)が待機状態(読み込み待ち状態)となり、フェリカカードをかざすと
かざしたカードリーダーのIDを読み取り、ターミナル上にそのIDが表示されるプログラムを作成しています。
なお、フェリカカードをかざした後は再び待機状態となります。再度フェリカカードをかざすと再びIDがターミナル上に表示されます。
プログラムの実行はターミナル上から行っています。なお、フェリカーカードをかざすと、同時にGPIOピンが動作してリレーやLEDの点灯、
電子音ブザーが鳴るようにしています。やりたい事としては、"enterキー"を押したら、プログラムから抜けれるようにしたいのですが、
"enterキー"を押してもプログラムから抜けることが出来ずに、フェリカカードの待機状態が続きます(読み込み待ち状態)。
if keyboard.is_pressed("enter"):
break
の1文で指定しているはずなのですが、どこがおかしいのでしょうか?お知恵貸していただけると幸いです。

発生している問題・エラーメッセージ

エラー自体は出ないのですが、"enterキー"を押すとプログラムを終了できるようになりたいです。
今現在は"enterキー"を押してもプログラムを終了することが出来ないため、control + Z で強制終了しています。。。

該当のソースコード

import sys import RPi.GPIO as GPIO import time import binascii import nfc import os import datetime import csv sys.path.append('/home/pi/.local/lib/python2.7/site-packages') import keyboard class NFCReader(object): def on_connect(self, tag): #タッチ時の処理 print("【 Touched 】") #タグ情報を全て表示 print(tag) print("dump felica.") print(' ' + '\n '.join(tag.dump())) #IDmのみ取得して表示 self.idm = binascii.hexlify(tag._nfcid) print("IDm : " + str(self.idm)) #特定のIDmだった場合のアクション if self.idm == "00000000000000": print("【 登録されたIDです 】") return True def read_id(self): clf = nfc.ContactlessFrontend('usb') try: clf.connect(rdwr={'on-connect': self.on_connect}) finally: clf.close() if __name__ == '__main__': # GPIO番号指定の準備 GPIO.setmode(GPIO.BCM) gpio_led = 17 gpio_relay = 4 gpio_buzzer = 22 # LEDピンを出力に設定 GPIO.setup(gpio_led, GPIO.OUT) GPIO.setup(gpio_relay, GPIO.OUT) GPIO.setup(gpio_buzzer, GPIO.OUT) reader = NFCReader() dt_now = datetime.datetime.now() while True: if keyboard.is_pressed("enter"): break else: print("touch card:") reader.read_id() print("released") print(reader.idm) print(dt_now) GPIO.output(gpio_led, 1) # LED点灯 GPIO.output(gpio_relay, 1) # relay点灯 GPIO.output(gpio_buzzer, 1) # buzzer点灯 time.sleep(0.5) GPIO.output(gpio_led, 0) # LED消灯 GPIO.output(gpio_relay, 0) # relay消灯 GPIO.output(gpio_buzzer, 0) # buzzer消灯 # ピンの設定を初期化 # この処理をしないと、次回 プログラムを実行した時に「ピンが使用中」のエラーになる GPIO.cleanup(gpio_led) GPIO.cleanup(gpio_relay) GPIO.cleanup(gpio_buzzer)

試したこと

なお、試したこととして単純に”enterキー”の物理的な接触不良の可能性が無きにしもあらずのため
”space”に変更してみてプログラムを試したところやはりダメでした。

そこで、かなりプログラムを単純化させて、NFCとGPIOを無しで動作させてみました。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
import sys
import time
sys.path.append('/home/pi/.local/lib/python2.7/site-packages')
import keyboard

while True:
if keyboard.is_pressed("space"):
break
else:
print("touch card:")
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
ターミナル上から上記のプログラムを実行させ、”space”を押すと無事にプログラムが終了しました。
このことから、"enterキー"の不良ではなく、プログラムのどこかに問題があるように感じます。

分かる方がいましたら、ご教示いただけると幸いです。

補足情報(FW/ツールのバージョンなど)

PCはラズベリーパイ4 Bモデルです。使用言語はPython3です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2023/10/19 08:15

- is_pressed('space') など他のキーではどうか - NFC、GPIO処理をなくして単純にtime.sleep待ちのみループではどうか を試した結果を質問本文に記載ください。
退会済みユーザー

退会済みユーザー

2023/10/19 08:57

「試したこと」に詳細を追記しました。お知恵貸していただけますと幸いです。
tmp

2023/10/19 09:12

nfcを使ったことないのですが、フェリカカードの待機状態のまま、待っているので if keyboard.is_pressed("enter"):まで、到達しないのではないでしょうか? connectのキーワード引数terminateで、キーチェックなどは、できませんか?
guest

回答2

0

2つ問題があります。

  1. reader.read_id() はNFCカードを読み込まないと返らない。
  2. keyboard.is_pressed() は関数が呼ばれたときにキーが押されている必要がある。

なので、is_pressed()でチェックしているときにリターンキーが押されているようにするには、リターンキーを押しながらNFCカードをかざすくらいのことをしなければなりません。

2の解決策としては、keyboard.add_hotkey()関数を使う手があります。
この関数で定義しておくと、非同期でキーの入力を得ることができます。例としてはこんな感じ。

python

1import keyboard 2import time 3 4interrupt = False 5def set_interrupt(): 6 global interrupt 7 interrupt = True 8 9keyboard.add_hotkey('enter',set_interrupt) 10 11while True: 12 if interrupt: 13 print('interrupted.') 14 break 15 else: 16 print("wait 3 sec") 17 time.sleep(3)

3秒待ちのときにenterを押すと中断できます。

あとは、reader.read_id() が永久待ちのところを解決すればよさそうですが、以下の記事をみつけました。
https://www.kosh.dev/article/3/
これを参考にして、少し待って抜けるようにすれば、目的は達成できるのではないかと。

投稿2023/10/19 09:25

TakaiY

総合スコア14523

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

reader.read_id()はカードがない場合すぐに戻ってくるのですか?
処理を見る限りここがブロックしてる気がします。

投稿2023/10/19 09:15

cas

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問