4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Donkey Car から PCA9685 を取っ払って、ESC・サーボをラズパイに直結する ~pigpio版~

Posted at

はじめに

前回、Donkey Car から PCA9685 を取っ払って、ESC・サーボをラズパイに直結するという記事を書きました。これはPWM出力にServoBlasterを利用するものでした。

ServoBlasterはaptでインストールできず、なんだかアウェイ感が否めません(※個人の感想です)

その記事でも書きましたが、pigpioが使えそうです。こちらはaptでインストールできるホーム感がうれしいところです。

ということで、pigpio を使ってまいります。

pigpio インストール

apt でインストールできてホーム感がありますね(大事なことではないけど2回言ってみました)

sudo apt install python3-pigpio
sudo systemctl start pigpiod

manage.py 追記

(あとで仕切り直しで上書きしますが、参考までに)

    elif cfg.DRIVE_TRAIN_TYPE == "SERVO_ESC_PIGPIO":
        from donkeycar.parts.actuator import PiGPIO_PWM, PWMSteering, PWMThrottle

        steering_controller = PiGPIO_PWM(cfg.STEERING_CHANNEL)
        steering = PWMSteering(controller=steering_controller,
                                        left_pulse=cfg.STEERING_LEFT_PWM*305,
                                        right_pulse=cfg.STEERING_RIGHT_PWM*305)

        throttle_controller = PiGPIO_PWM(cfg.THROTTLE_CHANNEL)
        throttle = PWMThrottle(controller=throttle_controller,
                                        max_pulse=cfg.THROTTLE_FORWARD_PWM*305,
                                        zero_pulse=cfg.THROTTLE_STOPPED_PWM*305,
                                        min_pulse=cfg.THROTTLE_REVERSE_PWM*305)

        V.add(steering, inputs=['angle'])
        V.add(throttle, inputs=['throttle'])

*305 は何をやっているかというと、PCA9685のときの設定値を流用するための係数です。

ServoBlasterで設定した4マイクロ秒ベースの値を使う場合は*300にしましょう。
ラジコンの世界からやってきて、1マイクロ秒ベースで設定したい場合は*75にしましょう。

なお、1は1/75/1000000[s]です。

myconfig.py 修正

(あとで仕切り直しで上書きしますが、参考までに)

下記定数3つを修正します。

DRIVE_TRAIN_TYPE = "SERVO_ESC_PIGPIO"
STEERING_CHANNEL = 12           #pin number on the Raspberry Pi
THROTTLE_CHANNEL = 13           #pin number on the Raspberry Pi

今回は物理ピン番号でなく、GPIO番号のほうで指定します。ややこしや。

12と13を選んだのは、ハードウェアの制約でほぼそれしか選べないからです。
使えないピンを選ぶと manager.py起動時に

pigpio.error: 'GPIO has no hardware PWM'

というエラーが出て実行出ません。

制約がきつすぎますね。ピンが隣り合っていないと、前回記事の「これをこうしてこうじゃ」の簡単な配線ができなくて微妙です。

仕切り直し

DonkeyCar の PiGPIO_PWM クラスのソースを読んでみると、pigpioのhardware_PWM() を利用しています。これは2chしかないハードウェアPWMをそのまま使っていてモッタイナイです。

一方、pigpioには set_servo_pulsewidth() という関数もあるので、こちらを使いたいと思います。

ServoBlaster は PWMとDMAを組み合わせて、多チャンネルPWMを実現しています。詳しく調べていませんが、 pigpio のset_servo_pulsewidth() も同じ仕組みで動いていると思われます。

PiGPIO_SERVOクラス作成

クラスの内容は以下の通りとなります。
PWM周波数の設定をしていませんが、50Hzで動いているようです。これは特に変える必要はないでしょう。

