[본 문서는 서울 IoT 센터에서 진행할 교육을 위해 작성된 한글문서입니다.]
[This document is currently written in Korean only for the purpose of being presented in the Seoul IoT tutorial.]
# 준비물
:::hw
Board|Eageleye 530s|1|
Board|Motion Sensor|1|HC-SR501
Board|LED Light|1|
Board|Resistor|1|330 ohm
:::
:::sw
SDK|Tizen Studio|
:::
### Eagleye 530s

### Infrared Motion Sensor (HC-SR501)

[HC-SR501 사용자 매뉴얼](https://www.mpja.com/download/31227sc.pdf)
[Arduino HC-SR501 Motion Sensor Tutorial (Personal Blog)](http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/arduino-hc-sr501-motion-sensor-tutorial/)
### LED Light & Resistor
* 5파이 LED 전구 (전압 2.2V / 전류 50mA)
* 공급전압 5V 시, 100~400Ω 저항 사용

***
# Hardware Setting
## Motion Sensor 세팅 변경
* 지연 시간: 약 5초 / Repeatable Trigger 모드
* 감지 거리: 약 3m

## Motion Sensor 연결

## LED Light & Resistor 연결

***
# General Purpose Input/Output (GPIO)
Binary input peripheral 상태 읽기/쓰기 가능한 Interface

## GPIO APIs
[Tizen Peripheral IO Native APIs - GPIO 가이드](https://developer.tizen.org/development/iot-preview/iot-apis/tizen-peripheral-io-native-api/gpio)
### Opening and Closing a Handle
**peripheral_gpio_open()**
특정 pin 넘버의 Peripheral GPIO 핸들을 열어줌
```c
int pin = 26; /* ARTIK 530 : GPIO8, Raspberry Pi 3 : GPIO26 */
peripheral_gpio_h gpio_h;
Int ret = peripheral_gpio_open(pin, &gpio_h);
```
**peripheral_gpio_close()**
더 이상 사용되지 않는 Peripheral GPIO 핸들을 닫아줌
```c
peripheral_gpio_close(gpio_h);
```
### Setting the Data Direction
**peripheral_gpio_set_direction()**
데이터 전송 방향을 설정함
* PERIPHERAL_GPIO_DIRECTION_IN : 데이터 읽기 모드
* PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH : 데이터 쓰기 모드, 초기값을 high(1)로 설정
* PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW : 데이터 쓰기 모드, 초기값을 low(0)로 설정
```c
peripheral_gpio_set_direction(gpio_h, PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
```
### Reading and Writing Binary Data
**peripheral_gpio_read()**
Peripheral 핸들로부터 binary 데이터 값을 읽어옴
```c
uint32_t value;
peripheral_gpio_read(gpio_h, &value);
```
**peripheral_gpio_write()**
Peripheral 핸들에 binary 데이터 값을 입력함
```c
uint32_t value = 1;
peripheral_gpio_write(gpio_h, value);
```
## GPIO Pin Number for Eagleeye 530s
보드에서의 Pin의 위치와 실제 Pin Map의 번호가 상이하여 코딩 시 아래 표의 Pin Param 참고

| Pin Oder | Pin Param |
|:-:|:-:|
| 11|28 |
| 13|29 |
| 16|130|
| 18|46 |
| 26|14 |
| 29|27 |
| 31|25 |
| 32|0 |
| 33|26 |
***
# Code Implementation
## 코드 준비
**1. Git Bash에서 rcc/smart-motion-light 코드 clone 받기**
```C
git clone https://git.tizen.org/cgit/apps/native/rcc -b smart-motion-light smart-motion-light
```

**2. Tizen Studio에서 motion-light-basic 프로젝트 불러오기**
* File > Import >> Tizen > TIzen Project >> Root directory > Browse

* clone 받은 smart-motion-light 폴더 아래 basic-init 폴더 선택

* Project Name: motion-light-basic / Profile: iot-headless / Version: 4.0 선택 (이미 열려있는 프로젝트와 프로젝트명이 동일하면 안 열리니 주의)

## Privilege 추가
Peripheral IO API 사용을 위해 peripheralio privilege 추가
* tizen-manifest.xml 파일 선택
* Privileges 탭 > 추가(+) 버튼 >

* Custom Privileges 추가
```
http://tizen.org/privilege/peripheralio
```

* 파일 저장 후 Source 탭에서 privilege 추가된 것을 재확인
> tizen-manifest.xml
```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<manifest xmlns="http://tizen.org/ns/packages" api-version="4.0" package="org.tizen.motionlight" version="1.0.0">
<profile name="iot-headless"/>
<service-application appid="org.tizen.motionlight" auto-restart="false" exec="motionlight" multiple="false" nodisplay="true" on-boot="false" taskmanage="false" type="capp">
<label>motionlight</label>
<icon>motion-light.png</icon>
</service-application>
<privileges>
<privilege>http://tizen.org/privilege/peripheralio</privilege>
</privileges>
</manifest>
```
## Resource 코드 내 GPIO 설정 확인
> src/resource/resource_infrared_motion_sensor.c
```c
#include <peripheral_io.h>
#include "log.h"
static peripheral_gpio_h g_sensor_h = NULL;
static int g_pin_num = -1;
int resource_read_infrared_motion_sensor(int pin_num, uint32_t *out_value)
{
int ret = PERIPHERAL_ERROR_NONE;
if (!g_sensor_h) {
peripheral_gpio_h temp = NULL;
ret = peripheral_gpio_open(pin_num, &temp);
retv_if(ret, -1);
ret = peripheral_gpio_set_direction(temp, PERIPHERAL_GPIO_DIRECTION_IN);
if (ret) {
peripheral_gpio_close(temp);
_E("peripheral_gpio_set_direction failed.");
return -1;
}
g_sensor_h = temp;
g_pin_num = pin_num;
}
if (g_pin_num != pin_num) {
_E("Invalid pin number.");
return -1;
}
ret = peripheral_gpio_read(g_sensor_h, out_value);
retv_if(ret < 0, -1);
return 0;
}
```
```c
void resource_close_infrared_motion_sensor(void)
{
if (!g_sensor_h) return;
_I("Infrared Motion Sensor is finishing...");
peripheral_gpio_close(g_sensor_h);
g_sensor_h = NULL;
g_pin_num = -1;
}
```
> src/resource/resource_led.c
```c
#include <peripheral_io.h>
#include "log.h"
static peripheral_gpio_h g_sensor_h = NULL;
static int g_pin_num = -1;
int resource_write_led(int pin_num, int write_value)
{
int ret = PERIPHERAL_ERROR_NONE;
if (!g_sensor_h) {
peripheral_gpio_h temp = NULL;
ret = peripheral_gpio_open(pin_num, &temp);
retv_if(ret, -1);
ret = peripheral_gpio_set_direction(temp, PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
if (ret) {
peripheral_gpio_close(temp);
_E("peripheral_gpio_set_direction failed.");
return -1;
}
g_sensor_h = temp;
g_pin_num = pin_num;
}
if (g_pin_num != pin_num) {
_E("Invalid pin number.");
return -1;
}
ret = peripheral_gpio_write(g_sensor_h, write_value);
retv_if(ret < 0, -1);
_I("LED Value : %s", write_value ? "ON":"OFF");
return 0;
}
```
```c
void resource_close_led(void)
{
if (!g_sensor_h) return;
_I("LED is finishing...");
peripheral_gpio_close(g_sensor_h);
g_sensor_h = NULL;
g_pin_num = -1;
}
```
## Motion Sensor 값 읽어오기
46번 핀((Pin Order #18)에 접근하여 Motion Sensor 값을 읽어옴
> src/controller.c
```c
#include <unistd.h>
#include <Ecore.h>
#include <tizen.h>
#include <service_app.h>
#include "log.h"
#include "resource/resource_infrared_motion_sensor.h"
#include "resource/resource_led.h"
static Eina_Bool __read_motion_write_led(void *data)
{
uint32_t value = 0;
int ret = -1;
/* Gets value from motion sensor */
// TODO: Read data from motion sensor
ret = resource_read_infrared_motion_sensor(46, &value);
if (ret != 0) _E("Cannot read sensor value");
_D("Detected motion value is: %d", value);
/* Sends value to LED light */
// TODO: Send data to LED sensor
return ECORE_CALLBACK_RENEW;
}
```
## LED 값 변경하기
130번 핀((Pin Order #16)에 접근하여 LED Light 값을 변경함
> src/controller.c
```c
static Eina_Bool __read_motion_write_led(void *data)
{
uint32_t value = 0;
int ret = -1;
/* Gets value from motion sensor */
// TODO: Read data from motion sensor
ret = resource_read_infrared_motion_sensor(46, &value);
if (ret != 0) _E("Cannot read sensor value");
_D("Detected motion value is: %d", value);
/* Sends value to LED light */
// TODO: Send data to LED sensor
resource_write_led(130, value);
return ECORE_CALLBACK_RENEW;
}
```
## 타이머 설정하기 (app_create)
특정 주기(1.0f)마다 모션 센서 값을 불러오고 LED 값을 설정해주는 __read_motion_write_led 함수 호출
> src/controller.c
```c
typedef struct app_data_s {
Ecore_Timer *getter_timer;
} app_data;
static bool service_app_create(void *data)
{
app_data *ad = data;
/**
* Creates a timer to call the given function in the given period of time.
*/
// TODO: Add ecore timer which calls __read_motion_write_led() every 1 second
ad->getter_timer = ecore_timer_add(1.0f, __read_motion_write_led, ad);
if (!ad->getter_timer) {
_E("Failed to add infrared motion getter timer");
return false;
}
return true;
}
```
## 리소스 정리하기 (app_terminate)
App 종료 시 App에서 사용하던 리소스 정리
> src/controller.c
```c
static void service_app_terminate(void *data)
{
app_data *ad = (app_data *)data;
/**
* Deletes all the resources and timers created for this app.
*/
// TODO: Delete timer
if (ad->getter_timer)
ecore_timer_del(ad->getter_timer);
// TODO: Close infrared motion & led resources
resource_close_infrared_motion_sensor();
resource_close_led();
// TODO: Free data resource
free(ad);
}
```
## Tizen App 실행
Project Explorer 내 프로젝트 우클릭 > Run As > Tizen Native App

***
# 최종 확인
Motion sensor 값에 따른 LED Light 변화 확인

Notice
Are you sure to delete this post?
Smart Motion Light Basic
1
2
|
Last modified on August 22, 2018
Craft info. | |
Maker |
![]() |
Status | In Progress |
Period | ~ |
About This Craft | |
Seoul IoT Presentation | |
Making Note