Windows Remote Arduino を Arduino Uno/Nano で試す

ホーム – 組込みシステム開発技術展 | ESEC の開催中だし、de:code の準備で忙しいのか、誰もがスルーしたままの Windows Remote Arduino を試してみました。

image

Windows Remote Arduino が何をするものかを簡単に言うと、Arduino にサーバーを入れて、Bluetooth 経由などで Windows 8.1/10 や Windows Phone から GPIO などを操作しようという仕組みです。Arudino 側には Firmata というライブラリがあって、すでに色々な言語(Ruby とか Javascript/Node.js など)からアクセスできるようになっています。Arduino IDE では、「ファイル」→「スケッチの例」→「Firmata」→「StandardFirmata」で、コードが開けるのでビルドしてインストールができます。

部品を準備する

サイトを見れば、さっくりと動く?のかどうかはわかりませんが、まあ試行錯誤をすれば30分程で動くようにはなります。手持ちの Arduino と Bluetooth モジュールによってちょこちょことソースを書き換えないといけないのが、嵌りどころではあるのですが。

  • Visual Studio 2013/2015RC
    Microsoft.Maker のライブラリをビルドするに必要です。本ブログで解説するコードは Windows 8.1/VS2013 で動作確認しています。
  • Windows 側の Bluetooth ドングル
    ノート PC だったりすると内蔵なんですが、据え置き PC だとドングルを刺して。
  • Arduino Uno など。
    Firmata が動けば何でも。
  • Bluetooth モジュール
    Microsoft のサイトでは、SparkFun Bluetooth Mate Silver を使っていますが何でもいいです。私は手持ちの HC-05/06 で動作確認しています。BT2.0 のシリアル通信を使うので BLE の必要はありません。
  • ブレッドボード、ジャンパーワイヤー、LED など
    ここは電子工作的に。

Arduino に Firmata を焼く

「ファイル」→「スケッチの例」→「Firmata」→「StandardFirmata」を開いて、ビルドします。

image

この時、Arduino 側に差し込む Bluetooth のシリアル通信速度を設定し直します。デフォルトでは、57600 のように高速になっているので、HC-05 の初期値の 9600 に設定し直します。このあたりは、手持ちの Bluetooth モジュールに合わせます(私の AT コマンドが面倒で、そのまま 9600 で使っています)

Firmata.begin(9600);

Windows Remote Arduino のライブラリをダウンロードする

Windows IoT – SetupPCWRA の Option 1: Install the NuGet package を使えば、一発で Nuget で取れるようなことが書いてありますが…まだ、NuGet 上にはありません(Windows 8.1からも見つからない)。仕方がないので github からダウンロードしてビルドをします。

ライブラリは、以下からダウンロードできます。win8.1 と win10 の違いは、win8.1 が従来の Windows ストアと Phone のユニバーサルアプリで作ってあって、win10 は新しい Universal なプロジェクトで作ってあります。どちらもライブラリとし使うだけなので、UI は必要ないのですが、どうやらコードが C++/CX で書いているためなのか、8.1 では PC と Phone とのライブラリを別々に作らないとだめなようです。win10 のほうはひとつにまとまっています。

ms-iot/remote-wiring · GitHub
https://github.com/ms-iot/remote-wiring

これと、Lチカをさせるためのコードをダウンロードします。

ms-iot/windows-remote-arduino-samples · GitHub
https://github.com/ms-iot/windows-remote-arduino-samples

内部的に RFCOMM を使っているのでマニフェストファイルを手作業で修正する必要があります。remote-wiring のプロジェクトを参照させるために、remote-wiring フォルダにライブラリのプロジェクトを丸ごとコピーしておきます。

 

public MainPage()
{
    this.InitializeComponent();
    // bluetooth = new BluetoothSerial("RNBT-E072");
    bluetooth = new BluetoothSerial("HC-06");

    arduino = new RemoteDevice(bluetooth);
    bluetooth.ConnectionEstablished += OnConnectionEstablished;

    //these parameters don't matter for bluetooth
    bluetooth.begin(9600, SerialConfig.SERIAL_8N1);
}

 

ここでも、シリアル通信の速度「9600」と、Bluetooth モジュールの名前「HC-05」のように設定し直しておきます。あとは、x86 あたりでビルドをすれば ok です。x64 でビルドをすると XAML デザイナが動かないので、ひとまず x86 で動作確認するとよいでしょう。Any CPU で動かないのは C++/CX を使っているためです。

ちなみにLチカさせているところはこんな感じ。RemoteDevice クラスで取得した arduino オブジェクトを使って、digitalWrite してます。このあたりは Android の Scketch に似せているみたい。
個人的には .NET Micro に寄せたほうが良いのでは?と思うのですが、そこは OSS なので自己拡張で。

private void OnConnectionEstablished()
{
    //enable the buttons on the UI thread!
    var action = Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler( () => {
        OnButton.IsEnabled = true;
        OffButton.IsEnabled = true;
    }));
}

private void OnButton_Click( object sender, RoutedEventArgs e )
{
    //turn the LED connected to pin 5 ON
    arduino.digitalWrite( 5, PinState.HIGH );
}

private void OffButton_Click( object sender, RoutedEventArgs e )
{
    //turn the LED connected to pin 5 OFF
    arduino.digitalWrite( 5, PinState.LOW );
}

Bluetooth とペアリングする

Windows 8.1 のとき、BT2.0を接続する場合はペアリングが必要です。Windows 10 で BLE 接続する場合はペアリングなしでいけるらしいのですが、そこはまだ確認してません。

image

HC-05 のピンコードは「1234」です。

Arduino Uno で動かす

Bluetooth モジュールへの配線は MS のサイト で確認してもらうとして(RX/TXを接続するだけの簡単なものです)Uno 互換機で動かした結果がこんな感じです。

https://pbs.twimg.com/media/CFAp8IxUgAA88WX.jpg:large

