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

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

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

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Raspberry Pi

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

Python

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

Q&A

解決済

3回答

2830閲覧

【ラズパイ】○秒以内に何回スイッチを押したかを検知したい

very_salty

総合スコア4

Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Raspberry Pi

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

Python

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

0グッド

0クリップ

投稿2021/06/20 06:41

編集2021/06/20 07:01

前提・実現したいこと

○秒以内に何回スイッチ(タクト)を押したかを検知したい
例えば10秒以内に3回押せばprint(count)したときに3が出力される
それを繰り返したい

一例 (こんなのしか思いつかなぃ)

0 : 押されるまで待機

     ↓

A1 & B1へ


A1 : 押されたら10秒タイム開始 & count += 1

    ↓

A2 : 1で計測中の10秒以内にもう一回押されるとさらに count += 1

    ↓ ↑       繰り返し

A3 : 1で計測中の10秒以内にもう一回押されるとさらに count += 1


B1 : A1での計測が10秒を満たした

    ↓

B2 : Aスレッド停止(要るかな??)

    ↓

B3 : print(count) 出力

    ↓

B4 : count = 0

    ↓

0へ (再び待機)

試したこと

threading使ったけどなんかタイマーのdef動いてないっぽい?というか並列せずにできるのかなこれ?できたらいいけど。

raspberrypi zero w です。タクトスイッチはgpio21(40番目のやつ)と39番目のGNDにつないでます。

10秒で終わってくれずに押せばずっとカウントされる・・・

python

1#10秒で終わってくれずに押せばずっとカウントされる・・・助けて・・・ 2import threading 3import time 4import RPi.GPIO as GPIO 5 6 7 8GPIO.setmode(GPIO.BOARD) 9GPIO.setup(40 , GPIO.IN, pull_up_down = GPIO.PUD_UP) 10 11count = 0 12 13 14 15def counter(): 16 global count 17 while True: 18 if GPIO.input(40) == GPIO.LOW: 19 print("click") #ここまでは出る、というかチャタリングして大量に出る 20 count = count + 1 21 #print (count) デバッグ用、正常にカウントアップしてた チャタ(ry 22 23def timer(): #これ起動してないっぽい? 24 global count 25 if count >= 1: #これのせい??? 26 time.sleep(10) 27 print (count)                      #本来求めてる出力はこれ 28 exit() #おわっちゃう~ count=0のところまで戻りたい 29 # (というか出力が終わったら待機状態に戻りたい)のに~ 30def main(): 31 #並列の使い方あってんのかなこれ。 32 print("wait") #ちゃんと出る 33 t1 = threading.Thread(target=counter) 34 t2 = threading.Thread(target=timer) 35 t1.start() 36 t2.start() 37 38 39 40if __name__ == "__main__": 41 main() 42 43#これを手直ししてほしいってわけではないです。多分始めっから全部間違ってる気がしてます。

補足情報

raspberrypi zero w です。タクトスイッチはgpio21(40番目のやつ)と39番目のGNDにつないでます。

ほんとうはここからrequestsでifttt(webhook)経由でlineにcountの数字をvalue1に入れて飛ばしたい(親切な方~)

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

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

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

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

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

guest

回答3

0

自己解決

自己解決しました
GPIO.add_event_detectでthreadingをなくし、チャタリングも解決
普通にtimer()の中にwhile True:入れるの忘れてただけだった。

python

1import time 2import RPi.GPIO as GPIO 3 4 5 6GPIO.setmode(GPIO.BOARD) 7GPIO.setup(40 , GPIO.IN, pull_up_down = GPIO.PUD_UP) 8 9 10 11count = 0 12wait_time = 10 13 14 15 16def counter(self): 17 global count 18 #print("click") 19 count = count + 1 20 21def timer(): 22 global count 23 while True: 24 if count == 1: 25 time.sleep(wait_time) 26 print (str(count) + "\n") 27 count = 0 28 print ("accepting...") 29 30 31 32GPIO.add_event_detect(40, GPIO.RISING, callback=counter, bouncetime=100) 33 34 35 36def main(): 37 print("accepting...") 38 timer() 39 40 41 42if __name__ == "__main__": 43 main()

回答された方々、本当にありがとうございました!

投稿2021/06/22 15:02

編集2021/06/22 15:04
very_salty

総合スコア4

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

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

thkana

2021/06/22 21:58

だから「チャタリング」じゃないんだって。 しかも、そのプログラムだと本当に「チャタリング」が出たら無力ですよ。
very_salty

2021/06/22 22:51

あっ、すいません! gpio21がLOWの間を検知してるだけでした。回答読んでいたはずなのになぜかチャタリングという言葉を使ってしまってますね。申し訳ありませんでした。
guest

0

Python

1def counter(): 2 global count 3 while True: 4 if GPIO.input(40) == GPIO.LOW: 5 print("click") #ここまでは出る、というかチャタリングして大量に出る 6 count = count + 1

これ、ポートをLにしている間ず~っと「大量に出る」のではないですか? チャタリングは、押した/離した時にせいぜい100ms=1/10秒間程度出る現象です。現象をちゃんと確認してください。
GPIO.input(40) == GPIO.LOW
で検出できるのは「押された」という変化ではありません。「押されている」という状態です。つまり、押されている間どんどんcountが増加していくわけです。

では、「押された」とはどういうこと? 「直前までは押されていなかった、今は押されている」です。

Python

1def counter(): 2 count=0 3 while True: 4 current=GPIO.input(40)==GPIO.LOW 5 if current and ! past: #今は押されている。直前は押されていなかった 6 print("click") 7 count = count + 1 8 past=current #「今」は次回の「過去」

とかなんとかでしょう。チャタを取りたいのならここももうひと工夫ですがそれはご自分で。

で、10秒ですが、どれくらい精確に測らなきゃいけないんですか? そこそこでいいのなら、マルチスレッド等使わずに

import time def counter(): count=0 t0=time.time()*1000 #エポックミリ秒取得 while time.time()*1000-t0<10*1000: #ループ開始してから10*1000ミリ秒以下? current=GPIO.input(40)==GPIO.LOW if current and ! past: #今は押されている。直前は押されていなかった print("click") count = count + 1 time.sleep(0.01) past=current #「今」は次回の「過去」 print(count)

で十分だったりしませんか?

投稿2021/06/20 11:28

thkana

総合スコア7639

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

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

0

初回スイッチを押した際にtimer側のスレッドをstartさせれば「スイッチを押してから10秒間受付」は達成できるでしょう。スイッチを押した際countが0の時にtimerをstartで良いでしょう。

10秒経ったらもう一度待機状態にするには、

  • timerスレッド側でcountを0にし、exitせず関数を終了する
  • 次にスイッチが押された際はcountが0なので、またtimerがstartする

となればexitせずにcounter側が無限ループするので目的は達成できるのではないでしょうか。

※スレッドセーフかどうかはあまり考慮せず、とりあえず動作することを目標として回答しています。そのあたりはご容赦を。

投稿2021/06/20 08:50

hope_mucci

総合スコア4447

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問