* 워크숍 7일차 전체 동영상

 

 

* 실습 준비 : 조도센서로 조도 측정하기 [링크]

 

 

* 스케쥴

 

 

* 타이젠 스튜디오에 로그가 나오지 않는 문제 : [링크]

 

 

* SDTA7D SPI 업데이트 하기 : [링크]

 

 

* 누비슨 관련 공지사항

- 계정 : [슬랙채널]

- 관련내용 : [소스가 포함된 링크]

 

 

* thingpark Cloud with Tizen

- 발표자료

Thingspark IoT Cloud 연동-20190907.pdf
2.25MB

- 소스 : [링크]

 

 

 

수정내역 : '19. 8. 16(금) 내용 추가

 

'19년 8~9월, 타이젠 워크숍 및 해커톤을 개최할 예정입니다.

 

* 해커톤
- 주제 : 사람들의 간절한 문제를 해결하는 탑 메이커
- 모집기간 : ‘19. 7. 16(화) ~ 8. 16(금)
- 하드웨어 해커톤 일정 : 1박 2일, 9. 21(토) ~ 22(일)
- 참가규모 : 30팀 이내(120명 내외, 팀 당 4명 내외 구성)
- 참가요건 : H/W개발자, S/W개발자 각 1명 이상(필수)으로 구성된 4인 내외의 팀
   ※ 가능 : SW 개발자 1명 + HW개발자 1명 + 기획자
   ※ 불가능 : 기획자 2명 + 디자이너 2명
- 필수기술 : 타이젠
   ※ 타이젠은 음성이나 비전 등 고성능을 요구하는 제품에 적합한 OS.
