Raspberry Pi 2 model B に Windows10 IoT Core をのせてLチカするまで

米Microsoftが4月29日より提供を開始した「Windows 10 IoT Core Insider Preview」をRaspberry Pi 2 model B にインストールしLEDを光らせてみるまでの手順です。

環境および物品

  • Raspberry Pi 2 Model B
  • 赤色LED
  • 1kΩ抵抗
  • ブレッドボードとジャンパコード2本
  • ホストコンピュータ:iMac
  • VM:Parallels Desktop 10.2

Windows10を用意する

Raspberry Pi用のWindows10 IoTをSDカードに書き込むために、 Windows10を用意します。今回手元にWindowsマシンがないためMacのバーチャルマシン上にWindows10をインストールします。今回はParallels Desktopを使用しましたが、他のVMでも可能だと思われます。

スクリーンショット 2015-05-06 16.29.22
ParallelsのWindows10インストール機能でインストールされるバージョンは若干古いバージョンになってしまう

Parallels DesktopにはWindows10を自動的にダウンロード、インストールする機能がありますが、これは失敗でした。インストールされるWindows10が若干古く、Windows 10 IoTをSDカードに書き込めません。Microsoftより最新のWindows10をダウンロードしてそのイメージを使用してインストールするようにしてください。
http://windows.microsoft.com/ja-jp/windows/preview-iso
スクリーンショット 2015-05-06 16.33.39
Parallelsの新規仮想マシンから、「DVD/イメージファイルからWindows/その他OSをインストール」を選択し、ダウンロードしたWindows10のイメージを選択し、OSをインストールします。
スクリーンショット 2015-05-06 16.35.27
 

Windows10IoTをSDカードに書き込む

インストールが完了したらMacにSDカードを挿入、Windows10に接続します。
Windows10IoTをダウンロードするにはサインインが必要です。
https://connect.microsoft.com/windowsembeddedIoT
下記URLよりWindows10IoTをダウンロードします。
https://connect.microsoft.com/windowsembeddedIoT/Downloads/
Windows_IoT_Core_RPI2_BUILD.zipをダウンロードしてください。
Windows10でコマンドプロンプトを管理者として実行します。次のコマンドを実行し、SDカードの位置を確認します。

diskpart
list disk
exit
C:\Windows\system32>diskpart
Microsoft DiskPart バージョン 10.0.10074
Copyright (C) 1999-2013 Microsoft Corporation.
コンピューター: WIN-HIAMN2HUDSC
DISKPART> list disk
  ディスク      状態           サイズ   空き   ダイナ GPT
  ###                                          ミック
  ------------  -------------  -------  -------  ---  ---
  ディスク 0    オンライン            64 GB      0 B
  ディスク 1    オンライン            14 GB  5120 KB
DISKPART> exit
DiskPart を終了しています...
C:\Windows\system32>

上記より、ディスク1がSDカードだと判ります。
ダウンロードしたZIPファイルを展開します。コマンドプロンプトで展開したフォルダ(flash.ffuがあるフォルダ)に移動します。そして次のコマンドを実行します。PhysicalDriveNのNに、先ほど判明したディスク番号を指定します。

dism.exe /Apply-Image /ImageFile:flash.ffu /ApplyDrive:\\.\PhysicalDrive1 /SkipPlatformCheck

これでSDカードにWindows10 IoTがインストールされます。
dism.exeでエラー:87 が表示される場合、Windows10のバージョンが古くないか確認してください。

>dism.exe /Apply-Image /ImageFile:flash.ffu /ApplyDrive:\\.\PhysicalDrive1 /SkipPlatformCheck
展開イメージのサービスと管理ツール
バージョン: 10.0.9926.0
エラー: 87
/applydrive オプションはこのコンテキストでは認識されません。
詳細については、ヘルプを参照してください。
DISM ログ ファイルは C:\Windows\Logs\DISM\dism.log にあります

Windows 10 IoTの起動

Windows 10 IoTを入れたSDカードをRaspberry Pi 2に差し込み、Raspberry Pi2にLANケーブルを接続した後、電源を接続して起動します。次のような画面になりIPアドレスが割り当てられていればOKです。
IMG_0773
 

