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

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

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

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

Raspberry Pi

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

Q&A

解決済

6回答

1747閲覧

トグル動作によるLEDの点灯制御について

myu

総合スコア18

Python 3.x

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

Raspberry Pi

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

1グッド

1クリップ

投稿2017/09/05 09:40

編集2017/09/07 11:21

トグルスイッチでのLEDの点灯を制御したいのですが、
下記のようなソースで割り込みの箇所
pi.wiringPiISRの関数で、トグルスイッチを押すとプログラムが終了してしまいます。
本来は、無限ループなので、プログラムが終了することはないのですが。
原因が、わかりません。

import time, wiringpi as pi led_pin = 23 bt_pin = 17 counter = 0 pi.wiringPiSetupGpio() pi.pinMode( bt_pin, 0 ) pi.pullUpDnControl( bt_pin, 2) pi.pinMode( led_pin, 1 ) def Warikomi(): global counter if ( pi.digitalRead( bt_pin ) == 0 ): counter = counter + 1 try: ret = pi.wiringPiISR( bt_pin, pi.INT_EDGE_BOTH , Warikomi ) while True: if ( counter % 2 == 0 ): pi.digitalWrite( led_pin, 1 ) time.sleep(0.5) pi.digitalWrite( led_pin, 0 ) time.sleep(0.1) except KeyboardInterrupt: pi.pinMode( led_pin, 0 ) finally : pi.pinMode( led_pin, 0 )

動作としては、プログラムが開始すると、LEDが点滅します。
ボタンを押して、LEDの点滅を止めようとすると、プログラムが終了(正常終了?異常終了?)してしまいます。

下記は、その時の結果(添付画像が何故かさかさまになります。すみません。)
イメージ説明

問題を単純化してみたのが次のコードです。

wiringpi

1 2global counter 3bt_pin = 17 4counter = 0 5 6pi.wiringPiSetupGpio() 7 8def Warikomi(): 9 print( "割り込み関数通過" ) 10 11try: 12 ret = pi.wiringPiISR( bt_pin, pi.INT_EDGE_RISING , Warikomi ) 13 while True: 14 time.sleep(0.5) 15 counter = counter + 1 16 print( counter ) 17 time.sleep(0.5) 18except KeyboardInterrupt: 19 print ("except通過" ) 20finally : 21 print ("finally通過" ) 22

このプログラムが開始すると、ディスプレイに1ずつカウントアップされ、
ボタンが押されたときにプログラムが終了(正常終了?異常終了?)してしまいます。
finally句は通りません。Warikomi関数も実行されません。

退会済みユーザー👍を押しています

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/09/05 21:52

try:を外すとエラーの起きる箇所で止まってしかも「エラー:何行目の関数○○で××が起きました」と出そうなのですが、こちら試されましたか?
myu

2017/09/06 00:38

ご意見ありがとうございます。try句を外しても、同様の結果になってしまいます。エラーメッセージなどは出ず、単純にプログラムが終了してしまいます。
myu

2017/09/06 00:41

ちなみに、while True:の文節をpi.wiringPiISRの関数とtime.sleepにしても同様です。なので、wiringPiISRの関数の動きがネットで見る情報と違うような気がします
can110

2017/09/07 09:33

念のために確認です。プログラム開始するとLEDは点滅するが、スイッチ押したとたんにプログラム終了するということでしょうか?
myu

2017/09/07 09:36

はい。その通りです。LEDは点灯しっぱなしの状態(100%この状態です。)でプログラムが終了します。詳しい現象を書いていないのでわかりづらいですよね。
can110

2017/09/07 09:42

すなわちexcept,finally内に処理がいっていない可能性が高いですね。左記の場所にprint文を入れて何らか出力されるか確認ください(本来は出力されるはず)。
myu

2017/09/07 09:49

ご意見ありがとうございます。そうなのです。print文が入っているのですが、finally句を通らないのです。添付画像がさかさまで見づらいと思いますが、finally句にwiringPiISR関数の戻り値retを出力しているのですが、printされません。
myu

2017/09/07 09:54

もう少し、情報を付け加えますと、キーボードからの割り込み終了(Ctrl+c)をすると、except KeyboardInterruptを通り(当たり前ですよね)、finally句を通って、関数の戻り値が返ってきます(「None」と返ってきました)
can110

2017/09/07 09:55