デスクトップのストアアプリから Lチカができますね。まあ、Lチカだけやっても面白くないので、後でモーターかサーボモーターを動かしてみましょう。センサーの類も取得できるはずですね

Arduino Nano で動かす

USB 給電ではなくて、乾電池から給電させて Arduino Nano で動かします。これは、互換機なんで 300円前後のものです。Firmata + Windows の組み合わせが、手軽に?Windows Remote Android で実現ができます、ってことですね。

https://pbs.twimg.com/media/CFA0RLJUEAAlymU.jpg:large

ここでは、PC から扱っているわけですが、Windows Phone 経由にもできるだろうし、あるいは Ruby や Node.js を使っても同じインターフェースでできるということです。そのあたりは、クライアントアプリの切り替えが自由になって、便利な仕組みです。

カテゴリー: Arduino, Win IoT | Windows Remote Arduino を Arduino Uno/Nano で試す はコメントを受け付けていません

Win IoT に固定IPを指定する

ハンズオン用に RPi2 を持っていくのですが、現状の Win IoT では WiFi が使えません。MS 品川会場でホットスポットが使えないので、ローカルネットワークを組むことになりますが、DHCP でしか IP を割り振るとなるとルータが必要になって結構大変なので、固定 IP を指定するようにします。そうすると、ハブだけでいけます。インターネットには繋がりませんが。

GUI で設定できるような項目はないのですが、Win IoT に PowerShell でログインができるので、これを使います。

Win Iot on RPi にログインする

ログイン自体は以下のようにします。このあたり、powershell を知っていないと難しいんですが…知っていれば簡単なものなのでしょうか?

Enter-PsSession -ComputerName minwinpc -Credential minwinpc\Administrator

アドレスを確認する

PowerShell で IP アドレスの設定
https://www.upken.jp/kb/powershll-setipaddress.html

を参考にしながら設定していきます。上記のサイトでは IPv6 ですが、IPv4 に読み替えれば設定ができます。

Get-NetIPAddress で InterfaceIndex を確認します。大抵の場合、2 です。

Get-NetIPAddress

IPAddress         : 172.16.0.8
InterfaceIndex    : 2
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Dhcp
SuffixOrigin      : Dhcp
AddressState      : Preferred
ValidLifetime     : 23:03:26
PreferredLifetime : 23:03:26
SkipAsSource      : False
PolicyStore       : ActiveStore

固定IPを設定する

New-NetIPAddress で設定をします。PrefixOrigin が “Manual” になることでわかります。

New-NetIPAddress -InterfaceIndex 2 -IPAddress "172.16.0.99" -PrefixLength 24

IPAddress         : 172.16.0.99
InterfaceIndex    : 2
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Tentative
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : ActiveStore

IPAddress         : 172.16.0.99
InterfaceIndex    : 2
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Manual
SuffixOrigin      : Manual
AddressState      : Invalid
ValidLifetime     : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource      : False
PolicyStore       : PersistentStore

ネットマスクを 255.255.255.0 にする場合は 24 にします。

固定IP を変更する

Remove-NetIPAddress した後に New-NetIPAddress します。逆でも IP を指定すれば大丈夫みたいです。

DHCP に戻す

DHCP が割り振る IP に戻すには Set-NetIPInterface を使います。PrefixOrigin が “Dhcp” に戻ります。

Set-NetIPInterface -InterfaceIndex 2 -AddressFamily IPv4 -Dhcp Enabled

IPAddress         : 172.16.0.8
InterfaceIndex    : 2
InterfaceAlias    : Ethernet
AddressFamily     : IPv4
Type              : Unicast
PrefixLength      : 24
PrefixOrigin      : Dhcp
SuffixOrigin      : Dhcp
AddressState      : Preferred
ValidLifetime     : 23:59:47
PreferredLifetime : 23:59:47
SkipAsSource      : False
PolicyStore       : ActiveStore

コンピュータ名を変える

以下のように setcomputername で変更ができます。名前を確認したいときは hostname です。

setcomputername minwinpc1 

このあたりは、Linux と似ているので想像がつくんですけどね。Linux コマンドとの対応表がほしい。

カテゴリー: RaspberryPi, Win IoT | Win IoT に固定IPを指定する はコメントを受け付けていません

Win IoT on RPi で WebView を試す

基本、デバイスには豊富な UI は必要ない…のかもしれませんが、Win IoT Core には WebView というコントロールがあります。WebView 自体はストアアプリにもあるので、どれだけ表示されるかは IoT Core の実装次第になるわけですが、RPi2 の場合はそれなりに GPU が使える(描画の高速化も売りにしている)ので、手軽に画像やテキストを表示させるための WebView にも期待したいところです。たぶん、DOM 解析もできるから HTML をダウンロードしてきてパースしたり、逆にリソースに含めてある HTML を読みだして jQuery で制御するという技も可能なはずです。

実験用アプリ

WebView を貼り付けた簡単なアプリを作っておきます。私の RPi の場合、USB マウス/キーボードの両方とも効かないで、PC から URL を送る仕組みを作っておきます。先日作った SimpleWebServer を利用してアドレスを送れるようにします。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }

    SimpleWebServer _server;
    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        _server = new SimpleWebServer();
        _server.OnReceived += _server_OnReceived;
        _server.Start();
        // this.webView.Navigate(new Uri(textUrl.Text));
    }

    private async void _server_OnReceived(string data)
    {
        var url = data.Substring(1);    // 最初の "/" のみ消す
        // GET 受信
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
            () => {
                textUrl.Text = url;
                this.webView.Navigate(new Uri(url));

            });
        // 応答を送信
        _server.SendResponse("response: " + data);
    }
}

こんな風に送られてきたデータを、WebView.Navigate しているだけです。

いろいろ動かしてみる

