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の制御と、ユーザーインタフェースを簡単に作成できる点は魅力的だと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です