티스토리 뷰

반응형

Windows 10 IoT Core는 IoT 위해 만들어진 Platform 이다. IoT는 기존 제품과의 차별점으로 그 형태가 정해지지 않았다는 것인데 유저 시나리오에 따라서 어떤 형태로든지 만들수 있는 기본 Set이어야 한다. 여기서 등장하는 개념이 바로 Open Hardware와 Open source project 인데, RaspberryPi, Aduino, BBB 등과 같이 여러가지의 OS를 올려서 다양한 시나리오 베이스로 여타의 센서 등을 연동시킬 수 있어야 하고 Software 적으로 이를 지원해주어야 한다. 이를테면 하드웨어를 부착했지만 그 부착한 하드웨어를 잘 이용할수 있는 Framework 단, 말하자면 API 화 되어 쉽게 제어가능한 App 단위의 Service를 만들 수 있어야 할 것이다. 그런면에서 Open Hardware인 RaspberryPI와 이를 뒷바침하는 IoT Platform인 Windows 10 IoT Core를 가지고 다른 Hardware를 연동하는 것을 해보는것이 필요한데, 모든 시작은 Hello World에 있는 것처럼 IoT에서는 LED를 제어하는 것이 가장 기본이된다. 


#준비사항

1. 이전 글에서 이미 RaspberryPI와 Windows 10 IoT Core 개발 환경을 다 갖췃다고 가정한다.

2. LED 1개, 저항 330옴 1개, 브레드보드, 암수 커넥터, wifi 동글을 준비한다.

3. Host PC인 windows 10의 Visual studio와는 wifi로 RaspberryPI와 연결한다.(지원되는 wifi 동글을 꼭 확인한다.)


#사전 지식

- 옴의 법칙

IoT 개발자는 Software 뿐 아니라 Hardware의 기본적인 지식을 알고 있어야한다. LED의 경우, RaspberryPI 에서 지원하는 GPIO pin에 연결해서 High, Low 값을 기반으로 LED에 Signal을 줄 것이고, LED의 Spec에 따라 적정한 저항을 연결해서 전원을 공급한다.

단색 LED는 일반적으로 2개의 전극단자로 구성되어 있으며, 각 단자의 극성을 가지고 있다. 긴 단자는 애노드, 짧은 다자는 캐노드라고 부르는데 긴 단자에는 +전극을, 짧은 단자에는 -전극을 연결하면 LED가 켜지게 된다.

LED는 일반적으로 2V의 전원이 필요하므로 LED에 2V보다 더 높은 전압을 가하게 되면 빛의 밝기가 더 커지지만, 한계점에 이르러서 LED가 파손된다. 가지고 있는 LED가 2V와 10mA의 전류를 소비함으로 옴의 법칙으로 계산해보면 아래와 같다.

 V(전압) = I(전류의 세기) X R{저항)

3.3 V를 공급한다고 가정한다면 3.3 = 0.01 X R 이므로 R은 330 옴이 필요하다.


- RaspberryPI의 Pin 정보 및 연결방법

출처 : https://developer.microsoft.com/ko-kr/windows/iot/win10/GetStarted/rpi2/sdcard/stable/getstartedstep4


그러면 Windows 10 IoT Core에서 제공하는 API 기반으로 App을 작성해보자.


# C#으로 Main 코드 작성하기

UI 화면을 만드는 것은 나중에 설명하기로 하고 GPIO Pin을 Initialize 하고 Signal 보내주는 Main 코드를 먼저 보기로 하자. 

목표는 LED를 500ms 간격으로 깜빡이는 App이고, GPIO 5 번으로 LED에 Signal을 주기로 한다.

1. GPIO를 사용하기 위한 Wondows.Device.Gpio를 가져오기 한다.

2. LED를 5번핀에 연결할 것이므로 LED_PIN = 5로 정의한다.

3. 어플리케이션 선언에서 GPIO의 초가화를 처리할 수 있도록 한다.


- Initialize GPIO Pin

using Windows.Devices.Gpio;


namespace LED

{

public sealed pardtial class MainPage : Page

{

private const int LED_PIN = 5;

private GpioPin pin;

public MainPage()

{

this.InitializeComponent();

//GPIO 초기화 메서드 호출

InitGPIO();

//LED의 ON/OFF를 위한 loop 처리 호출

loop();

}


private void InitGPIO()

{

var gpio = GpioController.GetDefault();

if(gpio == null)

{

pin = null;

return;

}


// GPIO의 5번 핀을 연다.

pin = gpio.OpenPin(LED_PIN);

// 5번 핀을 High로 설정

pin.Write(GpioPinValue.High);

// 5번 핀을 출력으로 사용하도록 설정

pin.SetDriveMode(GpioPinDriveMode.Output);

}

}

}


- 1초 간격으로 LED를 점멸하는 루프

while (true)

{

pin.write(GpioPinValue.Low); // 5번 핀 LED 끄기

Thread.Sleep(1000);            // 1초간 슬립처리

pin.write(GpioPinValue.High); // 5번 핀 LED 켜기

Thread.Sleep(1000);             // 1초간 슬립처리

}


이렇게 구현해서 실행해보면 LED는 1초 간격으로 깜빡이지만 어플리케이션 쪽이 멈추어버리는 듯한 상태가 된다.

이것은 Thread.Sleep을 사용하는 바람에 1초간 스레드가 정지하게 되므로 클릭을 하든 무엇을 하든 반응이 없기 때문이다. Arduino 등에서는 어플리케이션 화면이 없으므로 단순히 Sleep 처리를 넣어도 문제가 없지만 Windows 에서는 GUI 어플리케이션을 만들 때 비동기 처리를 염두해두어야 한다.


- 비동기 처리시