ノーマルに自分の wordpress のサイトを表示させます。User Agenet がモバイルになっているらしく、スマートフォンの画面が表示されます。このあたりは、WebView のほうで指定が可能なはずです。

https://pbs.twimg.com/media/CEso-6tUEAAJYKr.jpg

重たそうな microsoft.com を表示させます。中央のダイアログが出てきたところを見ると、Javascript が動いていることがわかりますね。ちなみに、マウスが動かないので、これ以上進めませんが(苦笑)。

https://pbs.twimg.com/media/CEso-5SUsAEIDdM.jpg

どうせなので、Raspberrypi.org も表示させます。レイアウト崩れもないので、CSS がきちんと対応しているのでしょう。

https://pbs.twimg.com/media/CEsqnvNVAAAeonC.jpg:large

twitter.com も表示できます。キーボードが無反応なので、投稿とかはできませんが、タイムラインが表示されているところをみると、Twitter API がきちんと呼び出されているようです。Win IoT は SSL/TLS 対応なので https も通ります。

https://pbs.twimg.com/media/CEssUhTUUAAkmqq.jpg:large

ちょっと複雑なところで、SVGとjQueryで絵を描いているようなアニメーションを実装する方法 | 株式会社LIG にある SVG + jQuery のアニメーションを表示させます。えらく遅いですが、きれいに SVG と jQuery が動きます。これだけ動けば、たいていのサイトは表示できるのではないかと。

https://pbs.twimg.com/media/CEst9ZLUsAAwL8I.jpg:large

Youtube は HTML5 モードで動いているはずです。マウスでクリックできないので、動画が再生できるかどうかは不明なのですが(あちこちのサイトを探したけど、自動再生にはなりませんでした)、まあ、大丈夫なのでは。

https://pbs.twimg.com/media/CEswOxWUMAAQKkL.jpg:large

実験的に mpeg 動画を自サイトにアップして表示させると、うまく動きます。読み込みに少々時間がかかりますが、きれいに動きているのでこれで十分かと。音声が出なかったのは、4線プラグのほうで出ているのか、HDMI の音声出力に対応していないのかは不明です。

https://pbs.twimg.com/media/CEs0IdqUsAAjr6n.jpg:large

これらは、WebView コントロール内で表示させているのですが、XAML 内に適当なコントロール(メディアコントロールなど)を貼り付けても動くと思います。Flash とか ogg は無理そうなので、そのあたりは今後の OSS 系のライブラリに期待です。C++/CX が使えるので、デコード関係のものを持ってくれば動くんじゃないですかね。ちなみに、プロジェクトは Universal で作っているので、そのまま Windows Phone や PC でも動作が可能です。この実験プログラム自体も、一度 PC 上で動作確認してから RPi2 で動かしています。

カテゴリー: RaspberryPi, Win IoT | Win IoT on RPi で WebView を試す はコメントを受け付けていません

.NETラボ勉強会 5/23(土)に Windows 10 IoT Core on Raspberry Pi のハンズオンをやります

今月の 5/23 土曜日に MS 品川で Win IoT on RPi のハンズオンを急遽やります。単純に今月のネタが決まっていなかったのと、たまたま手元に RasPi 2 が 5台あるので思い付きでやる企画です。

//build/ で Win IoT on RPi が発表された記念と、de:code 直前の前夜祭気分で。

.NETラボ 勉強会 2015年5月 : .NET Lab
http://www.dotnetlab.net/dnn/2015/05/net%e3%83%a9%e3%83%9c-%e5%8b%89%e5%bc%b7%e4%bc%9a-2015%e5%b9%b45%e6%9c%88/

「ハンズオン」とは言え、特に学習用のプリントとかは用意しません。Raspberry Pi 2 に Windows IoT Core を入れて試してみたい方が対象ですね。手元に RPi2 がある方は持ってきて貰ってよいし、手元にない方は、増田が5台分持っていくので、それを使ってもらいます(人数が多い場合は、適当にグループ実習みたいな感じを想定しています)。

.NET ラボで側で用意するものは、

  • Raspberry Pi 2 を 5台 + micro SD カード(Win IoT インストール済み)
  • RasPi をつなぐためのローカルネットワーク(ハブ、ルータ、ケーブル等)
  • LED、サーボモータ、センサーの類を諸々
  • HDIM 付きの液晶モニタ(MSさんにお頼み中)
    時期的にVGAモニタしかないそうなので、HDMItoVGA 変換器を募集中

あとは増田の手元にあるロボットアーム、meArm、Arduino戦車あたりを持って行って、実際に動かせるところまで「楽しみ」ます。

https://pbs.twimg.com/media/CEdk0FiUkAABnwg.jpg:large https://pbs.twimg.com/media/CEV4sMOUsAAL6gL.jpg:large

各自用意して頂くのは

  • Visual Studio 2015 RC が入ったノート PC(Windows 8.1でも可)
  • 適宜 LANケーブル、電源タップ

あたりです。なくっても、まあ見てるだけで楽しいかもしれません。

スケジュール(予定)

1.Windows IoT Core の簡単な説明と Raspberry Pi 2 との組み合わせ
2.簡単なLチカの実習
3.HDMI 接続で液晶モニタへ表示する。
4.サーボモータ制御などを具体的に

な感じでお昼から、午後いっぱい程度で済ませる予定。そのあとは、適当なライトニングトークスと懇親会ですかね。人数は特に絞ってはいませんが、常連さんを含めていつも程度(20名ちょっと?)を想定しています。

申し込みはこちら

5月23日 .NETラボ勉強会 2015年5月(東京都)
http://kokucheese.com/event/index/294991/

 

カテゴリー: RaspberryPi, Win IoT | .NETラボ勉強会 5/23(土)に Windows 10 IoT Core on Raspberry Pi のハンズオンをやります はコメントを受け付けていません

Windows 10 を入れた直後に VS2015RC を入れて起動するとXAMLデザイナが動かないときの対処方法

