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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2216閲覧

raspberry pi pico上でのpythonコードについて

wataru.py

総合スコア7

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/09/26 06:46

編集2021/09/26 09:51

閲覧ありがとうございます。

現在、ラズベリーパイピコを使って電子工作を行っており、その際のpythonのコードについてご質問させていただきます。

電子工作の内容が、
・ランダムに3っつのLEDを点滅させる。
・LEDが点滅した箇所のタクトスイッチを押すとスコアが1点加算される。
・スコアが3点になるとbreaksする
というものです。

問題は、タクトスイッチを押すタイミングがLED点灯の瞬間でないとスコアが加算されません。
点灯の間隔は1秒にしているのですが、点灯した瞬間出なければ、LEDが光っていても反応しません。

LED点灯中であればどのタイミングでも反応するようにしたいのですが、分からず質問させていただきました。

アドバイスお願い致します。

import machine import utime import random led1 = machine.Pin(0,machine.Pin.OUT) led2 = machine.Pin(1,machine.Pin.OUT) led3 = machine.Pin(2,machine.Pin.OUT) score = 0 i = [led1,led2,led3] switch1 = machine.Pin(3,machine.Pin.IN,machine.Pin.PULL_UP) switch2 = machine.Pin(4,machine.Pin.IN,machine.Pin.PULL_UP) switch3 = machine.Pin(5,machine.Pin.IN,machine.Pin.PULL_UP) while True: print(score) print(switch1.value()) print(switch2.value()) print(switch3.value()) x = random.choice(i) print(x) x.value(1) utime.sleep(1) x.value(0) utime.sleep(1) if (x == machine.Pin(0,machine.Pin.OUT)): if (switch1.value() == 0 ): score += 1 elif (x == machine.Pin(1,machine.Pin.OUT)): if (switch2.value() == 0 ): score += 1 elif (x == machine.Pin(2,machine.Pin.OUT)): if (switch3.value() == 0 ): score += 1 if score == 2: break

y_waiwai様、thkana様回答、アドバイス本当にありがとうございました!!!
以下、ご指摘を参考に修正したコードです。
現時点では思ったように動作しております。
改良点などあればお願い致します。

import

1import utime 2import random 3 4led1 = machine.Pin(0,machine.Pin.OUT) 5led2 = machine.Pin(1,machine.Pin.OUT) 6led3 = machine.Pin(2,machine.Pin.OUT) 7 8switch1 = machine.Pin(3,machine.Pin.IN,machine.Pin.PULL_UP) 9switch2 = machine.Pin(4,machine.Pin.IN,machine.Pin.PULL_UP) 10switch3 = machine.Pin(5,machine.Pin.IN,machine.Pin.PULL_UP) 11 12score = 0 13 14flag = False 15 16ledlist = [led1,led2,led3] 17 18 19 20 21while True: 22 i = random.randint(0,2) 23 x = ledlist[i] 24 25 x.value(1) 26 for n in range(100): 27 utime.sleep(0.01) 28 29 if (led1.value() == 1): 30 if (switch1.value() == 0 ): 31 flag = True 32 33 if (led2.value() == 1): 34 if (switch2.value() == 0 ): 35 flag = True 36 37 if (led3.value() == 1): 38 if (switch3.value() == 0 ): 39 flag = True 40 41 x.value(0) 42 utime.sleep(1) 43 if (flag == True): 44 score += 1 45 flag = False 46 print(score) 47 48 if (score == 3): 49 break 50

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

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

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

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

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

guest

回答2

0

ベストアンサー

utime.sleep(1)
というのは、1秒間の間、マイコンは何もするな、という命令です。当然ながら、その間にスイッチが押されようと何しようとマイコンは知ることができません(というのは半分ウソで、割り込みとかマルチスレッドとかいろいろ手段はありますけど、いきなりソレに走るのは順番を飛ばしすぎだろう、と思いますので)。
原則として、(割り込みやマルチスレッドを使うのでなければ)秒単位のsleepなんかは余程単純なLチカぐらいでしか使えない、と思ってください

点灯した瞬間出なければ、LEDが光っていても反応しません。

本当はそうじゃないのでは。今のプログラムの動作を「日本語で」説明するなら、whileループの中身は
(表示系は略)
つぎに点灯するLEDを決める
決めたLEDを点灯する
1秒間何もしない
決めたLEDを消灯する
1秒間何もしない
LEDに対応したスイッチがこの瞬間にONになっていたらスコアを増加する

これを繰り返しているのですから、(次に光るのではなく)ひかり終わったLEDに対応したスイッチを押せばスコアが増加するプログラムになっていませんか。
何が起こっているかをちゃんと観察・把握することはとても大切なことです。「わかったつもり」にならないこと。

で、どうするか...解は一つじゃないですが、例えば。
まずは単純に「LED1を一秒周期で点滅する」ことは以下の手順でも実現できますね。主要部分のみ

while True: x = random.choice(i) x.value(1) for n in range(100): #0.01秒x100=1秒 utime.sleep(0.01) x.value(0) utime.sleep(1)

では、「点灯している間」にスイッチの検査を(とりあえずひとつ)挟んでみましょうか。

while True: x = random.choice(i) x.value(1) for n in range(100): utime.sleep(0.01) if (switch1.value() == 0 ): score += 1 x.value(0) utime.sleep(1) print(score)

