Raspberry Pi 2 + Windows 10 IoT で Lチカチカ!

Raspberry Pi 2 を購入し、Windows IoT Core のインストールが成功した ので、次はなんか

センサーなんかをつないだりしてみたりしたいなぁと。

1.Raspberry Pi 2 用センサーキット購入

Raspberry Pi 2 用のセンサー詰め合わせみたいなのを購入してみた。2,000円程度とお値ごろ。

ハック ラズベリーパイ Raspberry Pi 電子工作入門キット。

sensors

届いた!

電子工作での、Hello World はどうやら Lチカとかいって、LEDをチカチカさせることらしい。

ということで、上記センサーキットの説明書的な位置づけのブログ、

Raspberry PiでLED点灯(Lチカ)してみよう。

を参照して、見た、、、が、いまひとつうまく動かない。。。

第9回「ラズベリーパイで電子工作!Lチカ…の前にLピカ!」 こちらのサイトが非常にわかりやすい。

root になったうえで、以下の例だと、GPIOの 25番ピン に接続して、リダイレクト先の gpio25/value に 1 を書き込むとLEDが点灯して、0を書き込むと消灯する。

# echo 25 > /sys/class/gpio/export
# cd /sys/class/gpio/gpio25
# echo out > direction
# echo 1 > value
# echo 0 > value

上記サイトで例に出ている抵抗と同じものが、今回のセンサーキットには含まれていなかったので、値が近いものを探して利用する。

抵抗値とカラーコードの一覧表

抵抗の帯の色で区別できるようになってるんですね。というか抵抗の意味もあまりわかりませんが。

ということで、Raspbian での動作確認は難なくクリア。いよいよ本命の Windows IoT で Lチカだ!

2. Windows IoT でLチカ!

2.1 Windows.Devices.Gpio

ということで、以下あたりにあるサンプルコードどおりにコーディングすればすぐチカチカするだろうと軽く考えていたところ、、、

Starter Pack for Windows 10 IoT Core on Raspberry Pi 2

Blinky Sample

まず、Windows.Devices.Gpio ネームスペースがどこにあるかわからない。。。

結構ググったり、トライアンドエラーのすえ、結局、参照設定から、Universal Windows 拡張、Windows IoT Extensions for UWP の中にあることが判明。

選択して、参照設定。

win_extension_form_uwp

これで、Windows.Devices.Gpio が利用可能となる。

win_extension_form_uwp02

2.2 GPIO ピンが無効!

つぎに、上記のサイトを参考に、コーディングして、動かしてみるも、チカチカしないどころか、

Exception thrown: 'System.Runtime.InteropServices.COMException' in WinIoTSample01.exe
WinRT information: Pin ' is not available. It is reserved by the system or in use for another function.

てな、例外が発生。Pin が Available じゃない?ぁ?システムで予約されている?

さっき、Rasbian からは、チカチカできてたじゃないですか。。。

うーん。なんか ピンのステータスを検査するメソッド的なものがあったので、全ピンの状態をデバッグに出力してみる!

for (int i = 0; i < gpio.PinCount; i++)
{
    GpioOpenStatus openStatus = new GpioOpenStatus();
    gpio.TryOpenPin(i, GpioSharingMode.Exclusive, out pin, out openStatus);
    Debug.WriteLine($"{i} is {openStatus.ToString()}");
}    

ほう。なんかわからんけど、3番ピンはだめだけど、4番ピンは良さそうだ。

0 is PinUnavailable
1 is PinUnavailable
2 is PinUnavailable
3 is PinUnavailable
4 is PinOpened
5 is PinOpened
6 is PinOpened
7 is PinUnavailable
8 is PinUnavailable
9 is PinUnavailable
10 is PinUnavailable
11 is PinUnavailable
12 is PinOpened
13 is PinOpened
14 is PinUnavailable
15 is PinUnavailable
16 is PinOpened
17 is PinOpened
18 is PinOpened
19 is PinOpened
20 is PinOpened
21 is PinOpened
22 is PinOpened
23 is PinOpened
24 is PinOpened
25 is PinOpened
26 is PinOpened
27 is PinOpened
28 is PinUnavailable
29 is PinUnavailable
30 is PinUnavailable
31 is PinUnavailable
32 is PinUnavailable
33 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\Microsoft.ApplicationInsights.PersistenceChannel.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
34 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.Threading.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
35 is PinOpened
36 is PinUnavailable
37 is PinUnavailable
38 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.Private.Uri.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
39 is PinUnavailable
40 is PinUnavailable
41 is PinUnavailable
42 is PinUnavailable
43 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.Diagnostics.Tracing.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
44 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.Linq.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
45 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.Globalization.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
46 is PinUnavailable
'WinIoTSample01.exe' (CoreCLR: CoreCLR_UWP_Domain): 'C:\Users\DefaultAccount\AppData\Local\DevelopmentFiles\89e222f8-bd1a-4cd5-b792-0d1321e00be7VS.Debug_ARM.piroto\System.IO.dll' が読み込まれました。シンボルの読み込みをスキップしました。モジュールは最適化されていて、デバッグ オプションの [マイ コードのみ] 設定が有効になっています。
47 is PinOpened
48 is PinUnavailable
49 is PinUnavailable
50 is PinUnavailable
51 is PinUnavailable
52 is PinUnavailable
53 is PinUnavailable

