Lego Mindstorm EV3はLego社から発売されている教育用ロボットです。
EV3の凄いところはBluetoothでPCとつないでDirectCommandというデータを流し込むことでリアルタイムにPCからコントロールできる点です。
もちろん、Windows 8.1であればWindowsストアアプリからBluetooth 4.0 LEで繋いで使うことができます。
しかし、このDirectCommandの内容はドキュメントとしては存在せず、日本代理店のアフレル社さんが配布しているKinectと連携させる教育用ドキュメントのサンプルソースにもモーター制御はありますが、センサーからの入力は使用していませんでした。
そして今日は「「Windows 8.1 ストアアプリ開発デバイス祭り~周辺機器とつなぐアプリを創ろう!!」開催」です。
もちろん、ハード絡みなのに事前に何も準備せずに参加しようとは思えなかったので、なんとかセンサーの値をとる方法がないか、いろいろネットで検索していた時にそれっぽいページをみつけることができました。
しかしなんとなく違和感があります。DirectCommandという文字列はでてきるのですが、byte配列を作ってそれをBluetoothで送信してという感じではなく、また、Windows 8.1といえどもBluetoothからの受信イベントは自分で実装するしかないのですが受信イベントもあるような感じでした。
そして「あれ、これcodeplexだ!」ということで、なんと「Lego.Ev3」という便利クラスライブラリがcodeplexにありました。しかもnuget配布もされていました。
Windowsデスクトップ、Windows Phone 8、Windows ストアアプリ (ただし8.1以降) と3つも公開されているというすばらしさ。
しかもNuGetに至っては、2013/11/06提供のほっかほかクラスライブラリ、ダウンロード数「13」というもぎたてクラスライブラリになります。
新規にWindows 8.1プロジェクトを作成したら、[ツール]-[ライブラリパッケージマネージャー]-[ソリューションのNuGetパッケージの管理]からLego.EV3を追加したら、もう今までとは別次元の簡単さでMindstorm EV3をコントロールするプログラムが作成できます。
使い方 step1
まずはEV3と接続するためのオブジェクトを作成します。
VB.NET
Private WithEvents Connecter As Lego.Ev3.Core.Brick
C#
private Lego.Ev3.Core.Brick Connecter;
使い方 step2
接続するときは接続方法を選択します。今回はBluetoothにします。
VB.NET
Me.Connecter = New Lego.Ev3.Core.Brick(New Lego.Ev3.WinRT.BluetoothCommunication) Await Me.Connecter.ConnectAsync()
C#
this.Connector.BrickChanged += Connecter_BrickChanged(); this.Connecter = new Lego.Ev3.Core.Brick(new Lego.Ev3.WinRT.BluetoothCommunication); await this.Connecter.ConnectAsync();
使い方 step3
データ受信したときはイベントが発生するので、そのパラメタからセンサー値を取得できます。
VB.NET
Private Sub Connecter_BrickChanged(sender As Object, e As Lego.Ev3.Core.BrickChangedEventArgs) Handles Connecter.BrickChanged If e.Ports(Lego.Ev3.Core.InputPort.One).Type <> Lego.Ev3.Core.DeviceType.Empty Then Debug.Print e.Ports(Lego.Ev3.Core.InputPort.One).SIValue End If End Sub
C#
private void Connecter_BrickChanged(object sender, Lego.Ev3.Core.BrickChangedEventArgs e) { if (e.Ports(Lego.Ev3.Core.InputPort.One).Type != Lego.Ev3.Core.DeviceType.Empty) { Debug.Print e.Ports(Lego.Ev3.Core.InputPort.One).SIValue } }
使い方 step4
モーターをまわすためにはDirectCommandをつかいます。 500msごとに指定した速度でモーターをまわすには次のようなコードになります。
VB.NET
For index As Integer = 0 To Me.Motors.Count - 1 If Me.Motors(index).Power = 0 Then Await Me.Connecter.DirectCommand.StopMotorAsync(Me.PowerPorts(index), True) Else Await Me.Connecter.DirectCommand.TurnMotorAtPowerForTimeAsync( Me.PowerPorts(index), Me.Motors(index).Power, 500, False) End If Next
C#
for (int index =0; index <= this.Motors.Count - 1; index++) { if (this.Motors(index).Power == 0) { await this.Connecter.DirectCommand.StopMotorAsync(this.PowerPorts(index), true); } else { await this.Connecter.DirectCommand.TurnMotorAtPowerForTimeAsync( this.PowerPorts(index), this.Motors(index).Power, 500, false); } }
まとめ
近日中に、Code Recipeでサンプルコード提供予定です。現在、VB.NET版のデバッグ中、それが終わればC#版作成して同時公開という感じですので、もう少々お待ちください。
でも、需要あるのかなぁ。