接続の確認

Windows8.1にWindows_IoT_Core_RPI2_BUILD.zipに含まれるWindowsDeveloperProgramForIoT.msiをインストールします。起動すると接続されているWindows10IoTCoreとIPアドレスが表示されればOKです。
 
スクリーンショット 2015-05-06 17.42.13
 
右クリックからWeb Browser Hearを開くと、ステータスなどを表示することができます。
スクリーンショット 2015-05-06 17.48.42

開発環境の準備

開発環境にはVMにインストールしたWindows8.1を使用します。ますVisual Studio 2015 RC  Community Editonをインストールします。
https://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx
スクリーンショット 2015-05-06 17.29.35
インストールできたら起動できることを確認しておきましょう。起動時にライセンス確認のためユーザーIDを求められます。
スクリーンショット 2015-05-04 7.11.18

回路を用意する

それでは、Microsoftのサンプル通りにLEDを光らせてみましょう。サンプルはBlinky Sampleです。
サンプル通り、GPIOの5番(ピン29)と3.3V Pwr(ピン1)を使用し、抵抗とLEDを配置します。
Untitled Sketch 2_ブレッドボード
それでは、新しいプロジェクトを作成しましょう。「新しいプロジェクト…」をクリックします。
スクリーンショット 2015-05-04 5.21.52
 
Windows Universalより、Blank Appを選択してください。アプリケーション名は今回App1(デフォルト)としました。
スクリーンショット 2015-05-04 5.23.11
 
プロジェクトに参照を追加します。ソリューションエクスプローラーの参照から、参照の追加を開きます。
スクリーンショット 2015-05-04 5.26.12
 
Windows IoT Extension SDKにチェックを入れます。
スクリーンショット 2015-05-04 5.27.01
ユーザーインタフェースを作成するため、MainPage.xamlを編集します。

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Ellipse x:Name="LED" Fill="LightGray" Stroke="White" Width="100" Height="100" Margin="10"/>
            <TextBlock x:Name="DelayText" Text="500ms" Margin="10" TextAlignment="Center" FontSize="26.667" />
            <Slider x:Name="Delay" Width="200" Value="500" Maximum="1000" LargeChange="100" SmallChange="10" Margin="10" ValueChanged="Delay_ValueChanged" StepFrequency="10"/>
            <TextBlock x:Name="GpioStatus" Text="Waiting to initialize GPIO..." Margin="10,50,10,10" TextAlignment="Center" FontSize="26.667" />
        </StackPanel>
    </Grid>
</Page>

スクリーンショット 2015-05-06 17.58.54
MainPage.xaml.csを編集します。