- 지원내용
   ① 1개 팀당 개발지원금 30만원 제공
      (사후 증빙서류 제출후 입금해줌. 신용카드 매출전표 & 증빙사진이 필요함. 
   ② 토일 개발 워크숍 [4주 내외, 동영상강의 별도 제공]
   ③ 별도 주중 워크숍 [7월~8월사이 별도의 특별 워크숍도 진행예정, 고급과정 중심]

 

* 사전 기술워크숍(해커톤 참여자 대상, 외부참여 일부허용)

 

* 시상혜택

지원 내용

시상 내역

비 고

최우수상

상금 2,000천원 (1)

하드웨어 스타트업 엑셀러레이팅 프로그램 T-Stars 참가기회부여

기술창업비자 필수점수 부여 (법무부)

- 3D모델링, CNC/3D 프린팅 등 시작품 제작지원

서울시 창업허브 입주신청시 가점부여

심사위원

(60%)

동료 평가

(40%)

우수상

상금 1,000천원 (각 1팀, 총 2팀)

기술창업비자 필수점수 부여 (법무부)

- 3D모델링, CNC/3D 프린팅 등 시작품 제작지원

서울시 창업허브 입주신청시 가점부여

심사위원

(60%)

동료 평가

(40%)

장려상

상금 500천원 (각 1팀, 총 2팀)

- 3D모델링, CNC/3D 프린팅 등 시작품 제작지원

서울시 창업허브 입주신청시 가점부여

심사위원

(60%)

동료 평가

(40%)

우수 리더상

∘ 2

삼성 갤럭시 워치 각 1

 

동료 평가

(100%)

기타 사항

※ 외국인 개발자 특전 사항 (최우수상우수상 수상시)

기술창업비자 필수점수 부여 (법무부)

 

 

자세한 내용을 확인하고 싶으시거나 해커톤 참가 신청을 하시려면,
여기를 참고해주세요~

 

(2019) '사람들의 간절한 문제를 해결하는 탑 메이커'를 주제로한 서울 하드웨어 해커톤 | Seoul Hardware Hackathon, Top Maker

(2019) '사람들의 간절한 문제를 해결하는 탑 메이커'를 주제로한 서울 하드웨어 해커톤 | Seoul Hardware Hackathon, Top Maker ※ 서울 하드웨어 해커톤은 개발자간 네트워킹을 중요시합니다. 서로 많이들 알아..

www.topmaker.kr

 

추가 : 신청이 마감되었습니다.

* 본 게시물은 '19. 7. 29(월)에 추가로 수정되었습니다.

 

G Camp에서 타이젠 워크숍이 개최될 예정입니다.
타이젠 스페셜리스트이신 방진석님의 강의를 들으실 수 있습니다.

* 1차 워크숍
- 일정 : '19. 7. 29(월) ~ 31(수)
- 장소 : 서울시 금천구 디지털로 9길 90 까르뜨니트 물류창고
- 신청하기 : (마감) https://www.g.camp/910

1차 워크숍에서는 예정에 없던 타이젠팀 강석현님의 발표도 있었습니다.

발표자 : 강석현님

강석현님은 20분 남짓한 시간 동안 타이젠의 지난 몇 년간의 흐름을 짚어주셨습니다.

 

발표자 방진석님

그리고 방진석님께서 전체적으로 강의를 이끌어 나가셨는데,

이번이 공식적인 발표 데뷰전이신데도 불구하고 침착하게 잘하시더군요.

 

다행스럽게도,

1차 워크숍의 인기가 좋아서 동일한 내용의 워크숍이 하나 더 개설되었다고 합니다.

 

* 2차 워크숍
일정 : '19. 8. 5(월) ~ 7(수)
장소 : 서울시 금천구 디지털로 9길 90 까르뜨니트 물류창고
- 신청하기 : https://www.topmaker.kr/186

(이하 게시 내용)


 

 

 

□ 개요
 ○ 개최 배경
  - 리눅스기반 고성능 하드웨어의 제조 요청이 증가하고 있으나, 이와관련된 교육기회는 적으며, 라즈베리파이 기반으로 제공되는 경우는 적용은 매우 쉬우나, 실제 상용으로서의 한계를 가지고 있음
  - Tizen은 이미 많은 하드웨어에 실제 적용되어, 오류코드가 지속적으로 수정되고 있으며, 보안적으로 우수함
  - 다양한 API를 제공하여 쉽게 하드웨어 적용이 가능함
  - 이에 리눅스 기반 타이젠 플랫폼을 이용한 디바이스 제작으로  여러 기업 및 하드웨어 스타트업이 활용 할 수 있는 기회 제공

 ○  강의 : 타이젠 스페셜리스트 방진석 (https://developer.tizen.org/blog/tizen-specialist-program)

 ○ 기대효과
- 전년도 교육(https://topmaker.tistory.com/tag/TIZEN2018)과 변화된 내용 전달 
- Tizen IoT Platform을 이용한 간단한 전자 부품 및 Seneor 실습을 통한 Tizen IoT Project 이해 
- Tizen IoT Platform을 이용한 Lidar Sensor 제작 경험 공유 

□ 세부 내용 

 ○ 모집인원 : 20 명 (선착순) 다만, 전자 부품 및 C언어에 대한 이해를 중급이상으로 가지고 있어야 합니다. 

 ○ 일정

 [1일차] 

Tizen IoT Platform 소개 및 Tizen Studio 설치, 구조알기 Tizen 소개와 설치, 구조 알기 작년도 동영상 교육 내용 활용 (동영상 교육 재활용) - 현 시점의 달라진 내용 전달 - Craftroom workspace를 이용한 image 제작 소개 (해당 web page 에서 설명) - Tizen IoT Platform Memory Card 에 Image Fusing 하기 (해당 web page 에서 설명) - Tizen Studio 설치 설명 (해당 web page 에서 설명) - Tizen Project 구조 동작 방식 (작년도 동영상 교육 내용 으로 전달) - WiFi 설정 및 연결 - SDB 사용과 연결하기 - GPIO 사용을 위한 API 설명 - LED 제어 하기(실습)

 [2일차] 

Tizen IoT Platform을 이용한 전자 부품 및 Sensor 실습 - 버튼 입력 받기(실습) - 모션 센서 (실습) - I2C Bus 사용을 위한 API 설명 - illuminance Sensor (실습) - OLED 출력 하기

 [3일차] 

Tizen IoT Platform을 활용한 Digital 거리계 만들기 - Lidar Sensor 알아보기 - Hardware 배선((실습) - Tizen Project(distance) 설명 - Tizen Project를 활용한 Lidar Sensor 개발 경험 및 개발 멘토링

  ○ 준비물 ( 메이커스페이스에서 구매 준비합니다)

구분

품명

규격

수량

비고

개인

노트북

INTEL I5 이상 권장

1

 교육중에 Mac 셋팅을 지원하지는 않아요. 

재료

목록

Embedded board

Raspberry Pi 3 B

1

 

Lidar Sensor

Lidar Lite V3

1

 

OLED

0.96인치 OLED 디스플레이

모듈 - I2C

1

 

디지털 조도 센서

BH-1750 IIC bus

1

 

8-Channel 10bit

ADC SPI Interface

MCP3008

1

 

 

Motion Sensor

HC-SR501

1

 

 

 

 

 

 

USB to TTL Convert

PL2303

1

 

Bread Board

Half Size Breadboard

1

 

Raspberry Pi power

DC5V / MAX 2.5A

1

 

Electrolytic Capacitors

470 uF/ 16V

1

 

Yellow LED

5 pi, 5mm

1

 

Green LED

5 pi, 5mm

1

 

Resistance

2.7Kohm 1/4W

2

 

Resistance

330ohm 1/4W

2

 

※ 교육 참여자는 개인 노트북 및 USB 지참하여야 합니다. 
※ 교육에 사용되는 노트북 OS 는 Windows10 를 사용 합니다. Linux OS 및 Mac OS는 지원 하지 않습니다.
※ 교육 참여자는 전자 부품 및 C 언어에 대한 이해도가 중급이상이어야 합니다. 
※ 이 교육은 전자부품 및 센서 모듈을 중점 적으로 설명할 예정으로 Tizen에 연관된 클라우드는 다루지 않습니다. 

□ 참가신청
 ○ 천만원 가까이 비용이 투입되는 워크숍으로 불참시 반드시 통보요망, 미 통보시 향후 워크숍 참여불가
 ○ 참가비는 2만원을 받을 예정이며, 이는 최종일에 상호 네트워킹의 음료 구매시 실비로 사용할 예정입니다. 영수증은 제공되지 않으며, 영수증이 필요하신 분은 당일 근처 편의점에서 음료를 구매해서 가져오시면 됩니다. 

SDTA7D 보드 <사진=서울산업진흥원(SBA) 제공>

지난해 11월 아틱 브랜드가 종료된 이후,
지난 반년간 타이젠 플랫폼이 탑재된 보드를 개발하였습니다.

후원 : 서울산업진흥원 G Camp
제작 : Sigma Delta Technologies
기술지원 : 삼성전자
보드명 :  SDTA7D, Sigma Delta Technologies Arm cortex 7 Dual

조만간 인터넷으로도 구매할 수 있을 예정입니다.
구매가능하게 되면 이 게시물에 관련 정보를 추가하겠습니다.

관련기사 : http://www.etnews.com/20190722000115

 

서울시-SBA 메이커스랩 G·CAMP, 사물인터넷용 리눅스 보드 출시

[전자신문인터넷 박동선기자] 서울산업진흥원(대표 장영승, 이하 SBA)이 상용 하드웨어 보드 공급을 토대로 사물인터넷(IoT) 산업 활성화를 촉진한다. 최근 SBA 측은 산하 메이커스페이스 랩 G·CAMP(지&midd

www.etnews.com

 



안녕하세요, 타이젠 개발자 윤진입니다.


전자신문을 비롯하여 몇 개의 언론사에서 타이젠 기반 IoT 개발 워크숍에 대한 기사를 다뤘습니다..

근데 전자신문이 내용을 제일 잘 이해하고 썼네요.


전자신문 : http://www.etnews.com/20180727000135

한국경제 : http://news.hankyung.com/article/201807275359a





해커톤에서 사용된 자료를 공유합니다.

- 이은영님, '타이젠 IoT 환경설정',  Tizen_IoT_Environment.pdf

- 한준규님, '타이젠 앱 개발 기초',  Tizen_IoT_App_Basic_Development.pdf

- 손보연님, 'GPIO', https://craftroom.tizen.org/smart-motion-light-smartthings/

- 윤진, 'I2C & PWM', https://craftroom.tizen.org/illuminance_to_servo/

- 박정훈님, 'SPI', https://craftroom.tizen.org/co2/

- 정성문님, 박지원님, 자료는 따로 공유하지 않습니다.




* 본 게시물은 '19. 7. 29(월)에 추가로 수정되었습니다.

  Tizen IoT Preview는 Tizen 4.0에서 베타 버전으로 한시적으로 지원되었습니다.

  Tizen 5.0에서는 더 이상 사용할 수 없습니다.





출처 : https://developer.tizen.org/development/iot-preview/iot-apis


IoT APIs

 

The Tizen IoT API provides a common set of interfaces allowing you to build compelling IoT device applications which achieve native performance. The characteristics include:

  • Common set API, which means that the Tizen IoT API is based on the Tizen 4.0 common profile. The API supports the common set of mobile, wearable, and TV profiles and allows you to make IoT applications, such as network audio applications.
  • Available platform binaries, which allow you to efficiently create an IoT application. Tizen Common Headed binaries for Raspberry Pi 3 and ARTIK 530 have passed the API test verification, which means that you can create IoT applications with a productive quality.

In Preview 1, the Tizen IoT API releases only the native "C" API. Other convenient language types for the API are to be considered in the future.

The following table lists the IoT-specific Tizen platform API group.


Things SDK API

Developing "Things" which are market-ready (with cloud support) has been a challenge for most of the companies and individual developers. The SmartThings™ Things SDK API helps you to create new IoT devices easily. The version number of the first release is 0.9, which is the preview version.

The 2 core components for creating a new device are:

  • SmartThings™ Things JSON Configuration file (device_definition.json)

    For more information on the configuration file details, see Device Definition.

  • Application logic and user interaction

    For more information on using the SmartThings™ Things SDK API, see API Usage.

Figure: Creating a new device

Creating a new device

The SmartThings™ (ST) Things SDK provides you an easy and configurable option to build and deploy your own devices quickly:

  • The ST Things SDK provides JSON-based things definition, which:
    • Defines device and platform information.
    • Defines resources that the thing is supporting.
    • Defines an easy-setup configuration.
  • The ST Things SDK provides spec-agnostic APIs, which:
    • Hide the interface and resource type details in a request data.
    • Divide a collection resource request into single resource requests.
    • Provide the "property_key" in case of the GET request.

The SmartThings™ Things SDK API provides the following benefits for you:

  • Supporting pin-based and UserConfirm(Certificate)-based OTM in EasySetup.
  • Providing a JSON-based device/resource definition method in a single file:
    • Includes Single resource and Collection resource support.
  • Resources that are defined in a JSON file/string are made internally.
  • Easy APIs to handle requests and responses:
    • Supports request methods: GET and POST.
    • You only need to make a representation (bundle of property values) for a response.
    • You do not need to handle interfaces, as they are handled internally.
    • The request to a collection resource is divided into individual requests to single resources.
  • Cloud setup (Sign-up/Sign-in/Sign-out/Resource publish to cloud) is handled internally.
  • Following operations are handled internally:
    • To respond to an Access Point List (APList) request from a client.
    • To start and stop softAP.
    • To connect to a target WiFi AP (Enroller).
    • To make the whole response data according to the interfaces (such as oic.if.baselineoic.if.b, and oic.if.ll).


API Usage

The following figure illustrates the SmartThings™ Things API life-cycle.

 

 

Figure: SmartThings™ Things API life-cycle

SmartThings Things API life-cycle

Initializing Stack and Callbacks

Once the device configuration JSON file is ready, you can specify the read-only and read-write paths in the st_things_set_configuration_prefix_path() function (optional), and specify the file in the st_things_initialize() function:

bool easysetup_complete = false;
st_things_set_configuration_prefix_path("/ropath/XXX/res", "/rwpath/XXX/data"); /* Optional */
st_things_initialize("sample_device.json", &easysetup_complete);

/* User input can be handled graphically or using CLI */
/* You need to decide that */
if (!easysetup_complete) {
    int cmd = 0;
    printf("[%s]Start Easysetup ? (1:yes, other:no): ", TAG);
    scanf("%d", &cmd);
    if (1 != cmd) {
        st_things_deinitialize();

        return 0;
    }
}

/* Register Callbacks */
st_things_register_request_cb(handle_get_request, handle_set_request);
st_things_register_reset_cb(handle_reset_request, handle_reset_result);
st_things_register_user_confirm_cb(handle_ownership_transfer_request);
st_things_register_things_status_change_cb(handle_things_status_change);

st_things_start();
printf("ST Things Stack started\n");

handle_main_loop();

st_things_stop();
printf("ST Things Stack Stopped\n");
st_things_deinitialize();
printf("ST Things Stack deinitialized\n");

You must define the highlighted code in the above example. The st_XXX() functions come from the ST Things SDK API. For more information, see the API Documentation.

Getting and Setting Request Handling Callbacks

Assume that the following resources and resource types are defined in the sample_device.json file:

Example: Resources and resource types

"resources": {
   "single": [
      {
         "uri": "/switch",
         "types": [
            "oic.r.switch.binary"
         ],
         "interfaces": [
            "oic.if.a",
            "oic.if.baseline"
         ],
         "policy": 3
      },
      {
         "uri": "/audio",
         "types": [
            "oic.r.audio"
         ],
         "interfaces": [
            "oic.if.a",
            "oic.if.baseline"
         ],
         "policy": 3
      }
   ]
}
"resourceTypes": [
   {
      "type": "oic.r.switch.binary",
      "properties": [
         {
            "key": "value",
         "type": 0,
            "mandatory": true,
            "rw": 3
         }
      ]
   },
   {
      "type": "oic.r.audio",
      "properties": [
         {
            "key": "volume",
            "type": 1,
            "mandatory": true,
            "rw": 3
         },
         {
            "key": "mute",
            "type": 0,
            "mandatory": true,
            "rw": 3
         }
      ]
   }
]

The 2 defined resources are:

  • Switch (URI = "/switch")
  • Audio (URI = "/audio")

The following example illustrates the get and set request handlers:

static const char* RES_SWITCH = "/switch";
static const char* RES_AUDIO = "/audio";

bool
handle_get_request(st_things_get_request_message_s* req_msg, st_things_representation_s* resp_rep)
{
    printf("[%s]Received a GET request on %s\n", TAG, req_msg->resource_uri);
    bool ret = false;
    if (0 == strcmp(req_msg->resource_uri, RES_SWITCH)) {
        ret = handle_get_request_on_switch(req_msg, resp_rep);
    } else if (0 == strcmp(req_msg->resource_uri, RES_AUDIO)) {
        ret = handle_get_request_on_audio(req_msg, resp_rep);
    } else {
        printf("[%s]Not supported uri.\n", TAG);
    }

    return ret;
}

bool
handle_set_request(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
{
    printf("[%s]Received a SET request on %s\n", TAG, req_msg->resource_uri);
    bool ret = false;

    if (0 == strcmp(req_msg->resource_uri, RES_SWITCH)) {
        ret = handle_set_request_on_switch(req_msg, resp_rep);
    } else if (0 == strcmp(req_msg->resource_uri, RES_AUDIO)) {
        ret = handle_set_request_on_audio(req_msg, resp_rep);
    } else {
        printf("[%s]Not supported uri.\n", TAG);
    }

    return ret;
}

The key difference is the req_msg->resource_uri value passed in the callbacks to distinguish the 2 resources. Since the resource URI is unique in the device definition, each resource can be handled separately.

The following examples illustrate the get and set request handling callbacks for a single and multiple properties:

  • For a single property, you must extract the desired property from the request message and update the device property database locally. Once you have updated the device property, you must update the response representation about the updated property which is sent to the client:
    #define TAG "DEVELOPER_DEVICE"
    
    static const char* PROPERTY_VALUE = "value";
    bool g_switch_value = false;
    
    bool
    handle_get_request_on_switch(st_things_get_request_message_s* req_msg, st_things_representation_s* resp_rep)
    {
        printf("[%s]IN-handle_get_request_on_switch() called..\n", TAG);
        printf("[%s]current switch value: %d\n", TAG, g_switch_value);
    
        resp_rep->set_bool_value(resp_rep, PROPERTY_VALUE, g_switch_value);
    
        printf("[%s]OUT-handle_get_request_on_switch() called..\n", TAG);
    
        return true;
    }
    
    bool
    handle_set_request_on_switch(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
    {
        printf("[%s]IN-handle_set_request_on_switch() called..\n", TAG);
        printf("[%s]current switch value: %d\n", TAG, g_switch_value);
    
        bool desired_value = false;
        req_msg->rep->get_bool_value(req_msg->rep, PROPERTY_VALUE, &desired_value);
    
        printf("[%s]desired switch value: %d\n", TAG, desired_value);
        g_switch_value = desired_value;
        printf("[%s]changed switch value: %d\n", TAG, g_switch_value);
    
        resp_rep->set_bool_value(resp_rep, PROPERTY_VALUE, g_switch_value);
    
        printf("[%s]OUT-handle_set_request_on_switch() called..\n", TAG);
    
        return true;
    }
  • For multiple properties, the process is the same, except that you need to handle multiple properties at the same time:
    #define TAG "DEVELOPER_DEVICE"
    static const char* PROPERTY_VOLUME = "volume";
    static const char* PROPERTY_MUTE = "mute";
    int64_t g_audio_volume = 0;
    bool g_audio_mute = false;
    
    bool
    handle_get_request_on_audio(st_things_get_request_message_s* req_msg, st_things_representation_s* resp_rep)
    {
        printf("[%s]IN-handle_get_request_on_audio() called..\n", TAG);
        printf("[%s]current audio volume: %"PRId64".\n", TAG, g_audio_volume);
        printf("[%s]current audio mute: %d.\n", TAG, g_audio_mute);
    
        resp_rep->set_int_value(resp_rep, PROPERTY_VOLUME, g_audio_volume);
        resp_rep->set_bool_value(resp_rep, PROPERTY_MUTE, g_audio_mute);
        printf("[%s]OUT-handle_get_request_on_audio() called..\n", TAG);
    
        return true;
    }
    
    bool
    handle_set_request_on_audio(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
    {
        printf("[%s]IN-handle_set_request_on_audio() called..\n", TAG);
        printf("[%s]current audio volume: %"PRId64".\n", TAG, g_audio_volume);
        printf("[%s]current audio mute: %d\n", TAG, g_audio_mute);
    
        int64_t desired_volume = 0;
        bool desired_mute = false;
        req_msg->rep->get_int_value(req_msg->rep, PROPERTY_VOLUME, &desired_volume);
        req_msg->rep->get_bool_value(req_msg->rep, PROPERTY_MUTE, &desired_mute);
    
        printf("[%s]desired audio volume: %"PRId64".\n", TAG, desired_volume);
        printf("[%s]desired audio mute: %d.\n", TAG, desired_mute);
    
        g_audio_volume = desired_volume;
        g_audio_mute = desired_mute;
    
        printf("[%s]changed audio volume: %"PRId64".\n", TAG, g_audio_volume);
        printf("[%s]changed audio mute: %d.\n", TAG, g_audio_mute);
    
        resp_rep->set_int_value(resp_rep, PROPERTY_VOLUME, g_audio_volume);
        resp_rep->set_bool_value(resp_rep, PROPERTY_MUTE, g_audio_mute);
    
        printf("[%s]OUT-handle_set_request_on_audio() called..\n", TAG);
    
        return true;
    }

Notifying Observers

The following example illustrates how you can notify observers:

#define TAG "DEVELOPER_DEVICE"
static const char* RES_SWITCH = "/switch";
static const char* RES_AUDIO = "/audio";
static const char* PROPERTY_VALUE = "value";
bool g_switch_value = false;

bool
notify_observers(const char *resource_uri)
{
    printf("[%s] Notify all observers for resource = %s\n", TAG, resource_uri);
    bool ret = false;
    if (0 == strcmp(resource_uri, RES_SWITCH)) {
        ret = st_things_notify_observers(resource_uri);
    } else if (0 == strcmp(resource_uri, RES_AUDIO)) {
        ret = st_things_notify_observers(resource_uri);
    } else {
        printf("[%s]Not supported uri.\n", TAG);
    }

    return ret;
}

bool
handle_set_request_on_switch(st_things_set_request_message_s* req_msg, st_things_representation_s* resp_rep)
{
    printf("[%s]IN-handle_set_request_on_switch() called.\n", TAG);
    printf("[%s]current switch value: %d\n", TAG, g_switch_value);
    bool is_value_changed = false;
    bool desired_value = false;
    req_msg->rep->get_bool_value(req_msg->rep, PROPERTY_VALUE, &desired_value);

    printf("[%s]desired switch value: %d\n", TAG, desired_value);
    if (g_switch_value = desired_value) {
        g_switch_value = desired_value;
        is_value_changed = true;
    }
    resp_rep->set_bool_value(resp_rep, PROPERTY_VALUE, g_switch_value);

    if (is_value_changed) {
        notify_observers(req_msg->resource_uri);
    }
    printf("[%s]OUT-handle_set_request_on_switch() called..\n", TAG);

    return true;
}

IoTivity Information

The following table lists the resource types supported by IoTivity.

Table: IoTivity resource types

Resource type nameResource type value
Deviceoic.wk.d
Platformoic.wk.p
Discoveryoic.wk.res
Presenceoic.wk.ad
Collectionoic.wk.col

The following table shows the IoTivity interfaces that specify how the device returns its response. These interfaces can be used by the IoTivity client (such as Samsung Connect) to retrieve information from the server (device).

Table: IoTivity interfaces for responses

NameInterfaceDescription
Baselineoic.if.baselineIncludes all information about the resource, including metadata and collection information. This is the default interface type.
Linked Listoic.if.llIncludes only the collection information about the resource. This is the default interface type for /oic/res.
Batchoic.if.bAllows for the aggregation of interaction with all resources. Each resource is interacted with separately, but their responses are aggregated.

The following table lists other interface types that are related to permissions. These interfaces are relevant for retrieve and update requests.

Table: IoTivity interfaces for permissions

NameInterfaceDescription
Readoic.if.rAllows values to be read.
Read Writeoic.if.rwAllows values to be read and written.
Actuatoroic.if.aAllows creating, updating, and retrieving actuator values.
Sensoroic.if.sAllows sensor values to be read.



Tizen Peripheral I/O Native API

Tizen IoT provides the Peripheral I/O APIs for IoT devices to control peripherals, such as sensors and actuators, using industry-standard protocols and interfaces:

  • GPIO (General-Purpose Input/Output)
  • PWM (Pulse-Width Modulation)
  • SPI (Serial Peripheral Interface)
  • I2C (Inter-Integrated Circuit)
  • UART (Universal Asynchronous Receiver-Transmitter)

Since each peripheral supports different interfaces and protocols, you must check from the peripheral's specifications whether a specific protocol is supported. Peripheral I/O APIs are categorized based on the protocol.

Figure: Peripherals connected to an IoT device

Peripherals connected to an IoT device

Supported Protocols

The following table lists the supported protocols for the Tizen IoT hardware targets.

Table: Protocols supported by the Tizen IoT hardware targets

ProtocolARTIK 530Raspberry Pi 3
GPIOYesYes
PWMYesNo
SPIYesYes
I2CYesYes
UARTYesYes

The following figures illustrate the pinout information for the Tizen IoT hardware targets.

Figure: ARTIK 530 pinout

ARTIK 530 pinout

Figure: Raspberry Pi 3 pinout

Raspberry Pi 3 pinout

Prerequisites

  1. To use the Peripheral I/O API, the application has to request permission by adding the following platform privilege to the tizen-manifest.xml file:
    <privileges>
       <privilege>http://tizen.org/privilege/peripheralio</privilege>
    </privileges>

    To obtain authorization to use platform-level privileges, the application must be signed with a platform-level distributor certificate. Create a certificate profile for signing the application:

    1. To open the Certificate Manager, in the Tizen Studio menu, go to Tools > Certificate Manager.

      Certificate Manager

    2. To add a new certificate profile for signing your application, click + in the Certificate Manager and enter a profile name.

      Add a new profile

    3. Select Create a new author certificate and click Next.

      Create an author certificate

    4. Enter the key file name, author name, password, and password again. If you want to provide more information for the certificate, enter the details after unfolding the More details section.

      Add author certificate details

    5. Select Use the default Tizen distributor certificate and the Platform privilege level, and click Finish.

      The new platform-level certificate is created and shown in the Certificate Manager.

      Select privilege level

      View new certificate

  2. To use the functions and data types of the Peripheral I/O API, include the <peripheral_io.h> header file in your application:
    #include <peripheral_io.h>


GPIO

GPIO (General-Purpose Input/Output) is a programmable interface for reading the state of binary input peripherals, such as a switch, and controlling the state of binary output peripherals, such as a LED.

GPIO sets a direction for the data transfer. It can also detect an interrupt signaled by a level transition: either a falling edge (high to low) or a rising edge (low to high). To detect the interrupt signal you want, set the appropriate edge mode.

GPIO offers the following edge modes:

  • Rising mode detects data changes from low to high.
  • Falling mode detects data changes from high to low.

Figure: GPIO edge modes

GPIO edge modes

Opening and Closing a Handle

To open and close a handle:

  1. To open a GPIO handle, use the peripheral_gpio_open() function:
    int pin = 26; /* ARTIK 530 : GPIO8, Raspberry Pi 3 : GPIO26 */
    peripheral_gpio_h gpio_h;
    peripheral_gpio_open(pin, &gpio_h);

    The pin parameter required for this function must be set according to the following tables.

    Table: ARTIK 530

    Pin namePin (parameter 1)Pin namePin (parameter 1)
    GPIO0128GPIO1129
    GPIO2130GPIO346
    GPIO414GPIO541
    GPIO625GPIO70
    GPIO826GPIO927

    Table: Raspberry Pi 3

    Pin namePin (parameter 1)Pin namePin (parameter 1)
    GPIO44GPIO55
    GPIO66GPIO1212
    GPIO1313GPIO1616
    GPIO1717GPIO1818
    GPIO1919GPIO2020
    GPIO2121GPIO2222
    GPIO2323GPIO2424
    GPIO2525GPIO2626
    GPIO2727--
    NoteFor more information on the pin names and locations, see Supported Protocols.
  2. To close a GPIO handle that is no longer used, use the peripheral_gpio_close() function:
    peripheral_gpio_close(gpio_h);

Setting the Data Direction

To set the data transfer direction, use the peripheral_gpio_set_direction() function with 1 of the following direction types:

  • PERIPHERAL_GPIO_DIRECTION_IN: Input mode to receive data from a binary output peripheral.
  • PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH: Output mode to send data to a binary output peripheral. This value initializes the output peripheral state as high.
  • PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW: Output mode to send data to a binary output peripheral. This value initializes the output peripheral state as low.
peripheral_gpio_set_direction(gpio_h, PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW);
NoteTo set the data direction to PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH or PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW, the edge mode must be set to PERIPHERAL_GPIO_EDGE_NONE.

Setting the Edge Mode

To set the edge mode, use the peripheral_gpio_set_edge_mode() function with 1 of the following edge mode types:

  • PERIPHERAL_GPIO_EDGE_NONE: No edge mode.
  • PERIPHERAL_GPIO_EDGE_RISING: Interrupted at a rising edge (low to high).
  • PERIPHERAL_GPIO_EDGE_FALLING: Interrupted at a falling edge (high to low).
  • PERIPHERAL_GPIO_EDGE_BOTH: Interrupted at both rising and falling edges.
peripheral_gpio_set_edge_mode(gpio_h, PERIPHERAL_GPIO_EDGE_RISING);
NoteTo set the edge mode to PERIPHERAL_GPIO_EDGE_RISINGPERIPHERAL_GPIO_EDGE_FALLING, or PERIPHERAL_GPIO_EDGE_BOTH, the data direction must be set to the PERIPHERAL_GPIO_DIRECTION_IN.

Setting the Interrupted Callback

The interrupted callback is called when the GPIO state changes, based on the selected edge mode.

The interrupted callback is unset when the peripheral_gpio_unset_interrupted_cb() function is called or when the callback receives an error value other than PERIPHERAL_ERROR_NONE.

To implement the interrupted callback:

  1. Define the interrupted callback content.
    static void
    interrupted_cb(peripheral_gpio_h gpio_h, peripheral_error_e error, void *user_data)
    {
        /* Code you want to run when the interrupt occurs */
    }
  2. Set the callback with the peripheral_gpio_set_interrupted_cb() function:
    peripheral_gpio_set_interrupted_cb(gpio_h, interrupted_cb, NULL);
  3. When no longer needed, unset the interrupt callback with the peripheral_gpio_unset_interrupted_cb()function:
    peripheral_gpio_unset_interrupted_cb(gpio_h);

Reading and Writing Binary Data

To read and write binary data:

  • To read binary data from a peripheral, use the peripheral_gpio_read() function:
    uint32_t value;
    peripheral_gpio_read(gpio_h, &value);
  • To write binary data to a peripheral, use the peripheral_gpio_write() function:
    uint32_t value = 1;
    peripheral_gpio_write(gpio_h, value);
NoteTo write binary data, the data direction must be set to PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGHor PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW.


PWM

PWM (Pulse-Width Modulation) is a programmable interface that allows you to, for example, control motor speed or change light brightness.

Peripherals that support PWM are controlled by the current strength. To modulate the current, the voltage needs to be modulated. The voltage is proportional to the intensity of the current.

To modulate the voltage, you must set the duty cycle and polarity:

  • The period is a constant interval at which the pulse repeats.
  • The duty cycle is the constant time within 1 period in which a signal is active.
  • A "polarity high" signal starts high for the duration of the duty cycle and goes low for the remainder of the period. Conversely, a "polarity low" signal starts low for the duration of the duty cycle and goes high for the remainder of the period.
  • The pulse repeats if repetition has been enabled.

Figure: Duty cycle

Duty cycle

For example, if the period is 10,000,000 nanoseconds and the polarity high duty cycle is 7,000,000 nanoseconds, the average voltage is at 70%.

Figure: Average voltage per duty cycle

Average voltage per duty cycle

Opening and Closing a Handle

To open and close a handle:

  1. To open a PWM handle, use the peripheral_pwm_open() function:
    int chip = 0;
    int pin = 2;
    peripheral_pwm_h pwm_h;
    peripheral_pwm_open(chip, pin, &pwm_h);

    The chip and pin parameters required for this function must be set according to the following table.

    Table: ARTIK 530

    Pin nameChip (parameter 1)Pin (parameter 2)
    PWM002
    NoteFor more information on the pin names and locations, see Supported Protocols.
  2. To close a PWM handle that is no longer used, use the peripheral_pwm_close() function:
    peripheral_pwm_close(pwm_h);

Setting the Period

To set the period, use the peripheral_pwm_set_period() function.

The following example sets the period to 20 milliseconds. The unit is nanoseconds.

Uint32_t period = 20000000;
peripheral_pwm_set_period(pwm_h, period);

Setting the Duty Cycle

To set the duty cycle, use the peripheral_pwm_set_duty_cycle() function.

The following example sets the duty cycle to 2 milliseconds. The unit is nanoseconds.

uint32_t duty_cycle = 2000000;
peripheral_pwm_set_duty_cycle(pwm_h, duty_cycle);

Setting the Polarity

To set the polarity, use the peripheral_gpio_set_polarity() function with 1 of the following polarity types:

  • PERIPHERAL_PWM_POLARITY_ACTIVE_HIGH: Polarity is high.
  • PERIPHERAL_PWM_POLARITY_ACTIVE_LOW: Polarity is low.
peripheral_pwm_set_polarity(pwm_h, PERIPHERAL_PWM_POLARITY_ACTIVE_HIGH);

Enabling Repetition

To enable repetition, use the peripheral_pwm_set_enabled() function:

bool enable = true;
peripheral_pwm_set_enabled(pwm_h, enable);


SPI

SPI (Serial Peripheral Interface) is a programmable interface for transferring data quickly to peripherals that require high performance.

The SPI protocol is a serial communication method that controls the clock signal as master and other peripherals connected to SPI as slaves. This protocol is used by peripherals, such as heart-beat pulse sensors and graphic displays, that require fast data transfer.

Figure: SPI interface diagram

SPI interface diagram

The SPI is a communication method between 1 master and multiple slave devices. In the above figure:

  • CLK (SCLK or SCK) is a simple synchronization signal and a communication clock.
  • The data flows from the master to the slave in the MOSI (Master Out Slave In) line, and from the slave to the master in the MISO (Master In Slave Out) line. Full duplex data communication is possible with 2 lines (MOSI and MISO).
  • CS (Chip Select) is a signal for selecting a slave device.

SPI supports half duplex read/write and full duplex transfer.

To use SPI, you must set the following:

  • SPI mode

    Figure: SPI modes

    SPI modes

    Each of the 4 available SPI modes defines a specific combination of clock polarity (CPOL) and clock phase (CPHA).

    Table: SPI modes

    SPI mode

    Polarity

    (CPOL)

    Phase

    (CPHA)

    Description
    SPI MODE 000CLK (Clock) is first low and data is sampled on the rising edge of each clock pulse.
    SPI MODE 101CLK is first low and data is sampled on the falling edge of each clock pulse.
    SPI MODE 210CLK is first high and data is sampled on the falling edge of each clock pulse.
    SPI MODE 311CLK is first high and data is sampled on the rising edge of each clock pulse.
  • Bit order

    The bit order refers to the sequential order in which bytes are arranged into larger numerical values. MSB indicates that the most significant bit is transmitted first. LSB indicates that the least significant bit is transmitted first.

  • Bit per word

    The bit per word refers to the number of bits to be transmitted at a time when data is exchanged with a connected slave. Normally, it is set to 8 bits per word.

  • Frequency

    The frequency refers to the clock signal in Hz. Since the frequencies are different for each slave device, the applicable value must be checked from the peripheral's specification.

Opening and Closing a Handle

To open and close a handle:

  1. To open a SPI handle, use the peripheral_spi_open() function:
    int bus = 2;
    int chip_select = 0;
    peripheral_spi_h spi_h;
    peripheral_spi_open(bus, chip_select, &spi_h);

    The bus and chip_select parameters required for this function must be set according to the following tables.

    Table: ARTIK 530

    Pin nameBus (parameter 1)Chip Select (parameter 2)
    SPI0_MOSISPI0_MISOSPI0_CLKSPI0_CS20

    Table: Raspberry Pi 3

    Pin nameBus (parameter 1)Chip Select (parameter 2)
    SPI0_MOSISPI0_MISOSPI0_CLKSPI0_CS000
    SPI0_MOSISPI0_MISOSPI0_CLKSPI0_CS101
    NoteFor more information on the pin names and locations, see Supported Protocols.
  2. To close a SPI handle that is no longer used, use the peripheral_spi_close() function:
    peripheral_spi_close(spi_h);

Setting the SPI Mode

To set the SPI mode, use the peripheral_spi_set_mode() function with 1 of the following mode types:

  • PERIPHERAL_SPI_MODE_0: CLK is active high and sampled at the rising edge.
  • PERIPHERAL_SPI_MODE_1: CLK is active high and sampled at the falling edge.
  • PERIPHERAL_SPI_MODE_2: CLK is active low and sampled at the rising edge.
  • PERIPHERAL_SPI_MODE_3: CLK is active low and sampled at the falling edge.
peripheral_spi_set_mode(spi_h, PERIPHERAL_SPI_MODE_1);

Setting the Bit Order

To set the bit order, use the peripheral_spi_set_bit_order() function with 1 of the following bit order types:

  • PERIPHERAL_SPI_BIT_ORDER_MSB: Use the most significant bit first.
  • PERIPHERAL_SPI_BIT_ORDER_LSB: Use the least significant bit first.
peripheral_spi_set_bit_order(spi_h, PERIPHERAL_SPI_BIT_ORDER_MSB);
NoteThe ARTIK 530 and Raspberry Pi 3 boards do not support the LSB bit order.

Setting the Bits per Word

To set the bits per word, use the peripheral_spi_set_bits_per_word() function:

uint8_t bits_per_word = 8;
peripheral_spi_set_bits_per_word(spi_h, bits_per_word);

Setting the Frequency

To set the frequency, use the peripheral_spi_set_frequency() function.

The frequency unit is Hz.

uint32_t frequency = 1024;
peripheral_spi_set_frequency(spi_h, frequency);

Reading, Writing, and Transferring Data

To read, write, and transfer data:

  • To read data from a slave device, use the peripheral_spi_read() function:
    uint8_t data;
    uint32_t length = 1;
    peripheral_spi_read(spi_h, &data, length);
  • To write data to a slave device, use the peripheral_spi_write() function:
    uint8_t data = 0x80;
    uint32_t length = 1;
    peripheral_spi_read(spi_h, &data, length);
  • To exchange bytes data with a slave device, use the peripheral_spi_transfer() function:
    uint8_t tx_data[2] = {0x80, 0x01};
    uint8_t rx_data[2];
    uint32_t length = 2;
    peripheral_spi_transfer(spi_h, tx_data, rx_data, length);


I²C

I2C (Inter-Integrated Circuit) is a programmable interface that allows you to communicate with I2C peripherals.

I2C is a synchronous serial interface that uses a clock signal to synchronize data transfers between master and slave device:

  • Master device generates the clock and initiates communication with slaves.
  • Slave device receives the clock and responds when addressed by the master.

Figure: I2C interface diagram

I2C interface diagram

To allow the I2C master to connect to 128 I2C slave devices, an I2C slave device provides a 7-bit address. Since most slave addresses are determined by the manufacturer, refer to the specification to find the slave device address.

Using the I2C bus, the master controls signal lines called SCL (Shared CLock) and SDA (Shared DAta) to read or write data to or from the device. SCL is a clock line for communication synchronization, and SDA is a data line. The master outputs the clock for synchronization with the SCL, and the slave outputs or receives data through the SDA according to the clock output to the SCL.

If the SDA line is used alone, only half duplex communication is possible because data is sent only to 1 line.

Opening and Closing a Handle

To open and close a handle:

  1. To open an I2C handle, use the peripheral_i2c_open() function:
    int bus = 1;
    int address = ...;   /* See the specification */
    peripheral_i2c_h i2c_h;
    peripheral_i2c_open(bus, address, &i2c_h);

    The bus parameter required for this function must be set according to the following table.

    Table: ARTIK 530 / Raspberry Pi 3

    Pin nameBus number (parameter 1)
    I2C1_SDAI2C1_SCL1
    NoteFor more information on the pin names and locations, see Supported Protocols.

    The address parameter must be set based on the peripheral specification.

  • To close an I2C handle that is no longer used, use the peripheral_i2c_close() function:
    peripheral_i2c_close(i2c_h);

Reading and Writing Data

To read and write data:

  • To write bytes to a slave device, use the peripheral_i2c_write() function:
    uint8_t data[2] = {0x06, 0x01};
    uint32_t length = 2;
    peripheral_i2c_write(i2c_h, data, length);
  • To read bytes from a slave device, use the peripheral_i2c_read() function:
    uint8_t data[2];
    uint32_t length = 2;
    peripheral_i2c_read(i2c_h, data, length);

Reading and Writing Register Data

To read and write register data:

  • To write single byte data to a slave device register, use the peripheral_i2c_write_register_byte() function:
    uint8_t data = 0x06;
    uint8_t register_address = ...;  /* See the specification */
    peripheral_i2c_write_register_byte(i2c_h, register_address, data);
  • To read single byte data from a slave device register, use the peripheral_i2c_read_register_byte() function:
    uint8_t data ;
    uint8_t register_address = ...;  /* See the specification */
    peripheral_i2c_read_register_byte(i2c_h, register_address, &data);
  • To write word data to a slave device register, use the peripheral_i2c_write_register_word() function:
    uint16_t data = 0xffff;
    uint8_t register_address = ...;  /* See the specification */
    peripheral_i2c_write_register_word(i2c_h, register_address, data);
  • To read word data from a slave device register, use the peripheral_i2c_read_register_word() function:
    uint16_t data ;
    uint8_t register_address = ...;  /* See the specification */
    peripheral_i2c_read_register_word(i2c_h, register_address, &data);


UART

UART (Universal Asynchronous Receiver-Transmitter) is a programmable interface that allows you to communicate 1:1 with a UART peripheral.

Figure: UART interface diagram

UART interface diagram

UART is an interface for exchanging data with peripherals. It is an asynchronous method that transmits data without a clock line, and consists of only 2 data lines: transmit (Tx) and receive (Rx). UART performs 1:1 communication.

Figure: UART data frame

UART data frame

The UART data frame consists of start (1 bit), data (5~8 bit), parity (1 bit) and stop (1 bit):

  • Start bit

    Indicates the start of the communication before sending data and holds it for a bit time length.

  • Data

    Transmits 5 to 8 bits of data.

  • Parity bit

    Generates and transmits a parity value for error verification, and determines a receiving side error. The following options are available: NoneEven, and Odd parity. Selecting None removes this bit.

  • Stop bit

    Indicates the termination of the communication and holds 1 or 2 bits.

  • Baud rate

    Asynchronous transmission/receiving speeds must be matched to the peripheral. For this purpose, the number of signals transmitted per second can be synchronized with a peripheral. It is called the Baud.

If a device supports a 5-wire UART port, hardware flow control can be used to increase the reliability of the data transmission. Software flow control can also be used to increase reliability.

Opening and Closing a Handle

To open and close a handle:

  1. To open a UART handle, use the peripheral_uart_open() function:
    int port = 4; /* ARTIK 530 : UART0 */
    peripheral_uart_h uart_h;
    peripheral_uart_open(port, &uart_h);

    The port parameter required for this function must be set according to the following tables.

    Table: ARTIK 530

    Pin namePort (parameter 1)
    UART0_RXUART0_TX4

    Table: Raspberry Pi 3

    Pin namePort (parameter 1)
    UART0_RXUART0_TX0
    NoteFor more information on the pin names and locations, see Supported Protocols.
  2. To close a UART handle that is no longer used, use the peripheral_uart_close() function:
    peripheral_uart_close(uart_h);

Setting the Baud Rate

To set the baud rate, use the peripheral_uart_set_baud_rate() function with a baud rate value:

  • PERIPHERAL_UART_BAUD_RATE_0 ~ PERIPHERAL_UART_BAUD_RATE_230400
peripheral_uart_set_baud_rate(uart_h, PERIPHERAL_UART_BAUD_RATE_9600);

Setting the Byte Size

To set the byte size, use the peripheral_uart_set_byte_size() function with 1 of the following byte size types:

  • PERIPHERAL_UART_BYTE_SIZE_5BIT: Byte size is 5 bits.
  • PERIPHERAL_UART_BYTE_SIZE_6BIT: Byte size is 6 bits.
  • PERIPHERAL_UART_BYTE_SIZE_7BIT: Byte size is 7 bits.
  • PERIPHERAL_UART_BYTE_SIZE_8BIT: Byte size is 8 bits.
peripheral_uart_set_byte_size(uart_h, PERIPHERAL_UART_BYTE_SIZE_7);

Setting the Parity Bit

To set the parity bit, use the peripheral_uart_set_parity() function with 1 of the following parity types:

  • PERIPHERAL_UART_PARITY_NONE: No parity bit.
  • PERIPHERAL_UART_PARITY_EVEN: Parity bit is even.
  • PERIPHERAL_UART_PARITY_ODD: Parity bit is odd.
peripheral_uart_set_parity(uart_h, PERIPHERAL_UART_PARITY_EVEN);

Setting the Stop Bits

To set the stop bits, use the peripheral_uart_set_stop_bits() function with 1 of the following stop bit types:

  • PERIPHERAL_UART_STOP_BITS_1BIT: 1 bit is used for stop bits.
  • PERIPHERAL_UART_STOP_BITS_2BIT: 2 bit is used for stop bits.
peripheral_uart_set_stop_bits(uart_h, PERIPHERAL_UART_STOP_BITS_2BIT);

Setting the Flow Control

To set the hardware and software flow control, use the peripheral_uart_set_flow_control() function with 1 of the following flow control types:

  • PERIPHERAL_UART_SOFTWARE_FLOW_CONTROL_NONE: No software flow control.
  • PERIPHERAL_UART_SOFTWARE_FLOW_CONTROL_XONXOFF: Software flow control uses XONXOFF.
  • PERIPHERAL_UART_HARDWARE_FLOW_CONTROL_NONE: No hardware flow control.
  • PERIPHERAL_UART_HARDWARE_FLOW_CONTROL_AUTO_RTSCTS: Hardware flow control uses RTSCTS.
peripheral_uart_set_flow_control(uart_h, PERIPHERAL_UART_SOFTWARE_FLOW_CONTROL_XONXOFF, PERIPHERAL_UART_HARDWARE_FLOW_CONTROL_AUTO_RTSCTS);

Reading and Writing Data

To read and write data:

  • To write data to a slave device, use the peripheral_uart_write() function:
    uint8_t data[2] = {0x06, 0x01};
    uint32_t length = 2;
    peripheral_uart_write(uart_h, data, length);
  • To read data from a slave device, use the peripheral_uart_read() function:
    uint8_t data[2];
    uint32_t length = 2;
    peripheral_uart_read(uart_h, data, length);


+ Recent posts