はじめに
Donkey Car はESC・サーボの制御にPCA9685(16ch PWM出力ボード)を使用しています。
しかし、Raspberry Pi単体でもサーボ制御信号(PWM信号)は出力できるはずです。
PCA9685はいらない子なのではないか?
そう思って調べてみたところ、割と簡単に外せました。
ラズパイのPWM出力
ラズパイからPWM出力する方法はいくつかあります。
pythonから利用しやすいものだと、RPi.GPIO や pigpio などがあります。
RPi.GPIO はソフトウェアでやっているのか、精度が悪いです。パルス幅が安定せず、サーボがプルプルしてします。(←聞いた話)
pigpio が本命でしょうか。
しかし、manage.py
を読んでみると、ServoBlaster を利用している箇所があります。これを使えば、Donkey Car 用の Parts を作らなくてもよさそうです。
というわけで、ServoBlaster を使うことに決めました。
ServoBlaster ビルド
apt
で拾ってこれないので、git clone
して make
します。
cd ~
git clone https://github.com/richardghirst/PiBits.git
cd ~/PiBits/ServoBlaster/user/
make servod
(make install
でサービス化できるようなのですが、どうもうまく動かないので推奨しません(後述))
ServoBlaster 起動
sudo ~/PiBits/ServoBlaster/user/servod --idle-timeout=2000 --step-size=4
で起動します。
オプション--idle-timeout=2000
は、使ってないときにサーボへの出力を止めるオプションです。これにより、manage.py
を動かしてないときの消費電力が若干減ると思います。
オプション--step-size=4
は、STEERING_LEFT_PWMなどの1が何マイクロ秒相当かという設定です。このオプションにより、PCA9685の場合とほぼ同じPWM設定値を流用することができます! (ほぼ同じですが、若干違います(後述))
manage.py 追記
manage.pyの、elif cfg.DRIVE_TRAIN_TYPE == "SERVO_HBRIDGE_PWM":
のブロックの後ろに、下記コードを追加します。
elif cfg.DRIVE_TRAIN_TYPE == "SERVO_ESC_ONBOARD":
from donkeycar.parts.actuator import ServoBlaster, PWMSteering, PWMThrottle
steering_controller = ServoBlaster(cfg.STEERING_CHANNEL)
steering = PWMSteering(controller=steering_controller,
left_pulse=cfg.STEERING_LEFT_PWM,
right_pulse=cfg.STEERING_RIGHT_PWM)
throttle_controller = ServoBlaster(cfg.THROTTLE_CHANNEL)
throttle = PWMThrottle(controller=throttle_controller,
max_pulse=cfg.THROTTLE_FORWARD_PWM,
zero_pulse=cfg.THROTTLE_STOPPED_PWM,
min_pulse=cfg.THROTTLE_REVERSE_PWM)
V.add(steering, inputs=['angle'])
V.add(throttle, inputs=['throttle'])
軽く説明すると、DRIVE_TRAIN_TYPE
に SERVO_ESC_ONBOARD
というタイプを追加して、具体的にはこーしてねというのを書いてます。
myconfig.py 修正
下記定数3つを修正します。
DRIVE_TRAIN_TYPE = "SERVO_ESC_ONBOARD"
STEERING_CHANNEL = 11 #pin number on the Raspberry Pi
THROTTLE_CHANNEL = 13 #pin number on the Raspberry Pi
ここのピンNo.は、GPIOの番号ではなく、1~40の物理ピン番号であることに注意してください。
また、標準で使えるのは 7,11,12,13,15,16,18,22 だけです。
ここで11と13を選んだのは、I2C接続も挿さってる場合に挿しやすい場所だったからです。
この辺はお好みでどうぞ。
配線
電源とGNDと信号線が繋がっていればオッケーなので簡単です。
ラズパイ | ESC | サーボ | 備考 |
---|---|---|---|
11 | 白 | GPIOでいうと17 | |
13 | 白 | GPIOでいうと27 | |
赤 | 赤 | ESCとサーボの赤同士をつなげる | |
黒 | 黒 | ESCとサーボの黒同士をつなげる |
ラズパイとサーボ・ESCのGNDが繋がってないような気がしますが、電源側で繋がってるので問題ありません。
ラズパイとサーボ・ESCの電源は繋がないのが正解です。(ESCが電源を供給して、サーボがそれを使っています。)
ラズパイは3.3V I/Oなので、サーボ・ESCからみるとI/O電圧が足りませんが、だいたい閾値がVcc/2のことが多いので、まあOKだと思います。
最近のBEC 6VのESCを積んだラジコンだと不安定になるかも???
ご心配ならI/O電圧を変換するナニカを挟んでくださいませ。
とりあえず、手元の Robocar Store で買ったDonkeyCar(のベース車両であるHSP 94186)では動いています。
走行
あとはいつものように走行するだけです!
cd ~/mycar
python manage.py drive
(実は、「Webコントローラーから制御できてるな」という確認までしただけで、教師走行や自律走行は試しておりません。。。)
細かい話:PWM設定値
PWM設定値の正確な値の話をすると、PCA9685 の場合の1は、パルス間隔を4096で割った値です(12bit PWMなので4096で割るんですヨ)。DonkeyCarではPWM周波数を60Hzにしているので、パルス間隔は1/60です。ということから計算すると
1,000,000[μs]/60/4096 ≒ 4.069[μs]
となります。
一方、ServoBlaster の場合は設定値がマイクロ秒単位で設定できて、設定どおり4マイクロ秒です。
1.7%ぐらいの誤差となります。ニュートラルが370だったとすると、376ぐらいに変更する必要があります。
おまけ:キャリブレーション
https://docs.robocarstore.com/guide/calibrate/ でやるキャリブレーションはPCA9685に接続されていることが前提なので、この記事の配線方法にすると使えません。
PWM出力を手動で行うことが、下記コマンドでできます。
echo P1-11=370 > /dev/servoblaster
一応説明しておくと、P1は固定で、11がピン番号、370が出力値です。
課題:servodのサービス化
ServoBlasterをmakeしたときのディレクトリで
sudo make install
をすると、実行ファイルservod
が /usr/local/sbin/
にコピーされ、起動用の /etc/init.d/servoblaster
が作成されます。
起動オプション --step-size=4
は、/etc/init.d/servoblaster
の OPTS
に追記する形で
OPTS="--idle-timeout=2000 --step-size=4"
としておけばよさそうです。
しかし、どうもOS起動後に --step-size=4
が効いてないような動作になります。
psコマンドで見ると引数は渡されているっぽいんですけれども。
sudo /etc/init.d/servoblaster restart
でサービスの再起動をしてみると、なぜか /dev/servoblaster
が見えなくなってしまいます。
psコマンドで見るとプロセスは生きているっぽいんですけれども。
とりま、stop start で正常動作するようにはなります。
sudo /etc/init.d/servoblaster stop
sudo /etc/init.d/servoblaster start
OS起動後にコマンド打たなきゃいけないなら、サービス化しなくてもいいんじゃないかと思います。
サービス化してもちゃんと動くようにしたいんですけれどもね・・・
おわりに
Donkey Car から PCA9685 を外す方法を紹介しました。
なんで設定が簡単にできるようになってないのか不思議です。しかし、ソースを読んでると、なんかこのぐらいの改造は設定のうちというふいんきを感じます。
この記事を書いた後、 ~/projects/donkeycar/donkeycar/parts/actuator.py
の中に PiGPIO_PWM
というクラスを見つけてしまいました。pigpio も似たような「設定」で使うことができそうです。
追記:pigpioを使う方法を書きました → https://qiita.com/rukihena/items/b3d16c2bf6e1a62b0c92