やはり通っていませんね。了解です。ちょっと勘なので回答ではなくこちらに記載しますがWarikomi関数の「if ( pi.digitalRead( bt_pin ) == 0 ):」行を取り除いてみてください。
can110

2017/09/07 09:56

キーボード割り込みは正常に動作しているということですね。やはり割り込み処理部分が怪しそうですね。
myu

2017/09/07 10:04

ご意見ありがとうございます。「if ( pi.digitalRead( bt_pin ) == 0 ):」行を取り除いてみましたが、同様の結果でした。
can110

2017/09/07 10:06

確認ありがとうございます。割り込み中にdigitalReadしてよいものか疑問だったので。調べてみて何か分かれば回答できればと思います。
mituha

2017/09/07 13:14

ラズパイの種類、OSやWiringPlのバージョンなども記載していただけますでしょうか?
myu

2017/09/07 13:37

ラズパイですが、zero wです。OSは、Raspbianです。WiringPlは、2.44.4です。よろしくお願いします。
mituha

2017/09/07 23:25

Package Ownerの違いでバージョンへの追従具合が違うだけに見えますね。実際どうなんだろ?
myu

2017/09/08 02:27

なるほど。勉強になります。slashさんのリンクしているサイトからwiringPi.cを確認しているのですが、(Raspbianの中のwiringPi.cが現在、探せていません。)正直、怪しいところにprintfを入れて確認したいのですが、それをコンパイルする方法(技量がない)がわからないので、(本題からそれてる気がします)調査中です。
guest

回答6

0

ベストアンサー

とりあえず、 time.sleep の代わりに pi.delay とWiringPIで用意されている関数を使用することで動作するようです。

examples でも delay を使っているので何か理由があるのだとは思います。

投稿2017/09/09 04:09

mituha

総合スコア385

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

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

myu

2017/09/11 00:45

mituhaさん、ありがとうございます。time.sleepのところをpi.delayに置き換えてうまくいきました。色々調べていたのですが、exampleの方までたどり着かず、迷宮入りしそうでした。本当にありがとうございました。
guest

0

解決としていいのか少々疑問なのですが、
(やりたいことが出来たからよしとします。とりあえず。)
WiringPiの「wiringPiISR」ではダメなのかと思い、
pigpioの「callback」を使用しました。
結果、思い通りの動きをしてくれました。

ご意見、ご指摘をくださった方々、大変ありがとうございました。

出来れば、WiringPiで行いたかったのですが、(pigpioが、現時点で、あまりよくわかっていないため。)
もし何かありましたら連絡ください。

以下のコードは、問題を単純化してみた時のコードをpigpioで書いてみました。
(こう見ると、wiringPiISRの引数にあるwarikomiの関数の引数に問題があるのかといろいろ試しましたが関係なさそうです。)

import pigpio import time bt_pin = 17 counter = 0 pi = pigpio.pi() def warikomi(gpio, level, tick): print( "割り込み関数通過" ) cb = pi.callback(bt_pin, pigpio.RISING_EDGE, warikomi) try: while True: time.sleep(0.5) counter = counter + 1 print( counter ) time.sleep(0.5) except KeyboardInterrupt: print ("except通過" ) finally : pi.stop() print ("finally通過" )

投稿2017/09/07 12:33

myu

総合スコア18

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

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

0

def Warikomi():が何も返さないのがエラーの原因かもしれません。

怪しいと思って調べたところ、StackOverflowのnickzamさんによれば、

Cについて造詣はないけれども、オレがソースを見るにこのコード(関数がVOIDを返したりエラーが起きるかどうかチェックする)が原因だと思う。だからオレは、my_int()の中で明示的にTrueを返すようにするか、1を返すようにすることを勧める。

今Pythonの関数の中ではNoneを返しているし、それで(Cのソース中の)関数の末端に来るけれども、(Cのソースによれば)何も返せないってことでしょ。


多分以下のコードで対応できます。

Python

1def Warikomi(): 2 print( "割り込み関数通過" ) 3 4 # wiringPiISR requires value 5 return True

投稿2017/09/07 12:28

編集2017/09/07 12:40
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

myu

2017/09/07 12:51

ご意見ありがとうございます。def Warikomi()にreturn ture, return 1 両方試しましたが、結果は同じでした。 問題を単純化したコードでprint( "割り込み関数通過" )が実行されていないので、return tureやreturn 1も実行されていないような気がします。ただ、この問題は、是非とも解決したいので、何かありましたら、連絡ください。私も、https://projects.drogon.net/raspberry-pi/wiringpi/functions/のサイトから、wiringPiISRを調査しています。
guest

