🥶
Raspberry PiでPWMを使おうとしたらまともじゃなかった話
起きたこと
- Raspberry PiでPWMでサーボを制御しようとした
- なんかめっちゃサーボ暴れる
- WTF
環境
ハードウェア
- Raspberry Pi Zero W
- MR995のコピー品(サーボモーター)
ソフトウェア
- Raspbian GNU/Linux 11 (bullseye)
- Python 3.9.2
- RPi.GPIO 0.7.0
コード(動かない)
test.py
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
servo_pin = 13
GPIO.setup(servo_pin, GPIO.OUT)
pwm = GPIO.PWM(servo_pin, 50) # 50Hz = 20ms周期
pwm.start(0)
def set_angle(angle):
print(angle)
angle = angle + servo_offset
duty = 2 + angle / 18 # 角度をデューティ比に変換
print("duty:"+str(duty))
pwm.ChangeDutyCycle(duty)
time.sleep(1)
pwm.ChangeDutyCycle(0)
#中右中左と動く
set_angle(90)
time.sleep(5)
set_angle(0)
time.sleep(5)
set_angle(90)
time.sleep(5)
set_angle(180)
time.sleep(5)
pwm.stop()
GPIO.cleanup()
結果、ジッタが発生してまともに動かない
いや、動きはするが、角度が確定せずブルブルと動く
改善1(主にハードウェア)
- 電源にコンデンサをつける(16V100μF)
- 電源を変更
- 9V電池から1.5Vx4本の電池を直列接続(合計6V)に変更
- どうやら9Vが適正だと思っていたが6~7V程度が適正だった
- サーボのデータピンにプルダウン抵抗を接続
結果、幾分か収まったがまだ発生する。
改善2(主にソフトウェア)
- pigpioを導入
pigpioのインストール
pigpioはpythonのライブラリ以外にaptでインストールする必要がある。
bash
~$ sudo apt update
~$ sudo apt install pigpio -y
python3のライブラリも入れる。
bash
~$ pip install pigpio
そしてpigpioは事前に起動しておく必要がある。
bash
#superuser権限じゃないと起動しなかったのでsudoは忘れず
~$ sudo pigpiod
ここまで来たらやっとpythonでコードを実行できる。
コード(pigpio)
多分、成功したのでコードを書いておく。
bash
import pigpio
import time
pi = pigpio.pi()
servo_pin = 13 # PWM対応のGPIO
pi.set_PWM_frequency(servo_pin, 50)
def set_angle(angle):
print(angle)
pulsewidth = 500 + (angle / 180) * 2000
print(f"pulsewidth: {pulsewidth}μs")
pi.set_servo_pulsewidth(servo_pin, pulsewidth) # サーボにパルス幅を送る
time.sleep(1)
#中右中左と動く
set_angle(90)
time.sleep(5)
set_angle(0)
time.sleep(5)
set_angle(90)
time.sleep(5)
set_angle(180)
time.sleep(5)
pi.set_servo_pulsewidth(servo_pin, 0)
pi.stop()
これでうまく動いた。
余談
最初はRPi.GPIOの特有な問題なのかなとか思っていたが、マジで特有の問題らしかった。
PWMのパルス管理のタイマーの管理がソフトウェア上で処理している関係上どうしてもずれが出てしまうらしい。
それこそマイクロ秒単位での精度が要求されるPWM制御ではハードウェア上でPWMに最適化された作りになっていないとやはり精度が悪くなってしまうのだろう。
最近になってAI用の演算装置をNPUだとか言って専門的に処理するコアが出てきたのと同じことだと思う。
Discussion