IoT 통합: 윈도우 10 UWP 앱으로 아두이노 원격 제어하기
부품 및 소모품
| 부품명 | 수량 |
| 아두이노 우노 | 1 |
| 스파크펀 블루투스 모뎀 BlueSMiRF 실버 (골드 버전 사용) | 1 |
프로젝트 소개
참고: 하단의 코멘트 업데이트를 확인하세요.
윈도우 10 UWP 앱을 Remote-Wiring 라이브러리 기반으로 구축하면, Firmata가 실행 중인 아두이노 장치와 상호작용할 수 있습니다. 윈도우 리모트 아두이노 "Blinky" 예제와 유사하지만 기능이 추가된 앱을 개발했습니다. GPIO(입력/출력)와 아날로그 I/O를 모두 수행합니다. 기능적으로는 이전 블로그의 윈도우 8.1 버전과 동일하지만, UWP(유니버설 윈도우 플랫폼) 맥락에서 다룹니다. 대상 플랫폼은 윈도우 10 데스크톱, 윈도우 10 폰, 라즈베리파이 2(윈도우 10 IoT 실행)입니다. 라즈베리파이 2 대상은 아직 진행 중입니다.
상세 내용은 블로그 https://embedded101.com/... 참조. 윈도우 리모트 아두이노 "Blinky" 예제는 ms-iot.github.io에서 확인 가능.
유니버설 앱과 UWP 앱
윈도우 8.1에서 유니버설 앱(UA)은 인텔 데스크톱, ARM 서피스 RT, 윈도우 폰을 단일 솔루션으로 타겟팅할 수 있었습니다. 공통 코드(이벤트 핸들러, 연산, 데이터) 공유 가능했지만 XAML은 타겟별로 따로 작성해야 했습니다.
윈도우 10의 "하나의 윈도우" 패러다임 전환으로 XAML을 포함한 모든 코드를 모든 타겟에 공유할 수 있게 되었습니다. 동일한 프로젝트를 타겟별로 재컴파일만 하면 됩니다. 진정한 유니버설 앱을 구분하기 위해 UWP(Universal Windows Platform) 앱이라는 새 이름이 생겼습니다.
모든 윈도우 10 플랫폼이 UWP 앱을 지원하지만, 플랫폼별 확장 SDK가 있습니다(데스크톱, 모바일, IoT 등). UWP는 모든 기기에서 보장되는 핵심 API 계층을 제공합니다. 이 프로젝트에서는 UWP 템플릿을 사용하며 확장 SDK는 불필요합니다.
[1] 아두이노 장치와 블루투스 통신 설정
이미 윈도우 8.1에서 수행했다면 건너뛰세요.
아두이노와 윈도우 장치 간 Firmata 통신에는 USB 또는 블루투스 사용 가능. 윈도우 10은 둘 다 지원, 윈도우 8.1은 블루투스만 지원. 이 프로젝트에서는 블루투스 사용. 스파크펀 블루투스 메이트 골드(최대 100m 범위) 사용. 실버는 10m. 기본 핸드셰이킹 설정도 다름. 둘 다 TTL 레벨 UART 인터페이스로 블루투스 장치 설정과 아두이노 시리얼 포트 통신에 사용.
블루투스 장치 설정이 필요하면 스파크펀/프리트로닉스 USB-시리얼 장치로 데스크톱 시리얼 터미널에서 설정 가능. PIO6(실제론 PIO4) 핀을 하이로 연결하고 3번 토글하면 공장 초기화됩니다.
블루투스 메이트는 스파크펀 FTDI 베이직과 핀아웃이 같아 상호 교환 사용 가능. 단, TX/RX를 바꿔 끼워야 합니다. 이 구성으로 데스크톱에서 블루투스 장치 설정이나 시리얼 통신 가능.
기본 TTL UART 시리얼 설정
- 보드레이트: 115,200
- 8비트, 패리티 없음, 1 스톱 비트
- 하드웨어 흐름 제어 활성화 (실버는 None)
- 직렬 포트 프로파일(SPP): FireFly-WXYZ (WXYZ = BT MAC 주소 끝 4자리)
- 패스키: 1234
- 최대 8개 기기 페어링 저장 가능
장치 문서: rn-bluetooth-um.pdf
Firmata 설정은 57600 보드레이트라 변경 필요. 블루투스 장치 설정 대신 Firmata 쪽을 115200으로 수정하는 게 더 쉽습니다. 하드웨어 흐름 제어는 RTS-CTS 연결로 처리.
블루투스 모듈을 브레드보드에 장착해 아두이노와 연결할 수도 있지만, 프로토타입 쉴드에 소켓을 장착해 사용했습니다. 6핀 아두이노 쉴드 헤더를 블루투스 장치 TTL UART 핀에 납땜하고 핀을 90도 굽혀 수직 장착 가능하게 했습니다. BT 소켓으로 FTDI 베이직 모듈과 직접 연결해 설정 가능. PIO6(PIO4)에 와이어 납땜해 공장 초기화용으로 활용.
[2] Firmata 설정
이미 수행했다면 건너뛰세요.
주의: 아두이노 우노의 UART 핀 0, 1은 USB로 아두이노 IDE에서 프로그래밍할 때 사용 중이라 블루투스 모듈의 TTL UART 인터페이스와 연결 시 충돌합니다. 따라서 이 섹션에서 아두이노 프로그래밍 시 블루투스 장치는 분리해야 합니다.
- 아두이노 IDE에서 표준 Firmata 스케치 새로 만들기
- IDE에서 57600 검색해 115200으로 변경. 저장 후 업로드 (예: Firmata_115200)
[3] 유니버설 앱 Firmata 소프트웨어 스택 설정
윈도우 8.1 버전과 약간 다릅니다.
소프트웨어 스택은 3계층:
- Remote-Wiring API: 아두이노 하드웨어 상호작용을 위한 고수준 속성, 메서드, 이벤트 제공 (GPIO 등). Firmata 프로토콜로 Firmata 계층과 통신.
- Firmata: 시리얼 프로토콜로 하위 계층과 통신. 블루투스와 USB-시리얼 전송 계층을 Serial 계층에서 구현.
- Serial: 블루투스/USB-시리얼 전송 구현
소스 두 곳:
- windows-remote-arduino-samples
- remote-wiring
둘 다 윈도우 8.1/10 버전 포함. 두 번째 저장소의 윈도우 8.1 버전은 빌드 실패 경험. 첫 번째 저장소 사용 권장. Visual Studio 2015 RC 사용.
저장소 클론 및 빌드
git clone --recursive https://github.com/ms-iot/windows-remote-arduino-samples.git
디렉토리 구조:
windows-remote-arduino-samples
remote-wiring
Microsoft.Maker.win8_1
Microsoft.Maker.win10
source
win8_1
win10
윈도우 10용으로는 remote-wiring/Microsoft.Maker.win10과 source만 필요. 경로 너무 길면 ARM 빌드 오류 발생할 수 있어 드라이브 루트(예: c:\wras10)에 배치 권장.
Microsoft.Maker.win10 솔루션 파일 열기
- 타겟을 Win32로 설정하고 솔루션 빌드 (3계층 각각 빌드됨)
- ARM 구성으로도 동일하게 빌드. x64 머신이면 x64도 시도
[4] 하드웨어 LED UWP 앱 만들기
윈도우 8.1 경험자라면 단축 경로 가능.
초기 버전: 소프트웨어 버튼으로 하드웨어 LED 온/오프. LED는 GPIO 핀 5에 연결.
- C# 윈도우 블랭크 유니버설 앱을 솔루션에 추가 (윈도우 8.1이 아닌 UWP!). 프로젝트 하나만 생성됨 (XAML과 C# 코드가 데스크톱/모바일 공통, 컴파일만 다름).
- 패키지 매니페스트에서 Serial과 Bluetooth 기능 활성화 (텍스트 에디터로 열기)
- Firmata, RemoteWiring, Serial 참조 추가
기존 윈도우 8.1 프로젝트 있는 경우 단축 경로
- 기존 프로젝트의 Grid XAML 코드를 새 프로젝트 MainPage.xaml에 복사
- 테스트 단계로 바로 이동
직접 작성하는 경우
MainPage.xaml UI (Grid, 버튼 2개: On/Off), MainPage.cs 선언부 (BluetoothSerial, RemoteDevice, LED_PIN=5), 생성자에서 블루투스 연결 설정, OnConnectionEstablished 핸들러로 버튼 활성화 및 핀 모드 설정, 버튼 클릭 핸들러로 digitalWrite 제어.
[5] 유니버설 앱 배포 및 테스트
데스크톱 테스트
- 데스크톱 앱을 시작 프로젝트로 설정
- 타겟 x86, 로컬 머신으로 리빌드
- 아두이노 핀 5에 LED 연결 (GND, VCC, 적절한 저항 직렬)
- 아두이노 전원 켜고 블루투스 모듈과 데스크톱 페어링 (패스키 1234)
- 앱 실행, 블루투스 연결 허용, 기능 테스트, 디버깅
- x64 환경이면 동일하게 반복
- 데스크톱 블루투스 끄기
윈도우 10 폰 테스트 (개발 모드 구성 가정)
- 폰 블루투스 켜고 모듈과 페어링 (패스키 1234)
- 타겟 ARM, Device로 리빌드
- USB로 폰 연결해 앱 배포
라즈베리파이 2 테스트 (진행 중)
원격 디버거가 라즈베리파이 2(윈도우 10 IoT)에 이미 설치/활성화되어 있다고 가정. IP 주소 확인(Windows IoT Core Watcher 사용), 프로젝트 속성-디버그에서 원격 머신 타겟 설정, 리빌드 후 배포 테스트.
블루투스 연결 미해결: 라즈베리파이 2에서 블루투스 미지원 상태. 아이디어나 성공 사례 있으면 댓글 바랍니다.
[6] UI 다듬기
블루투스 연결/해제 버튼 추가, 프로그레스 링으로 연결 상태 표시, 버튼 크기/색상 개선 (4살 손녀 사용자 테스트로 검증!).
XAML Grid에 행 추가: Connect, Off, On, Disconnect 버튼, ProgressRing. OnConnectionEstablished에서 프로그레스 링 끄기. Connect/Disconnect 버튼 핸들러로 begin/end 호출. 버튼 상태 관리 로직 추가.
[7] 푸시버튼 입력 추가
아두이노 핀 6에 푸시버튼 GPIO 입력 연결, 상태를 UI 텍스트박스에 표시. 초기엔 폴링(250ms 간격)으로 읽고, 나중엔 DigitalPinChanged 이벤트 핸들러로 개선.
UI에 TextBox 추가, 핀 모드 INPUT 설정, DispatcherTimer로 폴링 구현, Pushbutton_Pressed()로 상태 변경 시 UI 업데이트. 하드웨어 디바운싱을 위해 스위치 양단에 소형 커패시터, 슈미트 트리거 추가 권장.
소프트웨어 시뮬레이션 LED(타원 모양) 추가로 버튼 상태 시각화. 이벤트 기반 방식으로 개선: Arduino_DigitalPinUpdated 이벤트 핸들러에서 UI 스레드로 마샬링해 처리 (Dispatcher.RunAsync 사용).
[8] 아날로그 입력 추가
포텐셔미터 레벨을 프로그레스 바로 표시. 아날로그 입력은 A0(핀 14).
UI에 ProgressBar 추가 (최대값 255). 핀 모드 ANALOG 설정. 폴링 방식: 타이머 틱에서 analogRead(ANALOG_PIN-14)로 읽어 프로그레스 바 업데이트. 이벤트 방식: Arduino_AnalogPinUpdated 핸들러로 비동기 UI 업데이트. 아날로그 핀 인덱스(0-5)와 실제 핀 번호(14-19) 구분 주의.
[9] PWM 출력 추가 (독자 연습)
- PWM 핀: 3, 5, 6, 9, 10, 11
- PWM 모드 설정:
arduino.pinMode(PWM_PIN, PinMode.PWM)
- PWM 레벨 설정:
arduino.analogWrite(byte, ushort) (0-255)
슬라이더로 LED 밝기 제어 구현은 독자 연습 과제로 남깁니다.
코드
WindowsRemoteArduino_Win10.zip (C#)
"Blinky" 확장 버전: 입력, 출력, 아날로그 입력, 향상된 UI
회로도
회로도 이미지는 원본 프로젝트 페이지에서 확인 가능.