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

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

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

複数の計算が同時に実行される手法

Raspberry Pi

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

Python

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

Q&A

解決済

3回答

3020閲覧

Pythonでモーターとセンサーを並列処理したいのです

ryu-12

総合スコア2

並列処理

複数の計算が同時に実行される手法

Raspberry Pi

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

Python

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

0グッド

0クリップ

投稿2021/12/04 14:32

編集2021/12/06 13:53

プログラミング初心者です。現在、Pythonを使用してDCモーターと光電センサーの並列処理を行うプログラムを作成していますがうまくいきません。プログラムは下記の通りです。

Python3

1import RPi.GPIO as GPIO 2import time 3import sys 4GPIO.setwarnings(False) 5GPIO.setmode(GPIO.BOARD) 6 7GPIO.setup(13,GPIO.OUT) 8GPIO.setup(19,GPIO.OUT) 9GPIO.setup(21,GPIO.OUT) 10GPIO.setup(15,GPIO.OUT) 11GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 12GPIO.add_event_detect(24, GPIO.FALLING, bouncetime=300) 13 14#モーター制御 15pwm = GPIO.PWM(19, 30) 16pwm.start(0) 17pwm.ChangeDutyCycle(0) 18GPIO.output(19, 1) 19GPIO.output(21, 0) 20pwm.ChangeDutyCycle(40) 21pwmR = GPIO.PWM(15, 100) 22pwmR.start(0) 23pwmR.ChangeDutyCycle(0) 24GPIO.output(15, 1) 25pwmR.ChangeDutyCycle(23) 26time.sleep(3.0) #3秒間回転 27#モーター停止 28pwm.stop() 29pwmR.stop() 30time.sleep(3.0) 31GPIO.output(13, 0) 32GPIO.output(15, 0) 33GPIO.output(19, 0) 34GPIO.output(21, 0) 35 36while True: 37 try: 38 print(GPIO.input(24)) #センサーからGPIO 24へ入力信号 39 time.sleep(1) 40 except KeyboardInterrupt: 41 GPIO.cleanup() 42 sys.exit()

実現したいこと

このプログラムは現段階ではモーターを3秒回転させた後、モーターを停止、その後センサーが起動、センサーに反応している間はGPIO24に入力信号が行き、1秒おきにshellに[1]と表示されるプログラムになっております。実現したいことは、このセンサーからの入力信号を利用してモーターを停止させることです。

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

特にはエラーメッセージなどは出てきませんでしたが、センサーからの入力信号をどのようにすればモーターの停止にさせられるのかがわかりません。

試したこと

プログラムを組む際に優先順位があると気づき、何度かプログラムの順序を変えて組んでみましたがうまくいきませんでした。
どなたか解決策を教えていただけないでしょうか。

追記

ご指摘された通り、プログラムを修正してみました。修正後のプログラムは、センサー反応後にモーターが止められるようにはなりましたが、停止後にモーターを再稼働させるプログラムがうまくいきません。どのようにすればよいか、どなたか解決策を教えていただけないでしょうか。

Python3

