티스토리 뷰

반응형

Home Automation 구현을 완료하기 위해 잠시 Application Deploy 즉, RaspberryPi 부팅시 Main app으로 실행되게 하기 위해서 좀 알아보았는데 생각보다 손으로 해야할 것이 많다. 아마도 Visual Studio로 사용하는 최대 이점인 익숙한 IDE에서 App Packaging이 아직 적용이 안된 듯 하다. 이 부분은 주말을 통해서 진행하기로 하고, 오늘은 Interrupt에 의한 Gpio Control에 대해서 이야기하려 한다.

# Polling Vs Interrupt

너무너무 많이 들었던 개념적인 내용이다. 폴링은 주기적으로 계속 값이 변경됬는지 확인하는 것이고, Interrupt는 실제 변경되었을때 Trigger를 발생시켜 알수있게 하는 것인데, Resource 적인 측면에서는 Interrupt 방식을 사용하는 편이 낫다. IoT 환경에서는 24시간 365일 IoT 솔루션이 구동되어야 하는데 계속해서 먼가를 하고 있다면 심각한 낭비가 될 것이기 때문이다. 예를 들어보자, 지난번 Home Automation에서 핵심 시나리오는'온도가 27도 이상이면 LED를 키고 아니면 꺼라.' 였다. 이 시나리오를 위해서 Timer를 하나 생성하고 1초에 한번씩 온도 센서의 값을 읽어서 27도 이상인지, 그 아래인지 보고 Gpio 에 연결된 LED를 컨트롤 했었다. 지금은 솔루션 적인 요소들을 본다고 생각해서 이렇게 만들었지만 1초간 값을 읽는다면, 1분, 1시간, 24시간, 365일엔 어마어마한 일을 하고 있는 것이 될 것 같다. 단순히 값을 읽고 처리하는 일일 테지만 좀더 확장해보면 티끌모아 태산이 될 것 같다. 그래서 Interrupt 방식으로 지원하는 API가 있을것 같아서 찾아보니 Windows 10 IoT Core에서 사용할 수 있는 API가 있었다. 이를 이용해서 Interrupt에 세계로 한번 빠져 보자.

# 시나리오

스위치를 연결해서 한번 누르면 LED가 켜지고 다시 누르면 LED가 꺼지는 토글식 LED 제어를 해보자.

시나리오를 위와 같이 정의하고, 먼저 회로를 꾸며야 겠다. 필요한 부품은 LED, 저항, 스위치 가 되겠으며 이미 다른 사이트에서 회로도 구성에 대해 그림을 잘 설명해주고 있으니 참조하면 쉽게 따라할 수 있을 듯 하다.

참조 : http://www.rasplay.org/?p=3253

다만 위 참조 사이트와 대비해서 LED는 1개만 썻고 LED에 컨트롤 하는 출력용 GPIO PIN은 5번으로 했으며, 스위치의 입력 핀으로 GPIO PIN은 6번으로 했다. 물론 가지고 있던 확장핀 케이블을 사용했기에 실제 모습은 아래와 같다.

# 코드 작성

코드는 기본적으로 Gpio를 Initialize를 하는 부분과 Interrupt가 발생했을떼 처리되는 부로 나눌수 있는데, 먼저 Initialize 하는 부분을 보면 다음과 같다.

- GpioPin object를 LED 출력용과, ISR 입력용 두개를 생성해 놓았다.

//GPIO

        private const int LED_PIN = 5;

        private const int ISR_PIN = 6;

        private GpioPin pin;

        private GpioPinValue pinValue;

        private GpioPin isrPin;

        private GpioPinValue isrPinValue;

        private GpioPinEdge isrEdge;

- Gpio Init 코드에서는 출력용 Pin은 direction을 out으로 입력용은 in으로 설정해주었고, 실제 인터럽트가 즉 값의 변경이 있을때에 특정 함수가 불리도록 isrPin.ValueChanged += OnValueChanged 을 통해서 맵핑해준다. 뒤에서 좀더 설명하겠지만, 지금 gpio의 edge 모드를 설정하지 않고 있다. 다만 초기값을 1로 write 해주면서 출발했다.

private void InitGPIO()

{

            var gpio = GpioController.GetDefault();

            // Show an error if there is no GPIO controller

            if (gpio == null)

            {

                pin = null;

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

                return;

            }

            // LED PIN Initialize

            pin = gpio.OpenPin(LED_PIN);

            pinValue = GpioPinValue.High;

            pin.Write(pinValue);

            pin.SetDriveMode(GpioPinDriveMode.Output);

            // ISR PIN Initialize

            isrPin = GpioController.GetDefault().OpenPin(ISR_PIN);

            isrPinValue = GpioPinValue.High;

            isrPin.SetDriveMode(GpioPinDriveMode.Input);

            GpioStatus.Text = "GPIO pin initialized correctly.";

            isrPin.ValueChanged += OnValueChanged;

}

- 인터럽트가 발생했을때 하는일을 보면 아래 코드와 같다. MSDN의 문서만 보고 했을때, 설마 이렇게 간단하게 했는데 인터럽트가 설정됬을까 했는데, 디버깅 모드에서 브레이크 포인트 찍어보면 진짜 걸린다.

참조 :  https://msdn.microsoft.com/en-us/library/windows.devices.gpio.gpiopin.valuechanged.aspx

private void OnValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)

{

            Debug.WriteLine("Write : " + pinValue);

            if (sender == this.isrPin)

            {

                if( args.Edge == GpioPinEdge.FallingEdge)

                {

                    if (pin.Read() == GpioPinValue.High)

                    {

                        pinValue = GpioPinValue.Low;

                    }

                    else

                    {

                        pinValue = GpioPinValue.High;

                    }

                    Debug.WriteLine("Write : " + pinValue);

                    pin.Write(pinValue);

                }

            }

}

특이한 점은 edge 모드를 선택하지 않았는데, falling edge로 세팅이 되어있다. 아마도 interrupt를 위해 valueChanged에 함수를 매핑하면서 자동으로 선택되는 것 같다. 실제 내가 falling edge나 rising edge로 선택하는 방법이 있을지는 좀더 찾아봐야 겠다. 우선 위처럼 코드를 작성하면 스위치를 누르면 인터럽트가 발생되서 그 때 출력용 Gpio의 Pin의 Value를 읽어보고 high면 low로 low면 high로 write해주게 하였다. 이렇게 하니 1초마다 핀을 읽을필요도 없고 실시간 처리가 time slap 없이 잘 되는것 같다.

자 이제 결과를 직접 확인해보자!!

스위치를 누름에 따라 LED가 켜지고 커지는걸 볼 수 있다. API 측면에서 봤을때, windows 10 IoT Core도 생각을 많이 했구나 하는 걸 느낀다. 보통 user 단에서 폴링하도록 할 수 있지만 Platform 적인 요소로 Interrupt 기능을 지원한 점은 잘했다고 생각한다. 다만 일반적으로 Gpio의 Interrupt를 세팅하는 방법과는 조금 모호한 것이 있어서 이부분은 좀더 분석해 볼 예정이다. 또한 MSDN 잘 찾아보면 모르지만 유용한 기능이 더 많으니 생각이 나면 실천하고 분석해서 도움이 되는 글을 작성해야겠다. 우선 오늘은 여기까지!


반응형
댓글