はじめに

ここではモータの制御方法について説明しています.RPiCarには2個のモータがあり,それぞれ左右の車輪とギアボックスを介して接続されています.これにより,その場での旋回ができます.加えて,各モータの回転速度を変化させられます.このようなモータの制御方法についてここでは説明します.

環境

  • OS: Raspberry Pi OS Bulleyes
  • Java: OpenSDK Version 11
  • GPIO Controller: Pi4J Version 2.2
  • プログラミングを行うパソコン: Ubuntu 20.2
  • IDE: Visial Studio Code Version 1.72.2

なお,すでに開発環境であるVisual Studio Code を使ってリモート開発ができる状態であることを前提としています.また,ファームウェアをダウンロードしていることを前提にしています.もしまだダウンロードしていないようであれば,こちらにある記事を見て行ってください.

モータとモータドライバ

 RPiCarには2つのタミヤ製両軸モータNo.402 GP.402 ライトダッシュモーターPROが備わっています.このモータは本来,ミニ四駆®で使われるもので一つのモータで前輪と後輪を回転させるために両軸になっています.このモータを2個使ってツインギアボックスを駆動しています.ツインギアボックスは本来は方軸のモータで駆動できますが,回転数を検知するためにツインギアボックスを駆動していない方の軸にロータリエンコーダをつけてあります.

モータを駆動する時,Raspberry Piの端子とモータをつないでも回転させられません.その理由はRaspberry Piの端子からはそれほど多く電流を流せないからです.そこでモータを回すにはたくさんの電流を流すための回路が必要になります.RPICarではモータドライバとしてZXBM5210-S-13というICを用いています.このICでは3本の入力端子があり,そのうち2本のHigh/Lowの組み合わせで惰性,正転,逆転,ブレーキの4状態を指定し,もう1本のデューティ比で速度を調整できます.

ロータリエンコーダ

ロータリエンコーダはモータの回転数を検知するためのデバイスです.先ほど説明した両軸モータの片方に,中心から放射状に配置された孔のある円盤を取り付け,その孔の貫通方向にフォトインタラプタの光路になるように設置することで,孔があるタイミングでは受光し,ないタイミングでは受光しないため,その受光した回数と時間によりモータの回転数を検知できます.下は模式図です.黒い部分が円盤,銀色がモータの軸,灰色がフォトインタラプタです.モータが回転すると円盤も回転し,円盤にある孔の有無をフォトインタラプタが検知できます.フォトインタラプタから得られる電気信号がRaspberry Piに送られるとき,ヒステリシスのあるインバータ(いわゆるシュミットトリガインバータ)を通すことで,より方形波に近い信号に整形されます.Raspberry Piからみると,この方形波のHigh/ Lowの回数を検知することでモータの回転数が検知できます.

01

クラス関係

下に関係するクラス図を示します.

 真ん中の上あたりにあるDrivingDivisionクラスでモータとフォトインタラプタを使って直進,後退,左右旋回,左右曲折,停止を正確に行います.このクラスはThreadクラスを継承しており,常に動作を管理しています.

DrivingDivisionクラスの上側にあるクラス群がロータリエンコーダに関するものです.スーパクラスとしてRotaryEncoderクラスがあり,サブクラスとしてRightRotaryEncoderクラスとLeftRotaryEncoderクラスがあります.RotaryEncoderクラスにはgetRotationNumメソッドがあり,これによりどれだけ開店したかを得られます.また,clearメソッドで今までの回転数をクリアできます.

DrivingDivisionクラスの下側にあるクラス群がモータに関するものです.スーパクラスとしてMotorクラス,サブクラスとしてRightMotorクラスとLeftMotorクラスがあります.

ClassDiagram

プログラム

ではこれらのクラスでモータを制御してみましょう.モータで行えることはいくつかありますが,ここでは直進,左旋回,左モータの速度を75,右モータの速度を50にして右にゆっくり曲がっていく動作の3種を試しましょう.

直進

まずは直進です.いずれの動作でもそうですが,DrivingDivisionクラスのインスタンスを使います.このインスタンスをgetInstanceメソッドで取得し,goStraightメソッドを呼び出すことでRPiCarを直進させることができます.このメソッドにはスピードをパラメタとして持っています.0から100までの値を指定してください.直進をストップさせるにはstopMotionメソッドを呼び出します.

今回は3秒間直進して停止するプログラムを書いてみます.下のプログラムをご覧ください.goStraightメソッドを速度70として呼び出した後,3秒間待ち,stopMotionメソッドを呼び出しています.

 

        public static void main(String[] args) throws Exception {

        DrivingDivision dd = DrivingDivision.getInstance();

        dd.goStraight(70);
        Thread.sleep(3000);
        dd.stopMotion();

        Pi4J.newAutoContext().shutdown();
    }

 

動作させるだけであればそれだけではこれだけの知識で問題ありませんが,内部で行っている処理についても補足しておきます.左右のモータドライバに対して同じように命令してもモータの回転数は必ずばらつき,その結果として直進してくれません.そこで前に説明したロータリエンコーダにより回転数をチェックしています.RightRotaryEncoderクラスにあるgetRotationNumメソッドにより右タイヤの回転数,LeftRotaryEncoderクラスにあるgetRotationNumメソッドにより左タイヤの回転数を得られます.直進,後退,右旋回,左旋回の4動作については回転する方向は違うにせよ回転数ということだけを考えると左右の回転数は同じである必要があります.そのため,上記メソッドにより回転数を取得し,左右で回転数が異なってしまった場合にはその補填するために速度をPWMで微調整しています.

左旋回

次に左旋回です.先ほどの直進と同様にDrivingDivisionクラスのインスタンスをgetInstanceで取得し,そのインスタンスからrotateLeftメソッドを速度のパラメタを伴いながら呼び出します.下には速度90で3秒間左旋回するプログラムを示します.

 

        public static void main(String[] args) throws Exception {

        DrivingDivision dd = DrivingDivision.getInstance();

        dd.rotateLeft(80);
        Thread.sleep(3000);
        dd.stopMotion();

        Pi4J.newAutoContext().shutdown();
    }


右へ曲がっていく動作

最後は右へ曲がっていく動作です.これまでのプログラムでは両輪の回転速度は一緒になるようにしていましたが,今回は左右のタイヤは速度が異なります.具体的には,左のモータが75,右のモータが50の速度で回転させることで右へ曲がっていく動作をさせます.この動作をさせるのがsteerメソッドです.左右の速度をパラメタとして指定することで上記の動作を実現できます.下のプログラムは3秒間右に曲がる動作をするプログラムです.

 

    public static void main(String[] args) throws Exception {

        DrivingDivision dd = DrivingDivision.getInstance();

        dd.steer(50, 75);
        Thread.sleep(3000);
        dd.stopMotion();

        Pi4J.newAutoContext().shutdown();
    }