1import RPi.GPIO as GPIO 2import time 3import sys 4GPIO.setwarnings(False) 5GPIO.setmode(GPIO.BOARD) 6 7motor1speed=15 8motor1Direction=21 9SENSOR_PORT = 24 10LED = 35 11 12 13def motorstop(): 14 pwm.stop() 15 pwmR.stop() 16 17GPIO.setup(19,GPIO.OUT) 18GPIO.setup(motor1speed,GPIO.OUT) 19GPIO.setup(motor1Direction,GPIO.OUT) 20GPIO.setup(SENSOR_PORT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 21GPIO.setup(LED, GPIO.OUT) 22 23 24#モーター制御 25pwm = GPIO.PWM(19, 100) 26pwm.start(0) 27GPIO.output(motor1Direction, 0) 28pwm.ChangeDutyCycle(40) 29pwmR = GPIO.PWM(motor1speed, 100) 30pwmR.start(0) 31GPIO.output(motor1speed, 1) 32pwmR.ChangeDutyCycle(23) 33 34 35while True: 36 try: 37 time.sleep(0.1) 38 39 if(GPIO.input(SENSOR_PORT) == 1): 40 motorstop() 41 GPIO.output(LED, GPIO.HIGH) 42 else: 43 GPIO.output(LED, GPIO.LOW) 44 45 except KeyboardInterrupt: 46 GPIO.cleanup() 47 sys.exit()

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

Python 3.7.2

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

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

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

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

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

guest

回答3

0

システム側で提供されているマルチスレッド/マルチプロセスの仕組みを使用するのでない限り、いくつかの作業を「並行」して行おうというのなら、「指定時間なにもしません」な命令があったらだめでしょう。そのプログラムで言えばtime.sleep()で長時間眠ったら、気がついたら翌日の朝になっていて宿題は全然できていない、ということになってしまいます。
(システム側で並列を管理しているときは、逆に明示的に時間を切ってシステムに制御を返したりしますが)

基本的には

[擬似コード] 開始時刻を記録 モーターを回し始める ループ モーター回転フラグをリセット 開始時刻から3秒以内? モーター回転フラグをセット センサー値を得る センサー反応あり? モーター回転フラグをリセット モーター回転フラグによってモーター回転を制御

のようにすればよいのではないでしょうか。


以下余談(の方が多い?)

センサーが起動、センサーに反応している間はGPIO24に入力信号が行き

別にセンサーが「起動」するわけではないでしょう。プログラムを見る限り、常に動作しているセンサーと思います。
また、センサーが起動しているときだけ、反応しているときだけ「入力信号が行」くわけでもないはずです。
センサーは常に状態を検知して出力していて、あなたが入力信号を読み取る操作をしているかどうか、そういうことではないですか?
「モノを作る」という立場で見るのなら、実際の動作から乖離した理解をしないほうがいいです。


GPIO.add_event_detect(24, GPIO.FALLING, bouncetime=300)
これはセンサーの動作をイベントで拾おうという意図? イベントハンドラ/コールバック関数は?


GPIO.setup(13,GPIO.OUT) GPIO.setup(19,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(15,GPIO.OUT)

のようにピン番号を毎回プログラム中にベタに書かずに

motor1Speed=15 motor1Direction=21

などと一旦変数に格納することで名前をつけてから

GPIO.setup(motor1Speed,GPIO.OUT) GPIO.setup(motor1Direction,GPIO.OUT)

などと使うようにしましょう。そうすると混乱が減ると思います。
19ピンの使い方がなんかヘンな気がして仕方ないです。

pwm = GPIO.PWM(19, 30) pwm.start(0) pwm.ChangeDutyCycle(0) GPIO.output(19, 1) #これまでのPWM設定はなんだったの?

一方、13ピンは全然登場しません。冒頭で
GPIO.setup(13,GPIO.OUT)
の後は、モーターパートの最後で
GPIO.output(13, 0)
としてるだけ?

pwmの19は13の間違いだったりしませんか?


RaspberryPi/Pythonの流儀はあまり知らないのですがPWMの使い方ってこうなるのでしょうか?

... pwmR = GPIO.PWM(15, 100) #15ピンを100Hz(随分周波数低くない?)でPWMにするんですね pwmR.start(0)#デューティー0(つまり出力なし)で開始、と pwmR.ChangeDutyCycle(0)#連続して0にする? start(0)を信用できない? ... pwmR.ChangeDutyCycle(23) time.sleep(3.0) #3秒間回転 ... pwmR.stop() time.sleep(3.0) ... GPIO.output(15, 0) #敢えて0を出力する意味は?

投稿2021/12/04 22:47

thkana

総合スコア7629

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

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

ryu-12

2021/12/06 12:28

thkana様 返信が遅れて申し訳ありません。ご指摘ありがとうございます。 おっしゃる通り、不必要な部分の削除や、GPIOを変数に格納などを行い、プログラムを作り直してみました。センサーに使用している、「GPIO 24」を一旦スイッチのように置き換えて作成してみましたが、なんとかセンサー反応後にモーターを停止させることができました。 ですが、そのあとのモーターの再稼働がうまくいかず、悩んでいます。 何度も質問するようで申し訳ございませんが、何か解決策はないでしょうか。下記に修正したプログラムを貼っておきます。 import RPi.GPIO as GPIO import time import sys GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) motor1speed=15 motor1Direction=21 SENSOR_PORT = 24 LED = 35 def motorstop(): pwm.stop() pwmR.stop() GPIO.setup(19,GPIO.OUT) GPIO.setup(motor1speed,GPIO.OUT) GPIO.setup(motor1Direction,GPIO.OUT) GPIO.setup(SENSOR_PORT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(LED, GPIO.OUT) #モーター制御 pwm = GPIO.PWM(19, 100) pwm.start(0) GPIO.output(motor1Direction, 0) pwm.ChangeDutyCycle(40) pwmR = GPIO.PWM(motor1speed, 100) pwmR.start(0) GPIO.output(motor1speed, 1) pwmR.ChangeDutyCycle(23) while True: try: time.sleep(0.1) if(GPIO.input(SENSOR_PORT) == 1): motorstop() GPIO.output(LED, GPIO.HIGH) else: GPIO.output(LED, GPIO.LOW) except KeyboardInterrupt: GPIO.cleanup() sys.exit()
thkana

2021/12/06 12:36

ここは「コメント」欄です。 Pythonプログラムに対してはインデントが保存されないという致命的な欠点があります。 というか、あくまで「コメント」のための場所なので、質問の状態が何か変化したということならば質問に(前のを消して書き換えるのではなく)追記していっていただければと思います。
ryu-12

2021/12/06 13:26

thkana様 ご指摘ありがとうございます。 わかりました。質問に追記しておきます。
guest

0

詳しいわけではないのですが、たぶん、GPIOの値は設定すればその値を保持してくれるのでしょうから、並列にする必要はなくて、「GPIO.input(24)」の値が1になったらモータを止めるようにすればいいのではないでしょうか。
そして、たとえば0になったらモータを再び回すというような処理にすれば、センサーのON/OFFがモータの回転と連動するようになりそうですが。

投稿2021/12/04 15:14

TakaiY

総合スコア12743

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

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

ryu-12

2021/12/06 12:55

TakaiY様 返信が遅くなり申し訳ありません。ご指摘ありがとうございます。 ご指摘の通りに「(GPIO.input(24) == 1)」の形に直し、プログラム全体を修正しました。なんとかセンサー反応後にモーターを停止させることに成功しましたが、停止後にモーターを再稼働させることがうまくできません。何度も質問するようで申し訳ございませんが、何か解決策があれば教えていただけないでしょうか。下記に修正後のプログラムを貼っておきます。 import RPi.GPIO as GPIO import time import sys GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) motor1speed=15 motor1Direction=21 SENSOR_PORT = 24 LED = 35 def motorstop(): pwm.stop() pwmR.stop() GPIO.setup(19,GPIO.OUT) GPIO.setup(motor1speed,GPIO.OUT) GPIO.setup(motor1Direction,GPIO.OUT) GPIO.setup(SENSOR_PORT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(LED, GPIO.OUT) #モーター制御 pwm = GPIO.PWM(19, 100) pwm.start(0) GPIO.output(motor1Direction, 0) pwm.ChangeDutyCycle(40) pwmR = GPIO.PWM(motor1speed, 100) pwmR.start(0) GPIO.output(motor1speed, 1) pwmR.ChangeDutyCycle(23) while True: try: time.sleep(0.1) if(GPIO.input(SENSOR_PORT) == 1): motorstop() GPIO.output(LED, GPIO.HIGH) else: GPIO.output(LED, GPIO.LOW) except KeyboardInterrupt: GPIO.cleanup() sys.exit()
TakaiY

2021/12/06 14:00

インデントが無いのね読み難いのですが、 モータを止めるときには、motorstop()のような処理をしているのに、モータを動かすときにはLEDの状態を変えているだけですよね。これではモータは回らないでしょう。 また、処理としては、センサーのその時の値でなく、変化によって、命令を変えるのがいいでしょうね。 フラグを作って、モータONのときにセンサーが反応したらOFFに、OFFの時にセンサ反応がなくなったらONにするというような。
guest

0

自己解決

ご指摘してくださった皆様
たくさんのご指摘、ありがとうございました。センサーの状態の変化を条件にして修正したところ、成功させることができました。下記は成功したプログラムです。

Python3

1import RPi.GPIO as GPIO 2import time 3import sys 4import datetime 5GPIO.setwarnings(False) 6GPIO.setmode(GPIO.BOARD) 7 8motor1speed=15 9motor1Direction=21 10SENSOR_PORT = 24 11LED = 35 12 13 14GPIO.setup(19,GPIO.OUT) 15GPIO.setup(motor1speed,GPIO.OUT) 16GPIO.setup(motor1Direction,GPIO.OUT) 17GPIO.setup(SENSOR_PORT, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 18GPIO.setup(LED, GPIO.OUT) 19 20#モーター制御 21def motorstart(): 22 pwm = GPIO.PWM(19, 100) 23 pwm.start(0) 24 GPIO.output(motor1Direction, 0) 25 pwm.ChangeDutyCycle(40) 26 pwmR = GPIO.PWM(motor1speed, 100) 27 pwmR.start(0) 28 GPIO.output(motor1speed, 1) 29 pwmR.ChangeDutyCycle(23) 30 31motorstart() 32 33while True: 34 try: 35 if(GPIO.input(SENSOR_PORT) == 0): 36 motorstart() 37 GPIO.output(LED, GPIO.LOW) 38 39 else: 40 GPIO.output(LED, GPIO.HIGH) 41 42 except KeyboardInterrupt: 43 GPIO.cleanup() 44 sys.exit()

投稿2021/12/07 13:01

ryu-12

総合スコア2

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

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

thkana

2021/12/07 13:19

「モーターが3秒間まわる」というのは変更後のプログラムでは要件でなくなっていたのですか...
ryu-12

2021/12/07 14:37

thkana様 はい。もともとは、どうすればモータを停止させられるのかを調べるために入れていたので、そのままにしていました。最終的には「センサーの状態の変化によってモーターを停止、稼働」させたいだけでしたので…。 紛らわしいプログラムを入れていてすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問