using System;
using Windows.Devices.Gpio;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            InitializeComponent();
            this.timer = new DispatcherTimer();
            this.timer.Interval = TimeSpan.FromMilliseconds(500);
            this.timer.Tick += Timer_Tick;
            this.timer.Start();
            Unloaded += MainPage_Unloaded;
            InitGPIO();
        }
        /// <summary>
        /// GPIOを初期化します。
        /// </summary>
        private void InitGPIO()
        {
            var gpio = GpioController.GetDefault();
            // GPIOコントローラが存在しない場合はエラーを表示します
            if (gpio == null)
            {
                pin = null;
                GpioStatus.Text = "There is no GPIO controller on this device.";
                return;
            }
            // LED_PIN(=5)を開きます。
            pin = gpio.OpenPin(LED_PIN);
            // ピンが正しく初期化されなかった場合はエラーを表示します
            if (pin == null)
            {
                GpioStatus.Text = "There were problems initializing the GPIO pin.";
                return;
            }
            // LED_PIN(=5)をHighに設定
            pin.Write(GpioPinValue.High);
            // 出力に設定します
            pin.SetDriveMode(GpioPinDriveMode.Output);
            GpioStatus.Text = "GPIO pin initialized correctly.";
        }
        private void MainPage_Unloaded(object sender, object args)
        {
            // クリーンアップ
            pin.Dispose();
        }
        /// <summary>
        /// LEDを反転する
        /// </summary>
        private void FlipLED()
        {
            if (LEDStatus == 0)
            {
                LEDStatus = 1;
                if (pin != null)
                {
                    // LEDを点灯するために、PINを'low'に設定する
                    pin.Write(GpioPinValue.Low);
                }
                LED.Fill = redBrush;
            }
            else
            {
                LEDStatus = 0;
                if (pin != null)
                {
                    pin.Write(GpioPinValue.High);
                }
                LED.Fill = grayBrush;
            }
        }
        /// <summary>
        /// LEDを消灯します
        /// </summary>
        private void TurnOffLED()
        {
            if (LEDStatus == 1)
            {
                FlipLED();
            }
        }
        /// <summary>
        /// タイマーでLEDを点灯・消灯を繰り返します
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Timer_Tick(object sender, object e)
        {
            FlipLED();
        }
        /// <summary>
        /// 画面に表示します
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Delay_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            if (timer == null)
            {
                return;
            }
            if (e.NewValue == Delay.Minimum)
            {
                DelayText.Text = "Stopped";
                timer.Stop();
                TurnOffLED();
            }
            else
            {
                DelayText.Text = e.NewValue + "ms";
                timer.Interval = TimeSpan.FromMilliseconds(e.NewValue);
                timer.Start();
            }
        }
        private int LEDStatus = 0;
        private const int LED_PIN = 5;
        private GpioPin pin;
        private DispatcherTimer timer;
        private SolidColorBrush redBrush = new SolidColorBrush(Windows.UI.Colors.Red);
        private SolidColorBrush grayBrush = new SolidColorBrush(Windows.UI.Colors.LightGray);
    }
}

実行する
では実行してみましょう。ARMを選択し、デバイスからリモートコンピュータを選択します。
スクリーンショット 2015-05-04 7.28.33
アドレスにサーバ名のデフォルト値minwinpcを指定します。
認証モードはなしに設定します。
スクリーンショット 2015-05-04 7.28.56
 
実行した様子です。

 感想

使い慣れた環境と言語を使って、簡単にGPIOの制御と、ユーザーインタフェースを簡単に作成できる点は魅力的だと思います。

EPSON MOVERIO BT-200 で最先端のARを試す!

EPSON MOVERIO BT-200でVuforiaが使える様になったとの情報を得たので早速試してみました。
Vuforiaとはスマートフォンなどのチップで有名なQualcomm社によるAR プラットフォームです。
ビューフォリアが何かわからない方は、まずは、こちらをどうぞ。

どうですか?なかなか面白そうでしょう!本日はBT-200でVuforiaを動かしてみます!
まずは、MOVERIOで開発ができるようにしておかなければなりません。MOVERIO Developer Siteに行き、開発者登録しておきます。
次に、下記のページの情報を一通り目を通します。
https://tech.moverio.epson.biz/ja/bt-200/tools.html
開発者用システムソフトウェア適用手順書の手順に従い、BT-200に開発者用システムソフトウェアを導入します。
当方macなのですが、adbでBT-200が認識できていない様子。あきたじゅんさんのブログ
http://nextsphere-blog.blogspot.jp/2014/04/moverio-bt-200-adb.html
の手順通り設定すれば、macでBT-200が認識できる様になりました。ありがとうあきたさん!
次にQualcomm Vuforiaへ行きこちらも開発者登録を行います。
ログイン後、Downloads > Tools より、Vuforia Object Scannerをダウンロードします。ダウンロードしたvuforiaobjectscanner-4-0-103.zipを展開し、PDF「A4-ObjectScanningTarget.pdf」を印刷しておきます。vuforiaobjectscanner-4-0-103.apkをAndroid4.2以上の端末に転送し、インストールして起動します。とここでインストールに失敗。残念ながらBT-200はAndroid4.0と古めのバージョンなのでVuforia Object Scanner使えません。BT-200のカメラでスキャン出来たら格好良かったのですが。
さて、Vuforia Object Scannerは諦め、次にBT-200に対応しているVuforiaのbeta版を試してみましょう。まずはカメラのキャリブレーションから。
方法はhttps://developer.vuforia.com/library/articles/Training/Vuforia-Calibration-App に記載されている通りです。
まずベータ版のページからcalibration-4-1-3-public-beta.zipをダウンロードします。展開してapkをadbでBT-200にインストールします。
キャリブレーションターゲットhttps://developer.vuforia.com/sites/default/files/sample-apps/targets/stones.pdf をダウンロードし、印刷して壁に貼り付けます。
あとはBT-200を装着し、イントールしたCalibrationアプリを起動するとキャリブレーションが始まります。画面の指示に従いキャリブレーションを行います。
次にサンプルの実行方法です。まずVuforia SDK 4.1 Betaよりvuforia-sdk-eyewear-android-4-1-3-beta.zipとvuforia-samples-eyewear-android-4-1-3-beta.zipをダウンロード、展開します。
Android Studioを開き、 File – > Import Project … VuforiaサイトよりダウンロードしてきたサンプルDigitalEyewearVirtualButtons-4-1-3のフォルダを指定してインポートします。
展開したvuforia-sdk-eyewear-android-4-1-3-beta内にあるlibVuforia.soとVuforia.jaをサンプル内にコピーします。
それぞれ下記の様に配置します。
DigitalEyewearVirtualButtons-4-1-3