using System.Threading.Tasks;


namespace LED

{

public sealed partial class MainPage : Page

{

private const int LED_PIN = 5;

private GpioPin pin;

private GpioPinValue pinValue;

public MainPage()

{

this.InitializeComponet();

InitGPIO();

loop();

}


private void InitGPIO()

{

var gpio = GpioController.GetDefault();

if (gpio == null)

{

pin = null;

return;

}


pin = gpio.OpenPin(LED_PIN);

pin.Write(GpioPinValue.High);

pin.SetDriveMode(GpioPinDriveMode.Output);

}


// 1초 간격으로 LED를 ON/OFF 하는 루프 처리

private async void loop()

{

while (true)

{

pin.Write(GpioPinValue.Low);

await Task.Delay(1000);

pin.Write(GpioPinValue.High);

await Task.Delay(1000);

}


}

}

}


- Timer 구현

GPIO pin initialize 전에 timer를 생성하고 interval을 500ms으로 세팅한다.(뒤에 전체 코드를 보면 확인가능하다.)

아래는 Timer가 500ms 마다 하는 일을 보여준다.

private void Timer_Tick(object sender, object e)

{

if (pinValue == GpioPinValue.High)

      {

          pinValue = GpioPinValue.Low;

          pin.Write(pinValue);

      }

      else

      {

          pinValue = GpioPinValue.High;

          pin.Write(pinValue);

      }

}


#UI 구현

IoT 어플리케이션은 UI를 동반할 수도 있고 그렇지 않을 수 있는 시나리오가 있다. 일반적으로 UI가 없는 App은 Headless app이라고 불리며 Windows 10 IoT core에서 불필요할시 command를 통해 process를 종료시킬수 있다. 이 부분은 차차 더 알아가기로 하고, Blinky app에서 UI는 빨간색 동그란 원이 500ms 마다 점멸되게 하는 것이다. Timer_Tick 함수가 500ms 마다 GPIO pin의 signal을 주게 구현하였으니 이곳에 빨간색원이 점멸되게 연결하는 코드를 넣으면 되고(Ellipse의 name으로 찾아가서 Fill을 넣어주면 된다.

그리고 기본적인 xaml 템플릿에 구미에 맞게 작업해주면 된다. 기본적인 설명은 Windows IoT Core 첫번째 글인 Hello World 샘플을 확인해보면 된다.



- MainPage.xaml

<Page

    x:Class="Blinky.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="using:Blinky"

    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" />

            <TextBlock x:Name="GpioStatus" Text="Waiting to initialize GPIO..." Margin="10,50,10,10" TextAlignment="Center" FontSize="26.667" />

        </StackPanel>

    </Grid>

</Page>



- 전체 C# 코드

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Runtime.InteropServices.WindowsRuntime;

using System.Threading.Tasks;

using Windows.Foundation;

using Windows.Foundation.Collections;

using Windows.Devices.Gpio;

using Windows.UI.Xaml;

using Windows.UI.Xaml.Controls;

using Windows.UI.Xaml.Controls.Primitives;

using Windows.UI.Xaml.Data;

using Windows.UI.Xaml.Input;

using Windows.UI.Xaml.Media;

using Windows.UI.Xaml.Navigation;


// 빈 페이지 항목 템플릿은 http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 에 문서화되어 있습니다.


namespace Blinky

{

    /// <summary>

    /// 자체적으로 사용하거나 프레임 내에서 탐색할 수 있는 빈 페이지입니다.

    /// </summary>

    public sealed partial class MainPage : Page

    {

        private GpioPin pin;

        private GpioPinValue pinValue;

        private DispatcherTimer timer;

        private const int LED_PIN = 5;

        private SolidColorBrush redBrush = new SolidColorBrush(Windows.UI.Colors.Red);

        private SolidColorBrush grayBrush = new SolidColorBrush(Windows.UI.Colors.LightGray);

        public MainPage()

        {

            this.InitializeComponent();

            timer = new DispatcherTimer();

            timer.Interval = TimeSpan.FromMilliseconds(500);

            timer.Tick += Timer_Tick;

            InitGPIO();

            if(pin != null)

            {

                timer.Start();

            }

            //loop();

        }


        private void InitGPIO()

        {

            var gpio = GpioController.GetDefault();

            if (gpio == null)

            {

                pin = null;

                GpioStatus.Text = "There is no GPIO controller on this device"; 

                return;

            }

            pin = gpio.OpenPin(LED_PIN);

            pin.Write(GpioPinValue.High);

            pin.SetDriveMode(GpioPinDriveMode.Output);

        }


        private async void loop()

        {

            while(true)

            {

                pin.Write(GpioPinValue.Low);

                await Task.Delay(1000);

                pin.Write(GpioPinValue.High);

                await Task.Delay(1000);

            }

        }


        private void Timer_Tick(object sender, object e)

        {

            if(pinValue == GpioPinValue.High)

            {

                pinValue = GpioPinValue.Low;

                pin.Write(pinValue);

                LED.Fill = redBrush;

            }

            else

            {

                pinValue = GpioPinValue.High;

                pin.Write(pinValue);

                LED.Fill = grayBrush;

            }

        }

    }

}



실제 결과물을 동영상으로 확인해보자.


지금까지 LED를 깜빡거리기 위해서 Hardware의 기본지식도 살펴보았고, GPIO 제어를 위한 Windows 10 IoT core의 C# 코드 등을 살펴봤다. Software 적으로 봤을때 아직 더 알아야할 것들이 많다. 간단한 Hardware지만 더 언급이 필요한 부분에 대해서는 새로운 글에서 다루도록 할 예정이다. 그럼 오늘은 여기서 끝~! 

반응형
댓글