14,540 views
この記事は最終更新から 1142日 が経過しています。
1. やってみたいこと
Raspberry Piの ハードウェア PWMを使ってサーボモーターを廻してみたい。
2. ハードPWM vs ソフトPWM
(1) ハードPWM
PWMコントローラ(=PWM専用のH/W)で制御するため、指定したパルス幅を安定して維持できる。
(2) ソフトPWM
CPUで制御するため、CPUが高負荷状態のときに PWM周波数が狂ったりパルス幅が広がったりする。
(3) どちらがよいのか?
目的に応じて使い分ければよい。
LED点灯の明るさを PWMで制御する場合、多少パルス幅がぶれても人の目にはよくわからない。
サーボモーターを PWMで制御する場合、パルス幅が一定でないと回転角度が小刻みにぶれてしまう。
3. パーツを調達
(1) モーターを購入
(2) モーターの仕様
このモーターの仕様は以下の通り。
http://akizukidenshi.com/download/ds/towerpro/SG90_a.pdf
まとめると以下の通り。
・周波数 : 50Hz(1周期が 20ms)
・Duty Cycle 0.50ms : -90度回転
・Duty Cycle 1.45ms : 0度回転
・Duty Cycle 2.40ms : +90度回転
・電圧 : 4.8V ~ 5V
・回転速度 : 0.1s / 60度
4. 設計
(1) GPIOはどう使う?
ラズパイ公式ページの情報によれば、ハードPWMを使いたければ GPIO12,13,18,19を使えと記載されている。
https://www.raspberrypi.org/documentation/usage/gpio/README.md
なので…
今回は GPIO12 をサーボモーター制御のための PWM信号線として使う。
でも…
GPIO12の電圧は 3.3Vだ。
上記のモーターのデータシートには PWM信号線の電圧は 4.8V ~ 5Vと書いてあるがよいのか?
(2) モーターは別電源で駆動する。
消費電力の大きなモーターの電源をラズパイから取ると、ラズパイに大きな電流が流れて壊れてしまうかも…
この制限値はどこに書かれているのか?
公式ページでは見つけられなかったが、こちらのページ(↓)では
https://elinux.org/RPi_Low-level_peripherals#Power_pins
・3.3Vのピンからは合計 50mA
・5Vのピンからは合計 1A からラズパイの動作に必要な分を引いた残りだけ
と書かれている。
50mAといったら LED x 3個しか繋げちゃダメってことか?
よくわからないので…
消費電力の大きなデバイスを駆動するときには、ラズパイとは別に電源を用意した方がよさそうだ。
今回はモーター駆動用に 5Vの電源を別に用意 しよう。
5. 実装
・ラズパイとは別に、サーボモーター用に 5Vの電源を用意する。
・サーボモーターの GNDを ラズパイ側の GNDに繋ぐ。(GNDの電位を共通にするため)
6. マイコンで制御してみる!
今回も (23) 【1-3】マイコンで電子工作入門:LED点滅 と同じように RPi.GPIO を使用する。
(1) ターミナルを起動し、Python3を実行する。
python3
(2) 必要な Pythonモジュール(=パッケージ)を読み込む。
import RPi.GPIO as GPIO
(3) GPIOを初期化する。
GPIO制御関数で制御対象のピンを指定する際に、ピン番号ではなく GPIO番号を指定することにする。
・ピン番号指定: GPIO.BOARD
・GPIO番号指定: GPIO.BCM
GPIO.setmode(GPIO.BCM)
GPIO12を出力ポートとして使用する。
GPIO.setup(12, GPIO.OUT)
GPIO12を PWM(50Hz)として使用する。
pwm = GPIO.PWM(12, 50) pwm.start(0)
(4) モーターを廻す。
0度
前述のモーターのデータシートに従えば、
・0度の Duty Cycleは 1.45ms
・周波数 50Hz(=20ms)
なので、設定するパルス幅は…
1.45 / 20 = 7.25[%]
pwm.ChangeDutyCycle(7.25)
ここをホームポジションとして記憶する。
+90度
前述のモーターのデータシートに従えば
・+90度の Duty Cycleは 2.4ms
・周波数 50Hz(=20ms)
なので、設定するパルス幅は…
2.4 / 20 = 12[%]
pwm.ChangeDutyCycle(12)
半時計周りに 90度回転した。
-90度
前述のモーターのデータシートに従えば、
・-90度の Duty Cycleは 0.5ms
・周波数 50Hz(=20ms)
なので、設定するパルス幅は…
0.5 / 20 = 2.5[%]
pwm.ChangeDutyCycle(2.5)
時計周りに 180度回転した。
+45度
前述のモーターのデータシートに従えば、
・0度の Duty Cycleは 1.45ms
・+90度の Duty Cycleは 2.4ms
・周波数 50Hz(=20ms)
なので、パルス幅は…
+45度の Duty Cycleは
(2.4 – 1.45) / 90 x 45 + 1.45 = 1.925[ms] ※リニアだとすれば
なので、設定するパルス幅は…
1.925 / 20 = 9.6[%]
pwm.ChangeDutyCycle(9.6)
確かに 45度の位置まで回転した。
(5) 終了処理
pwm.stop() GPIO.cleanup()
問題発生!
意図した通り、確かにモーターは指定した角度に回転してくれた。
でも…
勝手に動く…
ビリビリと音を立てて振動したり、突然豪快に 180度回転したりする。
パルスの立ち上がりタイミングや幅など時間軸方向で乱れる ジッタ というやつか?
ToDo: ACアダプターが 5V 1.5Aの物を使用していた。電流値 2Aなどの大きな物に変更して試してみる。
回りすぎて振り切って戻ってこなくもなった。
モーターが動かなくなり「壊れたか…」と覚悟したが、これは無理やり手で回して復旧させた。
ひょっとしてソフトPWMで動いている?
RPi.GPIO.PWM(12, 50)
RPi.GPIOモジュールのこの使い方では、ハード PWM制御をしてくれていない?
オシロで PWM信号線を覗き見ると 20ms周期でパルスが流れ、パルス幅が乱れているようには見えない。
こんな状態でも不安定&豪快に回転したりする。
・パルス幅が一定範囲からはみ出したとき、
・信号の立ち上がりのタイミングがずれたとき、
にトリガーをかけてオシロの表示を停止させてみたいが、できない…
ソフトPWMで本当におかしな信号を出力しているのか? が確認できない…
(5) ハードウェアPWMでモーターを廻す。【仕切り直し】
RPi.GPIOの中身を未確認だが、RPi.GPIO.PWM() はソフトPWMであることはほぼ間違いない。
そこで…
wiringpi でハード PWMが出来るという情報に辿り付き、これを試してみる。
Super Userで Pythonを起動する。
sudo python
Python Shellで以下を打ち込む。
import wiringpi wiringpi.wiringPiSetupGpio() wiringpi.pinMode(18, wiringpi.GPIO.PWM_OUTPUT) wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS) wiringpi.pwmSetRange(1024) wiringpi.pwmSetClock(375) wiringpi.pwmWrite(18, 74) # 0deg. (1024 x 7.25% = 74) wiringpi.pwmWrite(18, 123) # +90deg. (1024 x 12% = 123) wiringpi.pwmWrite(18, 26) # -90deg. (1024 x 2.5% = 26)
・PWM_MODE_MS : PWM周波数固定モードを選択する。 参考情報
・pwmSetRange(1024) : Duty Cycle = 100% のときに 1024とする。
・pwmSetClock(375) : PWM周波数 = ラズパイ内蔵PWMコントローラの動作クロック周波数{19.2MHz} / (PWM信号の周波数{50Hz} x レンジ{1024})
今度はモーターが ピタッ と止まり、ビリビリしびれたような動きは全く見せない。
これがハード PWMの安定感だ。すばらしい!
(6) もし自分でちゃんと作りたければ…
ラズパイに搭載されているマイコンの仕様書を見て、PWMコントローラのドライバを自作する。(P.138 ~)
https://www.raspberrypi.org/app/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
wiringpi の中ではこの制御をしているのだろうから、プログラムの中身を覗いて制御方法を理解するのもよい。
いつか余裕が出来たらやってみよう。
7. 所感
今回はモーターがおかしな挙動を見せたので、不良品なのではないかと疑ってしまった。
実際にはラズパイのソフトウェア PWMの不安定さがモーターの誤作動となって表れていた。
※近いうちに「5V出力昇圧DCDCコンバーター」を使ってPWM信号の電圧を上げて実験してみよう。
それに比べてハードウェア PWMは安定感がすばらしい!
いつかラジコンカーのステアリングに使ってみたい。
また、PWMを使えば、アナログデバイスをデジタル信号で制御できる。
例えば、
・LEDの明るさを好きに変える。
・モーターの回転速度を好きに変える。
など、各デバイスに入力する電圧を変えなくても制御できてしまう。
いつかきっと何かの役に立つだろう。
いつかきっとラジコンが作りたくなるはず…
参考情報
ありがとうございます。 m(_ _)m
https://www.slideshare.net/YoshimotoYukiyoshi/raspberry-pipwm
連載
Raspberry Piの初期設定から簡単な動作実験まで、以下はマイコン制御入門の連載です。
(21) 【連載1-1】マイコンで電子工作入門:選定
(22) 【連載1-2】マイコンで電子工作入門:ラズパイ初期設定
(23) 【連載1-3】マイコンで電子工作入門:LED点滅
(24) 【連載1-4】マイコンで電子工作入門:時報を作る
(26) 【連載1-5】マイコンで電子工作入門:サーボモーターを廻す
(27) 【連載1-6】マイコンで電子工作入門:合成音声で時報 ←次回
サーボへの信号レベルが足らないです。
ソフトPWMは悪くないかと、
ありがとうございます。
ソフトPWM, ハードPWMともに出力信号レベルは 3.3Vなのです…
このため、時間軸の方を疑ってしまうのです。