読者です 読者をやめる 読者になる 読者になる

銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

RPi2 で Windows IoT (2) エルーチカ をコンパイル時バインディングでやってみる

C# IoT Raspberry Pi 2

Raspberry Piのセットアップができたので早速アプリを作って動かしてみます。最初はべたなLED点滅から。

必要な電子工作の部品はこちら

  • LED
  • 270Ωの抵抗
  • ブレッドボード
  • オス-メス のジャンパーワイヤ2本

ちなみにUWPのアプリを動かして操作するにはディスプレイが必要になります*1

さて、サンプル用のアプリはすでにソースコード込みで公開されているのですが

ms-iot.github.io

github.com

これらのサンプルはロジックをPageのコードビハインドで書いているので、データバインディングで書きたいなあと思っていたら、id:okazuki せんせーからお言葉をいただきました。

コンパイル時について詳しくはこちら。

okazuki.hatenablog.com

というわけでサンプルコードを元にコンパイル時バインディングで書いてみました。

github.com

LEDBlinky が今回のプロジェクトです。

実行したイメージがこちら。

さて、回路ですが↑のMSのリンク先にピン配置と回路図があるのでそれを参考にするとわかりやすいかと思います。LEDは足の長い方(絵で足が折れている方)を3.3V OutのPin1側にします。これはもう一方のGPIO5 のPin29を0Vにしてマイナス側にすることでLEDを点灯させるためです。反対につけたり、抵抗をつけなかったりして過電流が流れるとLEDが壊れる恐れがあるのでご注意を。

コードですが、ViewModel側にほとんどの処理が書かれています。

IoTSamples/MainPageViewModel.cs at master · tanaka-takayoshi/IoTSamples · GitHub

GPIOの初期化処理はこれだけ。ピンを指定して初期値を書き込んで、出力モードを指定しておきます。

        private void InitGPIO()
        {
            var gpio = GpioController.GetDefault();

            // Show an error if there is no GPIO controller
            if (gpio == null)
            {
                pin = null;
                GpioStatus = "There is no GPIO controller on this device.";
                return;
            }

            pin = gpio.OpenPin(LED_PIN);
            pinValue = GpioPinValue.High;
            pin.Write(pinValue);
            pin.SetDriveMode(GpioPinDriveMode.Output);

            GpioStatus = "GPIO pin initialized correctly!";

        }

LEDを点滅させる処理はこちら。

        public void TurnOnLed()
        {
            if (pinValue == GpioPinValue.High)
            {
                pinValue = GpioPinValue.Low;
                pin.Write(pinValue);
                LedColor = redBrush;
            }
        }

        public void TurnOffLed()
        {
            if (pinValue == GpioPinValue.Low)
            {
                pinValue = GpioPinValue.High;
                pin.Write(pinValue);
                LedColor = grayBrush;
            }
        }

さきほども書いた通り、GPIOの出力をLow(0)にしたときにLEDが点灯します。 XAML側は x:Bind でバインディングを指定します。デフォルトが OneWayなので、ViewModel側で更新するプロパティはModeを指定するのに注意しましょう。またIntellesenseが効かないので、Typoにも注意です。

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Ellipse x:Name="LED" Fill="{x:Bind ViewModel.LedColor, Mode=OneWay}" Stroke="White" Width="100" Height="100" Margin="10"/>
            <CheckBox Checked="{x:Bind ViewModel.TurnOnLed}" Unchecked="{x:Bind ViewModel.TurnOffLed}" Content="LED On/Off" HorizontalAlignment="Center" FontSize="26.667" />
            <CheckBox Checked="{x:Bind ViewModel.StartTimer}" Unchecked="{x:Bind ViewModel.StopTimer}" Content="Switch Timer" HorizontalAlignment="Center" FontSize="26.667" />
            <TextBlock x:Name="DelayText" Text="500ms" Margin="10" TextAlignment="Center" FontSize="26.667" />
            <TextBlock x:Name="GpioStatus" Text="{x:Bind ViewModel.GpioStatus}" Margin="10,50,10,10" TextAlignment="Center" FontSize="26.667" />
        </StackPanel>
    </Grid>

これが実行したときの画面のイメージです。

f:id:tanaka733:20150923143737j:plain

実行するときのVSからのデバッグ方法もMSのページに書いていますが、たまに配置に失敗するときがあります。このときは、Raspberry Pi 2側で msvsmon プロセスが動いていないのが原因の可能性があります。起動時に自動でプロセスが起動するようになっているので、Raspberry Pi 2を再起動するのがよいでしょう。

> Get-Process msvsmon*
#プロセスが見つからないときは
> shutdown /r /t 0

*1:リモートデスクトップ接続はなさそう