class PiGPIO_SERVO():

    def __init__(self, pin, pgio=None):
        import pigpio

        self.pin = pin
        self.pgio = pgio or pigpio.pi()
        self.pgio.set_mode(self.pin, pigpio.OUTPUT)

    def __del__(self):
        self.pgio.set_servo_pulsewidth(self.pin, 0)
        self.pgio.stop()

    def set_pulse(self, pulse):
        self.pgio.set_servo_pulsewidth(self.pin, pulse)

    def run(self, pulse):
        self.set_pulse(pulse)

本来は ~/projects/donkeycar/donkeycar/parts/actuator.py に追記するものと思いますが、書き換えるファイルが増えるとバージョンアップなどの際に面倒なことになるので manager.py の適当なところに追記しちゃいましょう。

__del__ の中で self.pgio.set_servo_pulsewidth(self.pin, 0) としているのは、非動作時にPWM出力を止めてサーボをお休みさせるためです。

manager.py修正

ふたたび manager.py の編集です。
上の方で追記したところを下記のように書き換えます。
PiGPIO_PWMの利用は無かったことにします)

    elif cfg.DRIVE_TRAIN_TYPE == "SERVO_ESC_PIGPIO":
        from donkeycar.parts.actuator import PWMSteering, PWMThrottle

        steering_controller = PiGPIO_SERVO(cfg.STEERING_CHANNEL)
        steering = PWMSteering(controller=steering_controller,
                                        left_pulse=cfg.STEERING_LEFT_PWM*4.069,
                                        right_pulse=cfg.STEERING_RIGHT_PWM*4.069)

        throttle_controller = PiGPIO_SERVO(cfg.THROTTLE_CHANNEL)
        throttle = PWMThrottle(controller=throttle_controller,
                                        max_pulse=cfg.THROTTLE_FORWARD_PWM*4.069,
                                        zero_pulse=cfg.THROTTLE_STOPPED_PWM*4.069,
                                        min_pulse=cfg.THROTTLE_REVERSE_PWM*4.069)

        V.add(steering, inputs=['angle'])
        V.add(throttle, inputs=['throttle'])

*4.069 は何をやっているかというと、PCA9685のときの設定値を流用するための係数です。

PiGPIO_SERVO クラスの追加をマジメに actuator.py に行った場合は、 importPiGPIO_SERVO を追加しましょう。

myconfig.py 修正

下記定数3つを修正します。

DRIVE_TRAIN_TYPE = "SERVO_ESC_PIGPIO"
STEERING_CHANNEL = 17           #pin number on the Raspberry Pi
THROTTLE_CHANNEL = 27           #pin number on the Raspberry Pi

今回も物理ピン番号でなく、GPIO番号のほうで指定します。
前回の記事と同じピンを使うように設定してみました。

配線

配線は前回記事と同様です。
(同じにするためにわざわざ PiGPIO_SERVO クラスを作成しました)

走行

あとはいつものように走行するだけです!

cd ~/mycar
python manage.py drive

(実は、「Webコントローラーから制御できてるな」という確認までしただけで、教師走行や自律走行は試しておりません。。。)

細かい話:PWM設定値

set_servo_pulsewidth() はマイクロ秒で指定します。ラジコンの世界から来た人には分かりやすいです。値の指示はマイクロ秒単位でできますが、実際の精度はデフォルトだと5マイクロ秒らしいです。
精度を1マイクロ秒にもできるようですが、メカ側の精度がそんなにないと思うのでいじらなくてもいいんじゃないかと思います。
専用ハードウェアのPCA9685の場合で約4マイクロ秒精度ですし。

おまけ:キャリブレーション

pigs SERVO 17 1500

にて、手動でPWM出力できます。

一応説明しておくと、17がGPIO番号、1500が出力値です。

socket connect failed というエラーが出る場合は、sudo raspi-configで、Remote GPIOを有効にしてください。(5 Interfacing Options -> P8 Remote GPIO にあります)

用事が済んだら

pigs SERVO 17 0

として出力を止めるとサーボ・バッテリーにやさしいと思います。

おわりに

環境整備ばかりしていて教師走行をしておりませんorz
CONFIG.SYS, AUTOEXEC.BATを延々いじっていた学生時代を思い出しますw

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?