BrickPi + LOGO Mindstorms EV3 をゲームコントローラーでコントロールする(後編)

手っ取り早く動かすには、先の あしがらがらくた研究所 by いしわたむねお さんのところから、RPi_DualShock3.c を取得してビルドをします。動作確認ができたら、BrickPiNet をインストールして試します。.NET版なので、apt-get install Mono をしないとダメなんですよね…というか、RasPi のレポジトリに 4.5 の Mono が入っていたか確認してないので、これはあとで確認。手元のものは 12時間かけてビルドをしたものなので、ちょっとお試しという訳にはいかないので。そのうち、パッケージを作りましょう(つーか、パッケージの作り方から学ばないとダメなんだけど)。

■C# からジョイススティックを操作する

C言語でIOCTLしないと駄目かと思ったんですが、Linuxでは /dev/input/js0 にアクセスさえすれば、ボタンやジョイスティックの状態が取れることを知りました linux/joystick.h に詳しい情報があります。
このデバイスは、そのまま C# のファイルストリームでも使えるので、こんな感じに書けます。

Raspberry Pi Series ? Mono C# USB Joystick Handlermpolaczyk | software, robotics, engineering & geeky stuff… | mpolaczyk | software, robotics, engineering & geeky stuff…
http://mpolaczyk.pl/raspberry-pi-mono-c-joystick-handler/
C# で joystick を利用する
https://gist.github.com/moonmile/7c44e5130617c7a76a87

自前のほうは、Dualshock3 専用になっています。どうやら各社のジョイスティック/ゲームパッド事に番号が異なっていて、実地で検証しないとだめなそうです。アプリケーションのほうが対応するというパターンらしいです。

public struct js_event
{
    public UInt32 time;    /* event timestamp in milliseconds */
    public Int16 value;    /* value */
    public byte type;      /* event type */
    public byte number;    /* axis/button number */
    public override string ToString()
    {
        return string.Format("time:{0} val:{1} type:{2} num:{3}", time, value, type, number);
    }
}

type でボタン(0x01)かジョイスティック(0x02)をチェックして、number でボタンの位置を調べます。ジョイステックの場合は0がニュートラル(中央)で、スティックを倒すとそれぞれ +/- に振れます。
ここでは、まだ作っていないのですが、Dualshuck3 ではコントローラ自体の傾き検知が入っています。23,24,25,26番にデータが入って来るのですが、どの軸なんだろう、ってのは後で調べましょう。

public bool SELECT { get { return Button0; } }
public bool LeftStick { get { return Button1; } }
public bool RightStick { get { return Button2; } }
public bool START { get { return Button3; } }
public bool Up { get { return Button4; } }
public bool Right { get { return Button5; } }
public bool Down { get { return Button6; } }
public bool Left { get { return Button7; } }
public bool L2 { get { return Button8; } }
public bool R2 { get { return Button9; } }
public bool L1 { get { return Button10; } }
public bool R1 { get { return Button11; } }
public bool Triangle { get { return Button12; } }
public bool Circle { get { return Button13; } }
public bool Cross { get { return Button14; } }
public bool Square { get { return Button15; } }

public int LeftAxisX { get { return Axis0; } }
public int LeftAxisY { get { return Axis1; } }
public int RightAxisX { get { return Axis2; } }
public int RightAxisY { get { return Axis3; } }

■BrickPiNet.dll を使う

そんな訳で、BrickPiNet https://github.com/moonmile/BrickPiNet を作成中です。

/dev/input/js0 を read して、ちまちまと調べていけばジョイスティックの操作はできるのですが、ボタンを離したタイミングとか、同時押しの状態とかが面倒ですよね。
そのあたり、状態が変かしたときにイベントを発生するのが、BPiJoystick です。

using System;
using Moonmile.BrickPiNet;

namespace Sample
{
    class simplebot_joystick
    {
        BPiMotor motor1, motor2;
        BPiJoystick js;

        public void main()
        {
            BPi.Setup();
            BPi.AutoUpdate = true;
            this.motor1 = new BPiMotor() { Port = BrickPi.PORT_B, Enabled = true };
            this.motor2 = new BPiMotor() { Port = BrickPi.PORT_C, Enabled = true };

            js = new BPiJoystick();
            js.OnJoystickChanged += js_OnJoystickChanged;
            js.Setup();

            BPi.Timeout = 5000;
            this.Go();
        }

        void js_OnJoystickChanged(object sender, JoystickEventArgs e)
        {
            int ly = e.Joystick.LeftAxisY;
            int ry = e.Joystick.RightAxisY;
            Console.WriteLine("joystick {0} {1}", ly, ry);
	    int sp1 = ly/(32767/200);
	    int sp2 = ry/(32767/200);
	    move_bot( sp1, sp2 );

        }

        void move_bot(int sp1, int sp2)
        {
            this.motor1.Speed = sp1;
            this.motor2.Speed = sp2;
        }
        void Go()
        {
            var k = Console.ReadKey();
        }
    }
}

BPiJoystick を new して、OnJoystickChanged を登録すれば、ジョイスティックが変化したときだけイベントが発生します。現在のところ、ジョイスティックとボタンの状態変化が一緒になって飛んでくるので、ボタンだけ使いたいときに不便なのですが…まあ、ひとまず、これでジョイスティックを使ったロボットが簡単に作れます。

■さらに、もうひとつのモーターを使うために

これは次の課題ですが、BrickPi/LEGO mindstorms EV3 には、モーター用のポートが4つついています。現在、車輪用に2つ使っていますが、他にもモーターを使えばクレーン用とかに使えます。これはあとで実験してみましょう。他に接触センサーとかカラーセンサーもついているので、それも確認して実装していきます。

また、GPIO を直接操作することでサーボも動かせます。このあたりは、wiringPi http://wiringpi.com/ を利用して BrickPiNet から制御できるようにしていきます。

カテゴリー: RaspberryPi パーマリンク