app
  + libs
    + Vuforia.jar
src
  + jniLibs
    + armeabi-v7a
      + libVuforia.so

 
Vuforia.jarを右クリックしAdd As Libraryを選択して表示されるダイアログでOKを押すと、build.gradelに下記が追加されます。手作業でbuild.gradleに追記しても同じです。

apply plugin: 'com.android.application'
android {
    compileSdkVersion 19
    buildToolsVersion "21.1.2"
    defaultConfig {
        applicationId "com.qualcomm.vuforia.samples.DigitalEyewearVirtualButtons"
        minSdkVersion 14
        targetSdkVersion 18
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}
dependencies {
    compile files('libs/Vuforia.jar')
}

これでビルド可能になります。早速実行してみると、ライセンス関係のエラーメッセジが。
Vuforia App key is missing. Please get a vaild key. by logging into your account at developer.vuforia.com and createing a new project.
Screenshot_2015-04-29-18-06-11
ライセンスが必要みたいですね。
https://developer.vuforia.com/library/articles/Training/Vuforia-License-Manager
を参考にライセンスを作成します。
https://developer.vuforia.com/target-manager
にアクセスし「Add License Key」をクリックします。
Application Nameを入力、SDKにDigital Eyewear[BETA]を選択、Next
チェックボックスにチェックを入れConfirmをクリック。
作成されたライセンスキー名をクリックすると、ライセンスキーが表示されます。これをサンプルアプリケーションのSampleApplicationSession.javaの345行目付近、setInitParametersにセットします。

Vuforia.setInitParameters(mActivity, mVuforiaFlags, " your_license_key ");

では実行してみましょう。おっとその前に、ターゲットとなる画像を印刷しておかなければなりません。
https://developer.vuforia.com/sites/default/files/sample-apps/targets/wood.pdf
を印刷しておきます。
では、BT-200でサンプルを実行してください。印刷した木の画像をBT-200でみると、やかんが表示されます。
Red、Blue、Yellow、Greenのボタンを押すと、ケトルの色がかわります!
この感動をお伝えするために、頑張って撮影しました。BT-200にWebカメラを固定し撮影しました。結構大変な撮影でしたが、うまく撮れたかとおもいます。実際には両眼で見る訳ですが、ちゃんと3D映像となっており、ケトルがそこにあるかのようにとても立体的に見えますよ。

いかがでしょうか。VuforiaのARライブラリを使えば、簡単にBT-200でARアプリが作れそうです。VuforiaはAndroidの他にもUnityにも対応しているので、手軽にARを使ったゲーム開発も出来そうです。
次回以降、サンプルソースを解析しながら、オリジナルアプリの作成に挑戦したいと思います。