Raspberry Pi2 付属の GPIOカードで、4番ピンの位置を確認して、ケーブルを接続しなおす。

raspi_gpio_card

2.3 いざ Lチカ

まずは、PC上で起動して、GPIOがエラーになることを確認。OK

win_iot_gpio01

いよいよ、Raspberry Pi2 上の Windows IoT Core に Visual Studio 上からデプロイかまします。

“GPIO pin initialized correctly.” OK! OK!

led_off_uwp

LED は、消灯状態 OK! OK!

led_off

さて、おもむろに SWITCH ボタンをおして、、、画面上のステータスは、ONとなりました。さて、LEDは、、、

led_on_uwp

点灯しましたーーー。めでたしめでたし。

led_on

3.ソースコード

ここまでの、ソースコードは以下。

Windows 10 mobile も入手して、Universal Windows Platform も覚えたいと思ってたりしていて、以下の書籍のサンプルをコーディング中なので、基本的なMVVMのUIはそちらをお手本に、練習がてら作成。

実際に、Lチカさせるのに必要なコードは、MainPageContent クラスの、InitGpio() および、Switch() のみ。あとは、UI回りのためのコードです。

Models/MainPageContent.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinIoTSample01.Commons;
using Windows.Devices.Gpio;
using System.Diagnostics;

namespace WinIoTSample01.Models
{
    class MainPageContent : BindableBase
    {
        private static MainPageContent instance = new MainPageContent();
        public static MainPageContent Instance
        {
            get { return instance; }
        }

        private bool state;
        public bool State
        {
            get { return this.state; }
            set { this.SetProperty(ref this.state, value); }
        }
        private string gpioStatus;
        public string GpioStatus
        {
            get { return this.gpioStatus; }
            set { this.SetProperty(ref this.gpioStatus, value);  }
        }

        private const int LED_PIN = 4;
        private GpioPin pin = null;
        private MainPageContent()
        {
            InitGpio();
        }
        private void InitGpio()
        {
            this.State = false;

            var gpio = GpioController.GetDefault();
            if (gpio == null)
            {
                this.GpioStatus = "There is no GPIO contoroller ont this device.";
            }
            
            //for (int i = 0; i < gpio.PinCount; i++)
            //{
            //    GpioOpenStatus openStatus = new GpioOpenStatus();
            //    gpio.TryOpenPin(i, GpioSharingMode.Exclusive, out pin, out openStatus);
            //    Debug.WriteLine($"{i} is {openStatus.ToString()}");
            //}             

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

            //gpio.TryOpenPin(LED_PIN, GpioSharingMode.Exclusive, out pin, out openStatus);

            this.GpioStatus = "GPIO pin initialized correctly.";
        }

        public void Switch()
        {
            this.State = !this.State;

            GpioPinValue pinValue = ((this.State) ? GpioPinValue.High : GpioPinValue.Low);
            Debug.WriteLine($"Pin No:{pin.PinNumber}, Value:{pinValue}");

            pin.Write(pinValue);
        }
    }
}

Commons/BindableBase.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WinIoTSample01.Commons
{
    public class BindableBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual bool SetProperty(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(field, value))
            {
                return false;
            }
            field = value;
            this.OnPropertyChanged(propertyName);
            return true;
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ViewModels/MainPageViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinIoTSample01.Commons;
using WinIoTSample01.Models;

namespace WinIoTSample01.ViewModels
{
    public class MainPageViewModel : BindableBase, IDisposable
    {
        public MainPageViewModel()
        {
            this.Model.PropertyChanged += this.MainPageViewModel_PropertyChanged;
        }
        private void MainPageViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.OnPropertyChanged(e.PropertyName);
        }

        private MainPageContent Model { get; } = MainPageContent.Instance; 
        public string State
        {
            get {
                return (this.Model.State?"ON":"OFF");
            }
        }
        public string GpioStatus
        {
            get
            {
                return this.Model.GpioStatus;
            }
        }

        void IDisposable.Dispose()
        {
            throw new NotImplementedException();
        }
        public void Switch()
        {
            this.Model.Switch();
        }
    }
}

Views/MainPage.xaml

<Page
    x:Class="WinIoTSample01.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinIoTSample01.Views"
    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}">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0"  Text="{x:Bind ViewModel.State, Mode=OneWay}" HorizontalAlignment="Stretch" TextAlignment="Center"/>
        <TextBlock Grid.Row="1" Text="{x:Bind ViewModel.GpioStatus, Mode=OneWay}" HorizontalAlignment="Stretch" TextAlignment="Center"/>
        <Button Grid.Row="2" Content="SWITCH" Click="{x:Bind ViewModel.Switch}" HorizontalAlignment="Stretch"/>
    </Grid>
</Page>

Follow me!

コメントを残す

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