Windows 10 IoT Coreでバックグラウンドアプリを作るメモ

Make a background app for Windows IoT Core
Raspberry Pi 2とWindows 10 IoT coreによる電子工作に挑戦しようとしているのですが、なかなか思うように行きません。まずひっかかったのは何もアプリを導入していないにもかかわらず、本体が再起動を繰り返すトラブル。調べてみたところ、主な原因としてSDカードとの相性に問題(200円で買ったワゴンのSDカードを使っていた)があるとのことでした。有志によって作成された互換性一覧によると、サンディスクやサムスンでさえも外れがあるみたいなので、結果、東芝製のカード(EXCERIA M301[輸入品])を買い直すことにしました。

ではここからが本題。Windows 10 IoT Coreによる開発は日本語による資料がほとんどないため、まずは基礎固めとして、ホビープログラミング入門という日経ソフトウェアのムックで紹介されていたRaspbian & Pythonによるスイッチプログラムの移植にチャレンジしてみました。

Windows 10 iot coreの導入方法は探せばすぐに見つかるので、ここでは割愛。まずは、スイッチと抵抗をブレッドボード経由で配線します。ブレッドボード中央の青い線の上に1KΩの抵抗がささっている点に気をつけてください。

続いてVisual Studio 2015のセットアップです。標準ではGUIのあるアプリしか作れませんが、こちらのページよりテンプレートを導入することで、GUIのないバックグラウンドアプリを作成できるようになります。インストールが終わると、Visual Studio 2015の新しいプロジェクトに「Background Application(IoT)」が追加されていると思います。

それではプログラムを組んでみましょう。バックグラウンドアプリはRunメソッドから呼び出されます。アプリを半永久的に起動させ続けるには、ここでGetDeferral()を呼び出す必要があります。今回はGPIO4に電気が入って来るかどうかの回路なので、4番ピンを入力モードにしています。あとはタイマーを起動させ、入力値が変更されたらVisual Studioのデバッグ出力に結果を表示させます。
startuptask.cs
// StartupTask.cs
using System;
using System.Diagnostics;
using Windows.System.Threading;
using Windows.ApplicationModel.Background;
using Windows.Devices.Gpio;

namespace Switch
{
    public sealed class StartupTask : IBackgroundTask
    {
        private BackgroundTaskDeferral deferral;

        private const int GPIO_PIN = 4;
        private GpioPin pin;

        private ThreadPoolTimer timer;
        private GpioPinValue gpv = GpioPinValue.Low;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // これがないとRunメソッドが終わるとアプリが終了してしまう
            // また、deferral.Complete(); で明示的に終了させることができる
            deferral = taskInstance.GetDeferral();

            // 4番ピンの入力を有効にする
            pin = GpioController.GetDefault().OpenPin(GPIO_PIN);
            pin.SetDriveMode(GpioPinDriveMode.Input);
            gpv = pin.Read();

            // 500msごとに判定する
            timer = ThreadPoolTimer.CreatePeriodicTimer(OnTickTimer, TimeSpan.FromMilliseconds(500));
        }

        private void OnTickTimer(ThreadPoolTimer timer)
        {
            var v = pin.Read();
            if (gpv != v) {
                Debug.WriteLine(v.ToString());
                gpv = v;
            }
        }
    }
}
続いてデバッガの設定です。対象のアーキテクチャを「ARM」にし、ターゲットは「リモートコンピューター」に。C#プロジェクトのプロパティの「Debug」に、対象のRaspberry Piが接続されているIPアドレスを入力します。アドレスは「Windows 10 IoT Core Dashboard」の「自分のデバイス」より確認できます。
初回起動時は追加コンポーネントなどの導入のため、やや時間がかかりますが、デバッガが起動すると、ブレッドボードのスイッチを押したり離したりするたびに、「出力」ウィンドウに結果が表示されます。
ちなみに、スイッチを押しているときはGNDピンへと電気が通じてGPIO4ピンには流れないため、GPIO4の結果は「Low」となり、離すとGPIO4に電気が流れるようになるため、結果が「High」となります。
2016/09/21