0

(Raspberry Piに興味はありますが、まだ触ったことがないので)確証はありませんが、
Re: wiringPi interrupts crashingのGordonさんによれば、

全体が書いてないからいまいちわからないけれど、wiringPiISR()をループの中で呼び出していないかい?どうもそうっぽいんだけど。プログラム全体の中で、モニターしたいPINごとにただの一回だけ呼び出すようにするべきだよ。

だそうです。こちらの対応でダメであればもう少し調べてみます。

投稿2017/09/06 10:14

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2017/09/06 10:14

mituhaさんがお昼にコメントしたものと同じですね o.0
myu

2017/09/07 01:45

ご意見ありがとうございます。連絡遅くなりました。whileの外に出し、wiringPiISRを実行しても結果が変わりませんでした。ご指摘ありがとうございます。
mituha

2017/09/07 02:20

門外漢なので勉強になります。
guest

0

PythonもWiringPiも使用していないので的外れかもしれませんが…

ret = pi.wiringPiISR( bt_pin, pi.INT_EDGE_BOTH , Warikomi() )

Warikomi()() はいるのですか?
割り込み用の関数登録だと他の言語では括弧なしで関数自体の登録になるのでは?
(Pythonは知りません)

投稿2017/09/06 02:08

mituha

総合スコア385

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

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

myu

2017/09/06 02:34

ご意見ありがとうございます。すみません。確かに必要ありませんでした。ただ、現象は、やはり同じです。ご指摘ありがとうございます。
mituha

2017/09/06 03:35

後、wiringPiISRはwhileの外で1回のみ呼び出すべきではないでしょうか? wiringPiISRが複数の登録を想定していた場合は落ちそうです。
myu

2017/09/07 01:45

ご意見ありがとうございます。連絡遅くなりました。whileの外に出し、wiringPiISRを実行しても結果が変わりませんでした。ご指摘ありがとうございます。
mituha

2017/09/07 02:18

一般的な作りとして気になるのは、 INT_EDGE_BOTH の場合、立ち上がり、立ち下がりの2回割り込みが走る。 割り込みの中でSleep等を行って良いか? ですかね。 後、counterが奇数時にもsleepをいれた方が負荷が少ないかもしれません。
myu

2017/09/07 07:58

ご意見ありがとうございます。「INT_EDGE_BOTHのところ」は、本来の仕様では、INT_EDGE_RISINGです。(wiringPiISRの関数がうまくいかないので、いろいろ変えていたら、戻すことを忘れていました。)「割り込みの中でSleep等を行って良いか?」なのですが、LEDの点滅を行う際、どうしてもsleepを使わないと出来ないため、(他に方法がわかりません。python、ラズパイ初心者です。)使用しております。ご指摘ありがとうございます。
mituha

2017/09/07 08:18

あ、点滅側は多分Sleepで問題ないと思います。 むしろ、点滅させない時にSleepが入っていない方が問題になるかも。 気になるのは、Warikomi側のSleepです。 一般的には割り込んだ処理の中では色々しないほうが無難です。 私の方もPython、ラズパイ共にほとんど使用しておらず、、 別な言語や装置等の場合の話ですので、今回の症状のヒントぐらいと思ってください。
myu

2017/09/07 09:32

>気になるのは、Warikomi側のSleepです。 そうですね。Warikomi側のSleepは、必要ないです。 ご指摘ありがとうございます。
mituha

2017/09/09 02:00

とりあえず、症状が再現することをラズパイ3で確認しました。 環境依存ではなさそうですね
myu

2017/09/11 02:54

現象を再現してくださったのですね。ありがとうございます。
guest

0

終了するのは?ですが、warikomi発動しないのはわかります。

exampleと比較して:

ret = pi.wiringPiISR( bt_pin, pi.INT_EDGE_RISING , Warikomi )

ret に束縛してるのみで実行されていないのでは? つまり登録されていない。
ret =がいらないのでは。

投稿2017/09/09 10:58

ttatsf

総合スコア35

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

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

ttatsf

2017/09/09 11:35

ごめんなさい。見当違いでした。実行した結果がretに束縛されるはず、ですよね。忘れてください。
myu

2017/09/11 01:00

ご意見ありがとうございます。皆さんのおかげで、疑問が解消できました。本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問