素の Windows 10 に Visual Studio 2015 RC を入れた後に、Universal アプリを作って XAML デザイナを開こうとすると「Enable Developer Mode for Widnws 10 …」というエラーが出ます。対処方法は書いてあるのですが、英語なのと、実際「設定」→「Update & security」→「for Developers」を開こうとすると、画面が落ちて設定できないという現象に陥ります。仕方がないので、ローカルグループポリシーエディタを使います。

Enable developer mode dialog that is displayed in Visual Studio

Enable your device for development – Windows app development
https://msdn.microsoft.com/en-us/library/windows/apps/dn706236.aspx#GroupPolicy

ここに書いてある設定通り進めばよいのですが、設定の手順が英語なので項目が見つけづらい。ヘルプが日本語化されていないので、メモとして残しておきます。

  1. コマンドプロンプトで、gpedit.msc を実行
    エラーダイアログが出るが、気にしない。
  2. 「管理テンプレート」→「Windows コンポーネント」→「アプリパッケージの展開」をクリック
  3. 「信頼できるすべてのアプリのインストールを許可する」をダブルクリックして、「有効」にする。
  4. 「Allows developement of Windows Store apps and …」をダブルクリックして、「有効」にする(これだけ日本語化されていない)。

image

これで、XAML デザイナが正常に動くようになります。

Windows IoT の場合は、「10″ IoT Device …」でレイアウトしていけば ok です。RPi2 を使って HDMI 接続するときは普通に HD ディスプレイになるので、サイズが違うんですけどね。

image

カテゴリー: Windows 10 | Windows 10 を入れた直後に VS2015RC を入れて起動するとXAMLデザイナが動かないときの対処方法 はコメントを受け付けていません

Win IoT/RT で StreamSocketListener を利用して簡易WebServerを作る

Win IoT on RPi では、HttpListener がありません。と言いますか、Universal アプリ自体に、System.Net.HttpListener がないので、何か代替案を考えないといけません。ってことで、すっかり忘れていた、Windows.Networking.StreamSocketListener を使うわけですが、ちょっと嵌ったのでメモを残しておきます。

StreamSocketListener をストアアプリで使う

もともと、(確か)Windows 8.1 で導入されてストアプリでも HTTP プロトコル待ちのサーバーが作れたところからスタートです。以前、HttpListener と TcpListener の違いと Firewall と netsh の設定 | Moonmile Solutions Blog; なところで、HttpListener を駆使していたのですが(この記事を書いたのは Windows 8 の頃)、netsh やら firewall やらの設定が大変で、どうにかならないかと思っていたところなのですが、Windows 8.1 ではあっさり解決されてしまいました。

でもって、当時のブログやら調べ直していたところ、Stack Overflow などを見ると、なかなかうまくいかないひとが多いようです。サンプルコードてきには、

Windows 8 StreamSocket sample サンプル 言語: C#, C++, JavaScript Visual Studio 2013 用
https://code.msdn.microsoft.com/windowsapps/StreamSocket-Sample-8c573931

が唯一正しいような気がします。本家にあたりましょう。とはいえ、この本家のサンプルにも落ち度があって、StreamSocketListener を使って HTTP プロトコル待ちをしているところは書かれていないんですよね。どちらかというと TcpListener に近いところにあるので、TCP/IP のデータを生で扱うようなものです。が、通常の Web API 的に使おうと思うとそのままでは結構面倒なので、HTTP プロトコル風にできると便利ですね。

幸いにして、Win IoT のサンプルの中に

App2App WebServer
https://github.com/ms-iot/samples/tree/develop/App2App%20WebServer

が、HTTP プロトコルを簡易実装しているので抜き出してみました。
ちなみに、Windows.Networking.StreamSocketListener 自体は、WinRT 内のクラスなのでデスクトップアプリから直接使えません(間接的に WinRT を参照設定させることで利用できますが)。デスクトップアプリの場合は、従来通り、HttpListener か TcpListener を使うとよいでしょう。

簡易的な WebServer クラスを実装する

ざっと実装したものが以下です。GET コマンドにしか対応していませんが、Web API で REST を使う限りはこれで十分です。まあ、そのうち画像を送る程度には POST に対応したいところですが。

/// <summary>
/// 簡易WebServerクラス
/// 単純な GET コマンドのみ対応する
/// </summary>
public class SimpleWebServer
{
    StreamSocketListener listener;
    StreamSocket socket;
    public event Action<string> OnReceived;

    // public Windows.Networking.HostName LOCALHOST { get; set; }
    public int PORT { get; set; }
    public SimpleWebServer()
    {
        // this.LOCALHOST = NetworkInformation.GetHostNames().Where(n => n.Type == Windows.Networking.HostNameType.Ipv4).First();
        // this.LOCALHOST = new Windows.Networking.HostName(&quot;localhost&quot;);
        this.PORT = 8080;
    }

    /// <summary>
    /// 受付開始
    /// </summary>
    public async void Start()
    {
        listener = new StreamSocketListener();
        listener.ConnectionReceived += Listener_ConnectionReceived;
        // await listener.BindEndpointAsync(LOCALHOST, PORT.ToString());
        await listener.BindServiceNameAsync(PORT.ToString());
    }
    private async void Listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
    {
        socket = args.Socket;
        var dr = new DataReader(socket.InputStream);

        /// GET ヘッダを取り出し
        StringBuilder request = new StringBuilder();
        uint BufferSize = 1024;
        using (IInputStream input = socket.InputStream)
        {
            byte[] data = new byte[BufferSize];
            IBuffer buffer = data.AsBuffer();
            uint dataRead = BufferSize;
            while (dataRead == BufferSize)
            {
                await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
                request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
                dataRead = buffer.Length;
            }
        }
        // GET method を取り出し
        string requestMethod = request.ToString().Split('n')[0];
        string[] requestParts = requestMethod.Split(' ');
        var text = requestParts[1];

        /// GETコマンドの受信イベント
        if (this.OnReceived != null)
        {
            OnReceived(text);
        }
    }
    /// <summary>
    /// レスポンスを返す
    /// </summary>
    /// <param name=&quot;text&quot;></param>
    public async void SendResponse( string text )
    {
        if (socket == null) return;

        byte[] bodyArray = Encoding.UTF8.GetBytes(text);
        MemoryStream stream = new MemoryStream(bodyArray);
        string header = String.Format(&quot;HTTP/1.0 200 OKrn&quot; +
                            &quot;Content-Length: {0}rn&quot; +
                            &quot;Connection: closernrn&quot;,
                            stream.Length);
        var dw = new DataWriter(socket.OutputStream);
        dw.WriteString(header);
        dw.WriteString(text);
        await dw.StoreAsync();
    }
}

