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("masuda");

        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("count: {0}", 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 ? "OFF" : "ON";
            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 パーマリンク