としたらどうなるでしょう。点灯中にボタンを押してscoreを増やすことはできたんじゃないかと思います。でも、ちょっとscoreの値がナンですね(どうナンなのかは実行して確かめてください)。さてどうしましょう。ここもなんとかする手段は一つではありませんが、「フラグ」を立てて処理してみましょうか。

while True: x = random.choice(i) x.value(1) flag=False #検査に入る前にフラグをクリアしておく for n in range(100): utime.sleep(0.01) if (switch1.value() == 0 ): flag=True #一度'以上'検出すればflagをセット、一度も押されていなければFalseのまま x.value(0) utime.sleep(1) if flag: score += 1 print(score)

ではスイッチの検査を真面目にチェックしましょうか。

と、その前に。別個に作られたオブジェクトを==で比較してTrueになるかどうかというのはちょっと深い話を含むので、x == machine.Pin(0,machine.Pin.OUT))というような比較は、内容を理解して絶対大丈夫という自信がない限り使わない方がよいように思います。今回はそれでも期待の動作をするのですが、本当に大丈夫という自信があってその比較をしていますか? そうでなければ

ledList = [led1,led2,led3] #中略 while True: i = random.randint(0,2) x=ledList[i] #中略 if(i == 0):#点いているLEDに対応してスイッチの検査を選ぶ if (switch1.value() == 0 ):

みたいな形にしたほうが安全かも知れません。あるいは...いや、改善案はキリがないので止めましょう。まずはちゃんと動かせてから。

あとは自力でできるかしら。


改良点などあればお願い致します。

私はPythonは決して得意ではないのであまりどうこうは言えませんが、特に問題はないんじゃないでしょうか。
多少手を入れるとしたらこんなところでしょうか。

import utime import random led1 = machine.Pin(0,machine.Pin.OUT) led2 = machine.Pin(1,machine.Pin.OUT) led3 = machine.Pin(2,machine.Pin.OUT) switch1 = machine.Pin(3,machine.Pin.IN,machine.Pin.PULL_UP) switch2 = machine.Pin(4,machine.Pin.IN,machine.Pin.PULL_UP) switch3 = machine.Pin(5,machine.Pin.IN,machine.Pin.PULL_UP) pairList = [(led1,switch1),(led2,switch2),(led3,switch3)] #タプルでペアにする score = 0 while True: i = random.randint(0,2) x = pairList[i] x[0].value(1) #x[0]はledn flag = False for n in range(100): utime.sleep(0.01) if (x[1].value() == 0 ): #x[1]はswitchn。選択されているスイッチだけ監視する flag = True x[0].value(0) utime.sleep(1) if ( flag ): # flagが論理型の値なので==Trueはあっても害は無いが意味もない score += 1 print(score) if (score > 2): #==3でもいいけれど、扱いを間違えて値が大きくなっても終われるように break while True: #明示的にプログラム内に留める pass

投稿2021/09/26 08:49

編集2021/09/26 11:58
thkana

総合スコア7629

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

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

wataru.py

2021/09/26 09:52 編集

ご丁寧にありがとうございます!!! 1つずつ試させていただきました。 一番最初のでは確かにスコアは加算されますが、y_waiwaiさんのご指摘のようにスイッチが押されている間加算されてしまうのですね。 フラグを立てて確かめるというのがとても勉強になりました。 上記のコメントをもとに作成してみたのですが、当初の狙い通りのものが出来ました!
thkana

2021/09/26 09:41

コメント欄はインデント付きません。Pythonのプログラムでインデントなしってのはちょっと勘弁なので、質問に「改善後」を追記(前のと置き換えると質問のやりとりがわけわからなくなるから、あくまで追記)してみてください。
wataru.py

2021/09/26 09:53 編集

失礼いたしました! 質問のところに追記させていただきました!
wataru.py

2021/09/26 13:07

ありがとうございます! 参考にさせていただきます! こんなに詳しいのに得意ではないのですか!? てっきり専門の方かと思いました!
wataru.py

2021/09/26 14:20

お~!ほんとにありがたやです~<m(__)m> もう少し追加機能を付けれるよう頑張ってみます! 普段はプログラミング関係のお仕事されているのですか?
guest

0

コードを見ると、
LED点灯の瞬間でしかスイッチの値を読んでいません
そこらへんどーにかしましょう

それと、スイッチを1か0かでしか読んでないけど、これじゃまずいです。
スイッチを押しているあいだじゅうずっとスコアが加算されるってことになります
これをどうにかするには、なにか変数を用意してスイッチの状態を覚えておいて、スイッチが1から0に変わるときに押された判定をするようにします

投稿2021/09/26 06:58

編集2021/09/26 07:25
y_waiwai

総合スコア87749

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

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

wataru.py

2021/09/26 07:02

やっぱりそー言うことなんですね! 考えてみます!ありがとうございます!
wataru.py

2021/09/26 08:06

教えて頂き、ありがとうございます! 言われていることは分かるのですが、どう改善すればよいかわからずで、いろいろ試してみても上手くいきません(´;ω;`)
wataru.py

2021/09/26 09:54

他の方の回答も合わせてコードを修正したところ思ったように動かすことが出来ました! アドバイスありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問