利用するときは、こんな感じです。クライアントから受信をしたときの OnReceived イベントで処理を行います。応答は、そのまま SendResponse メソッドを使います。このあたり、ストリームにしてもよいでしょう。

SimpleWebServer _server;
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    this.textIP.Text = NetworkPresenter.GetCurrentIpv4Address();

    _server = new SimpleWebServer();
    _server.OnReceived += _server_OnReceived;
    _server.Start();
}

private async void _server_OnReceived(string data)
{
    // GET 受信
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () => { textGet.Text = data; });
    // 応答を送信
    _server.SendResponse(&quot;response &quot; + data);
}

マニフェストを書き換える

現状 Visual Studio 2015 RC ではマニフェストファイル(Package.appxmanifest)の GUI が出て来ず、XML を直接編集することになります。
StreamSocketListener クラスで HTTP プロトコル待ちをさせたい場合は、internetClientServer(インターネット クライアント/サーバー)とprivateNetworkClientServer(プライベートネットワーク)を追加してください。これを書き忘れているブログが多くて、巷で「繋がらない」というのは、大方このせいです。

  <Capabilities>
    <Capability Name=&quot;internetClientServer&quot; />
    <Capability Name=&quot;privateNetworkClientServer&quot;/>
  </Capabilities>

これを設定しておくだけで、netsh やら firewall やらの設定をしなくて良くなります。多分、ストアアプリの範疇になるので、Windows 本体の TCP/IP のほうから切り離されている(WinRTで包まれている)のではないか、と想像します。

BindServiceNameAsync メソッドを使う

StreamSocketListener でサーバーを作るときに、どの URL とポートで待つのか?を指定するのですが、実際のところ、複数のアプリで同一ポートを共有できないので、実質ポートだけしてすれば ok です。また、BindEndpointAsync メソッドで、エンドポイントで指定される「ホスト名」を設定することができるのですが、あえて「localhost」のように同一マシン内に制限したり、「home-pc」のようにホスト名をわざわざ指定して外部アプリから使わせないようにしたりしない限りは、BindEndpointAsync メソッドを使う意味がありません。と言いますか、ここでホスト名を指定するのが結構面倒です。わざわざ名前を揃えるために IP アドレスを取ってきているものもあるのですが(stack overflow では大抵ここで嵌っています)、時に制限が必要ない場合はポート番号だけ指定する BindServiceNameAsync メソッドで十分です。このあたりは、先の MSDN のサンプルコードにも書いてあります。

IEから呼び出してみる

簡単な REST で呼び出せるようにしておくと、IE のようなブラウザからの操作が簡単にできます。

ブラウザで、アドレスを指定すると、

ストアアプリ側で受信できる

これは Windows 10 のユニバーサルアプリで作っていますが、ARM でコンパイルし直せばそのまま Windows IoT on RPi 上で動きます。このあたりは、UAP(Univesal Application Platform)の有利な点ですよね。タイトルが、for WiFi になっていますが、現在のところ Win IoT on RPi では WiFi のドングルは動作しません(リリース時には動作するとのこと)。現状では、有線 LAN オンリーですね。

という訳で、これで LAN 経由で Win IoT on RPi を制御する目途が立ったので、Raspberry Pi から GPIO で制御をする仕組みを入れていきます。ひとまず、先日買って Arduino で動かせるようになったロボットアームを動かす方を先にしようかなと。

カテゴリー: RaspberryPi, Win IoT, WinRT | Win IoT/RT で StreamSocketListener を利用して簡易WebServerを作る はコメントを受け付けていません

Windows 10 IoT Core on Raspberry Pi の情報先

Windows IoT のインストールが済んで、Lチカや “Hello World.” を表示し終わった後の情報先を羅列しておきます。どのように使うかは各人なのでしょうが、私の場合の例を挙げておくと、

  1. Raspberry Pi を XAML + デバイス機器として利用する
  2. Raspberry Pi の USB を活用する(Arduino だと USB の扱いは少々面倒なので)
  3. Raspberry Pi のカメラ機能を活用する

Windows IoT + Raspberry Pi に期待していたところが、主に2と3だったのですが、実際インストールしてみると1が結構使えそうです。2,3 は、Arduino でやろうとするとメモリの制約があったり、パフォーマンスに問題があったりして結構手間になるので、Rasbian(Linux)を使っていくところの延長です。まあ、その場合は、Linux 上で組んでも良い(OpenCV の組み合わせとかもあるし)のですが、そこは C# で組むということで Windows IoT を使います。

もうひとつは、HDMI 出力で XAML が簡単に使えるところです。これは意外だったのですが、Arduino でも Raspberry Pi でも小型液晶に出すパターンは多いのですが、大型液晶ディスプレイに出す例はあまりありません。RasPi の場合は Scratch でプログラミングというパターンもありますが、単純にデバイスの表示を画面に出すという点ではちょっと面倒です。面倒なので、CUI 的にターミナルで済ませてしまったりします。そういうところでは、GUI として XAML が使えるのは非常に便利です。確か、組み込み系 Windows としては GDI+ をサポートしない、と宣言されていたので、おそらく XAML で書いて出力させるのが Windows IoT 的には唯一の手段です。またスタート画面に示されているように、画像も出力ができます。

https://pbs.twimg.com/media/CD3M_BqVAAAKJ4c.jpg

以下は、Windows 10 IoT on RPi を構築するにあたっての情報先です。

情報先

フォーラム

  • Msdn forums – Windows IoT
    Microsoft サイト内のフォーラム。Windows IoT のインストールとか設定とかはこっちの方が適切でしょう。
  • Raspberry Pi • View forum – Windows 10 for IoT
    Raspberry Pi サイト内のフォーラム。Linux 系の RasPi を使ったことがあれば、こっちのほうがいいんでしょうが、Windows 特有の話は、MSDN フォーラムのほうがいいかも。

サンプル&映像

ひとまず、手元の RasPi 戦車が Win IoT でうごくようになったら、Hackster.io – The place where hardware gets created. に載せてみようかな、と計画中。

https://pbs.twimg.com/media/CESWgSZXIAEa_1F.jpg:large

カテゴリー: RaspberryPi, Win IoT | Windows 10 IoT Core on Raspberry Pi の情報先 はコメントを受け付けていません

Windows 10 IoT Core でアプリを起動する方法他

いくつか Windows 10 IoT Core on Rasberry Pi 2 のアプリを作っていてノウハウが溜まりつつあるので、ぼちぼちと OS 絡みをメモしておきます。

Win IoT は Visual Studio 2015 RC からデプロイできるので、お手軽で便利です。OS は Windows 10 TP でも、Windows 8.1 でも構いません。私は 8.1 のほうに Visual Studio 2015 RC を入れて動かしています。XAML のデザイナは動きませんが、Win IoT 自体にはあまり UI が必要がないので、まあそのままで。また XAML 自体は 8.1 のと互換がある(っぽい)ので、8.1 版のテンプレートを使って XAML をデザインして、IoT 版(Universal Windows版)にコピペしてもよいでしょう。

IoTCoreDefailtApp を立ち上げ直す

Win IoT on RPi2 を立ち上げると、最初はこの画面になるハズなのですが、なんとなく

IMG_0102

こんな風な、Windows ロゴ(だと思う)の画面で止まってしまうことがあります。暫く待っても前に進まないのでおかしいなーと思っていたのですが、上のウィンドウがフォアグランド(前面)になっていないだけっぽいです。

IMG_0103

Windows IoT Core Watcher からブラウザを選んで、起動しているプロセスをみています。左のメニューから「Apps」をクリックすると、今起動しているアプリが見れます。この中で、「IoTCoreDefailtApp」が、立ち上げ時に起動されるアプリになるので、「×」を押してプロセスを落とした後に、Installed apps でプロセスを選択して Start ボタンで再起動させます。

トップ画面では、有線 USB マウスが使えるようです。が、私の手元にある ELECOM の有線マウスは位置とびが激しくて使いものになりませんでした。

 

image

この画面でアプリをアップロードできるようですが、まあ、Visual Studio 2015 RC から直接アップロード(起動するだけ)したほうが手早いので、先行き使うということでしょう。

ちなみに、ここに出てくる謎な文字列は、ストアアプリではおなじみのアプリ ID で、パッケージマニフェストで変更が可能です。まだ、UI がテキストベース(Windows 8.1 でやっているから?)なのですが、ここの Identity タグの Name 属性を分かりやすくすれば ok ですね。これはストアにアップするときの ID になるので、自前でユニークになるように作ります(最初は自動で作ってくれる)。

image

パフォーマンスを見る

Win IoT ではバックグラウンドでプロセスを動かすこともできる(試してないが)ので、何かが暴走してしまって遅くなる?こともあるでしょう。ということで、プロセスをモニタの機能があります。「Processes」をクリックすれば、プロセスの一覧が見れて、対象のプロセスを落とすこともできます。ただし、単独のプロセスを立ち上げる機能はないので、変なことになったらリセットすればよいです。

image

デバイスマネージャを見る

Device Manager で見ることができます。PC のデバイスマネージャですね。ファイル保存して、メモ帳で見て、デバイスIDをコピーしたり、サービス GUID をチェックしたり、という使い方でしょう。

image

Miracat HID が入っているので、有線 USB マウスとか、有線 XBOX コントローラとかが動くのだと思う。Bluetooth ドングルとか、無線マウスとか動かないですかね?

ネットワークアドレスを見る

Networking をクリックすると、RasPi に割り当てられている IP アドレスが見れます。有線 LAN のほうしか有効でなくて、WiFI の USB ドングルを差しても無反応です。

image

見ると分かりますが、WiFi adapters や Profiles で接続先の SSID を選択できるようになっているので、無線LANの用意はされているようなのですが…現状は動かないんですかね?

次はモータードライブ L293D を動かす

ちょっと古めの L293D で、2個のモーターが動いたので後で公開しておきます。今は、L293N を調達するか、秋月電子で SN754410NE か TB6674PG を買うとよいでしょう。2個ワンセットで動かせと便利です。

https://pbs.twimg.com/media/CESWgSZXIAEa_1F.jpg:large

高機能なハット(シールド)を買ってもいいのですが、チップ1個だけでいけるので慣れるとこっちのほうが量産ができます。1個だけ作るならば、Adafruit DC & Stepper Motor HAT for Raspberry Pi – Mini Kit ID: 2348 – $22.50 : Adafruit Industries, Unique & fun DIY electronics and kitsAdafruit Motor/Stepper/Servo Shield for Arduino v2 Kit [v2.3] ID: 1438 – $19.95 : Adafruit Industries, Unique & fun DIY electronics and kits な感じで買えばいいのですが、多少高いのと、Windows.Devices.Gpio のピンが固定になっているので、動かない可能性があるので注意が必要です。

ちなみ上のモーターは、美工社の小学生学習キットのモーターです :) 低速ギア付きで2個 480円也。

カテゴリー: RaspberryPi, Win IoT | Windows 10 IoT Core でアプリを起動する方法他 はコメントを受け付けていません

Win IoT on RasPi と F# PCL の組み合わせでLチカ

どうせなので、Win 10 IoT を F# でやろうと思って、手始めに F# PCL と組み合わせてみます。C# の Windows Universal と、 F# の Portable Class Liberary との組み合わせです。

F# PCL を追加する

image

ポータブルクラスライブラリから、IoT のライブラリの参照はできないので、C# -> F# の呼び出ししかできませんが、適当なコールバック(乃至はイベント)を追加してやれば、C#/F# 間の行き来が可能です。MVVM の ViewModel を F# 側で作っておいて、C#/XAML に表示させるという方法でもよいでしょう。

image

F# のラインタイムは F# 4.0 ( FSharp.Core, 3.47.4.0)で動作確認しています。おそらく、その前のバージョンでも動くハズ。このあたりは、Xamarin.iOS/Android と同じになるので、PCL の範囲内で作っておけば動きます。

C# のコード

Lチカをさせているところで、F# を使ってカウントアップ。あまり意味はないけど、一応 F# のライブラリを呼び出しているということで。タクトスイッチの ValueChanged イベントはおまけです。Win IoT では、スイッチを押したときの ON/OFF をイベントで取得することができます。注意しないといけないのは、イベント自体は UI スレッドとは違うので、表示するときにはディスパッチを使います。このあたりはスレッドや非同期処理をしている方や、割り込み制御をしたことがある方にはおなじみなところです。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += (s, e) => main();
    }
    const int LED1_PIN = 13;
    const int LED2_PIN = 26;
    const int SW_PIN = 16;

    /// <summary>
    /// メインループ
    /// </summary>
    void main()
    {
        var gpio = GpioController.GetDefault();
        var LED1 = gpio.OpenPin(LED1_PIN);
        var LED2 = gpio.OpenPin(LED2_PIN);
        var SW = gpio.OpenPin(SW_PIN);

        LED1.SetDriveMode(GpioPinDriveMode.Output);
        LED2.SetDriveMode(GpioPinDriveMode.Output);
        SW.SetDriveMode(GpioPinDriveMode.Input);
        LED1.Write(GpioPinValue.Low);
        LED2.Write(GpioPinValue.Low);

        /// F# の PCL クラスを作成
        var fs = new PclFSharp.Sample();
        textName.Text = fs.Hello(&quot;masuda&quot;);

        int count = 0;
        new Task(async () => {

            while (true)
            {
                /// F# 内でカウントアップ
                count = fs.Add(count, 1);
                await textCount.Dispatcher.RunAsync(
                    Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    { textCount.Text = string.Format(&quot;count: {0}&quot;, count); });

                LED1.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED1.Write(GpioPinValue.Low);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.Low);
                await Task.Delay(500);
            }
        }).Start();

        // タクトスイッチの変更イベント
        SW.ValueChanged += async (s, e) =>
        {
            var text = SW.Read() == GpioPinValue.Low ? &quot;OFF&quot; : &quot;ON&quot;;
            await Dispatcher.RunAsync(
                Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                { textSw.Text = text; });
        };
    }
}

F# のコード

F# のコードがあまりチープなので実用性はないのですが、ひとまず動作確認まで。本当は、ここで LED の制御とかをやりたいのですが、IoT が参照できないので、制御自体は C# 側でやります。F# 側では、純粋にロジックを組めばよいかと。

 
type Sample() = 
    member this.X = "This is F# PCL"
    member this.Add(x,y) = x + y
    member this.Hello(name) = "Hello, " + name

 

動作させる

面倒なので、HDMI 出力させています。本来ならば、RasPi 付属の液晶ディスプレイとか使いたいところですよね。そのあたりはいずれ I2C 制御を試してから。

https://pbs.twimg.com/media/CEP_E6LUIAAwYUN.jpg

こんな風に LED 2個とタクトスイッチを扱います。USB 接続しているのは ELECOM の有線マウスなのだけど、うまく動かなかった。有線 USB のマウスだと動く場合もあるそうなので、まあ相性ということでしょう。折角買ったんですが、暫くお蔵入りです。

https://pbs.twimg.com/media/CEP_E3SUMAEQXQ1.jpg

というわけで、F# との組み合わせができることが確認できました。ということは、PCL 全般は大丈夫そうですね。また、ロジックのコードさえあれば、Windows デスクトップでテストをしてから、Win IoT のほうに持っていくということも可能です。

お次は RasPi 用のモーター制御用のハットを作って、実際に RasPi 戦車を作ってみようかなと。手元にあるハットはピンが異なってダメなので、自前で作ります。RasPi のモーター制御用のハットって意外と高いので。

カテゴリー: RaspberryPi, Win IoT | Win IoT on RasPi と F# PCL の組み合わせでLチカ はコメントを受け付けていません

Windows 10 IoT on RasPi で Lチカとモーター制御

無事、RasPi2 上で Hello world が出せたので、今度は Lチカをやってみます。Lチカ等のサンプルは、win-iot の github にあって、https://github.com/ms-iot/samples/tree/develop/Blinky/CS なところに C# のサンプルコードがあります。RasPi2 で Windows 10 IoT を使う利点としては、画面上に何か出すの非常に簡単(ストアアプリと同じように XAML を書けばよい)が挙げられます。いまのところ、HDMI 経由のサンプルしかないのですが、そのうちキャラクタ液晶に出力するサンプルも出るかもしれません。

Raspberry Pi 2 のピン

Windows IoT – RPi2 Pin Mappings にマッピングが表示されています。以下にそのまま引用します。

https://ms-iot.github.io/content/images/PinMappings/RP2_Pinout.png

ここの GPIO x のところにピンを差して Lチカをします。Arduino と違ってオスピンになっているので、ジャンパーピンのオス・メスを使わないといけないところなのですが、面倒なので HDD で使われているフラットケーブルを使います。こんな風に、フラットケーブルを差しておくと、普通のオス・オスのピンが使えるようになります(左右が逆になるので注意が必要ですが)。Raspberry Pi 電子工作レシピ に載っていた方法です。

https://pbs.twimg.com/media/CD7n7TXUIAAmzOP.jpg:large

ここでは、GPIO 13 と GPIO 26 に繋げて交互に Lチカをさせています。

Lチカのソースコード

さっくりとワンソースで書くとこんな感じになります。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        /// プログラム開始
        main();
    }

    const int LED1_PIN = 13;
    const int LED2_PIN = 26;

    /// <summary>
    /// メインループ
    /// </summary>
    void main()
    {
        var gpio = GpioController.GetDefault();
        var LED1 = gpio.OpenPin(LED1_PIN);
        var LED2 = gpio.OpenPin(LED2_PIN);

        LED1.SetDriveMode(GpioPinDriveMode.Output);
        LED2.SetDriveMode(GpioPinDriveMode.Output);
        LED1.Write(GpioPinValue.Low);
        LED2.Write(GpioPinValue.Low);

        new Task( async () => {
            while( true )
            {
                LED1.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED1.Write(GpioPinValue.Low);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.Low);
                await Task.Delay(500);
            }
        }).Start();
    }
}
  1. using Windows.Devices.Gpio; で名前空間を指定する。
  2. gpio.OpenPin で指定ピンをオープンする
  3. SetDriveMode で、出力(GpioPinDriveMode.Output)に設定する。
  4. 初期値は、消えている状態(GpioPinValue.Low)にしておく。
  5. Task クラスを使って、スレッドでぐるぐる廻します。間隔は Task.Delay が使えます。

C# を使うと、Task も使えるしラムダ式も使えるし簡単ですね。普通のストアアプリのように書くことができます(実は、.NET micro でも同じように書けます)。Visual Studio を使うとデバッグで一時停止させることもできるので、途中で値を確認することが可能です。

わざわざ、this.Loaded の時に Lチカを開始しているのは、今後画面アクセスをするときの開始タイミングをずらすためです。MainPage のコンストラクタで開始をしてしまうと、画面表示をしようとしてもまだ画面が作成させていない場合があるからですね。このあたりは、WPFやストアアプリと同じノウハウが使えます。

TA7267BP を使ってモーター制御をする

Lチカだけだとつまらないので、もう少しだけやっておきます。本当は、Raspberry Pi のモーター制御用のハット(Arduino のシールド)を使いたかったのですが、どうやら Windows 10 IoT の場合は、SPI 用のピンを GPIO のピンに差し換えできるような仕組みはないらしく、手元のハットが使えませんでした。仕方がないので、手元にあるモータードライバーで動作確認だけやっておきます。

image

配線はこんな感じで、モータードライバーを GPIO 5 と 6 を使って制御します。GPIO 5 が ON の時にはモーターが前進、GPIO 6 が ON のときはモーターが後進するようにプログラムを作ります。TA7267BP 自体は、ロジックの電源とモーターを流すための電源とを別々に取れるのですが、ここでは面倒なので、両方とも RasPi から取るようにしています。本来はコンデンサを挟まないといけないところですが、実験なのでこのままで。

モーター制御するコード

先に動かした LED のコードにモーター制御のコードを追加していきます。

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        /// プログラム開始
        main();
    }

    const int IN1_PIN = 5;
    const int IN2_PIN = 6;
    const int LED1_PIN = 13;
    const int LED2_PIN = 26;

    /// <summary>
    /// メインループ
    /// </summary>
    void main()
    {
        var gpio = GpioController.GetDefault();
        var LED1 = gpio.OpenPin(LED1_PIN);
        var LED2 = gpio.OpenPin(LED2_PIN);
        var IN1 = gpio.OpenPin(IN1_PIN);
        var IN2 = gpio.OpenPin(IN2_PIN);

        LED1.SetDriveMode(GpioPinDriveMode.Output);
        LED2.SetDriveMode(GpioPinDriveMode.Output);
        LED1.Write(GpioPinValue.Low);
        LED2.Write(GpioPinValue.Low);
        IN1.SetDriveMode(GpioPinDriveMode.Output);
        IN2.SetDriveMode(GpioPinDriveMode.Output);
        IN1.Write(GpioPinValue.Low);
        IN2.Write(GpioPinValue.Low);

        new Task( async () => {

            while( true )
            {
                LED1.Write(GpioPinValue.High);
                IN1.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED1.Write(GpioPinValue.Low);
                IN1.Write(GpioPinValue.Low);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.High);
                IN2.Write(GpioPinValue.High);
                await Task.Delay(500);
                LED2.Write(GpioPinValue.Low);
                IN2.Write(GpioPinValue.Low);
                await Task.Delay(500);
            }
        }).Start();
    }
}

やっていることはLチカと変わりませんね。モーターを制御する IN1/2 が両方ONにならないように注意すれば、モーターの正反転が簡単にできます。ここでは一つだけのモーターを使いましたが、2つ制御できれば車輪を使ったロボットが動かせるわけです。

https://pbs.twimg.com/media/CD7oBC3VAAMqBud.jpg:large

 

無線化をする

このままだと常に有線LANがつながった状態になるので、無線化をします。xbox のコントローラーを使うか、Bluetooth でスマートフォンから制御するか、は後から調べることになるのですが、ms-iot のサンプルを見る限り、既に xbox コントローラで動かしたサンプルがあるので、それを流用すると楽かもしれません。ということで、こっちのほうは後日。

カテゴリー: RaspberryPi, Windows 10 | 1件のコメント