EE/Embedded Systems

[nRF52BLE][4]C Development with SoftDevice API

esmJK 2021. 1. 4. 14:03

4) Actual Code / API Use

개발환경 : Seggar Embedded Studio (SES) 

개발보드 : nRF52DK (PCA10040) 

 

ble_serv_char^.zip
0.28MB

 

i) - SDK폴더\examples에 폴더 생성 (폴더 이름은 마음대로) 

ii) - 첨부된 파일의 압축을 풀고 폴더 안에 위치 

(모든 dependency가 상대경로로 지정되어 있기 때문에 정확한 디렉토리 위치에 있지 않을 경우 컴파일되지 않는다)

iii) - 컴파일 

 

수정하고 추가한 모든 파일이 Application 폴더 안에 존재하게끔 되어 있다.

CTRL + F 로 각 numbering 된 단계를 따라가시면서 코드를 봐주시면 된다. 

 

주기적으로 송신되는 센서의 값은 nRF 에 내장된 프로세서 온도이고, 이를 응용해 GPIO로 받아지는 센서 출력을 받게끔 변경할 수 있다. 

 

1. Service 생성

1.A) Service 구조체 선언 [\main.c]

 

1.B) Service 초기화 [\main.c\services_init()]

 

1.C) BLE Stack Table에 UUID 추가 [\our_service.c\our_service_init()]

 

1.D) sd_ble_gatts_service_add() 로 Service 추가 [\our_service.c\our_service_init()]

 

1.E) Service UUID를 가지는 ble_uuid_t 구조체 변수 선언 [\main.c]

 

1.F) Scan Response 선언 / 인스턴스화 [\main.c\advertising_init()]

 

2. Characteristics 생성

2.A) Custom Characteristic UUID [\our_service.c\our_char_add()]

 

2.B) 메모리 어느 부분에 Attribute 저장할 것인지 설정 [\our_service.c\our_char_add()]

 

2.C) Characteristic value Attribute를 생성해 UUID를 저장할 수 있도록 sd_ble_gatts_characteristic_add() 로 Characteristics 추가 [\our_service.c\our_char_add()]

 

2.D) ble_os_t 구조체에 characteristic 위한 handle 추가 [\our_service.h]

 

2.E) sd_blegatts_characteristic_add()로 service에 Characteristic 추가 [\our_service.c\our_char_add()]

 

2.F) Read/Write Property 추가 [\our_service.c\our_char_add()]

 

2.G) Read/Write Permission 추가 [\our_service.c\our_char_add()]

 

2.H) Characteristic Length 설정 (기본이 0으로 되어있어 Write 불가했었음) [\our_service.c\our_char_add()]

 

 

3. CCCD를 설정하고 Characteristic에 추가하여 sensor value 바뀔때마다 주기적으로 notification 송신 & Housekeeping. 

Housekeeping : Bluetooth Connection 관리를 뜻한다

 

3.A) CCCD Metadata 설정 [\our_service.c\our_char_add()]

 

3.B) Housekeeping: Service connection handle 을 기본값으로(BLE_CONN_HANDLE_INVALID) 설정 [\our_service.c\our_service_init()]

 

3.C) Housekeeping: Responding to Connect and Disconnect Events [\main.c\ble_stack_init()]

 

여기서 Observer는 event를 듣고 있는 코드로 이루어져 있다. 안드로이드의 broadcasting, iOS의 notification 과 비슷한 느낌...

 

3.D) Switch 문으로 BLE Event 처리. 정확히는 Connection 시 BLE Stack에서 제공하는 현재의 connection handle로 Service 구조체의 connection handle을 업데이트.[\our_service.c\ble_our_service_on_ble_evt()]

 

3.E) Characteristic Value 업데이트 [\our_service.c\our_characteristic_update()]

Housekeeping을 한 이유는 connection을 확인 후 notification을 보내기 위함이었다. connection if문으로 확인 후 진행한다. 진행 시 hvx 라는 것을 마주치게 되는데 이는 Handle Value X 의 축약어이며, X는 구조체로 정의된 notification 또는 indication을 뜻한다. [\our_service.c\our_sensor_characteristic_update()]

 

여기서부터는 Sensor 데이터를 제시간에 제공하기만 하면 되는데, 타이머를 써야 한다.

 

3.F) timer가 일정 시간에 도달했을때 불려지는 함수 정의 - characteristic update [\main.c\timer_timeout_handler()]

 

3.G) timer ID 설정 및 시간 간격 설정 [\main.c]

 

3.H) timer app_timer_create()로 생성 [\main.c\application_timers_init()]

 

3.I) timer app_timer_start()로시작 [\main.c\application_timers_start()]

 

 

 


 

 

부록 - 함수 정보

  • observer

다음과 같이 구성되어 있다.

 

NRF_SDH_BLE_OBSERVER(_name, _prio, _handler, _context)

name: observer의 이름 설정

handler: BLE Stack의 Event가 생기면 handler function이 불러짐 .

context: Event Handler의 인자로 들어간다.

 

 

  • hvx_param의 멤버

handle : 어떤 characteristic value를 다루는지

type: notification (BLE_GATT_HVX_NOTIFICATION)인지 indication(BLE_GATT_HVX_INDICATION)인지

offset: 송신하고 싶은 정보의 byte 수가 많고, 적당한 곳에서 추출하고 싶을 경우

p_len: Softdevice는 송신하는 정보의 바이트 크기를 알아야 한다. 예를 들어 0x01, 0x02, 0x03, 0x04, 0x05 를 BLE를 통해 보내고 싶은데, 3번째와 4번째 바이트만 보내고 싶다면 offset = 2, len = 2 가 된다.

p_data: 실제 보내고자 하는 데이터를 가리키는 포인터

 

 

 

  • app_timer_create(&m_our_char_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);

m_our_char_timer_id : Timer ID

APP_TIMER_MODE_REPEATED : enumeration

timer_timeout_handler : timer event 실행 시 실행되는 함수 

 

 

 

  • app_timer_start(m_our_char_timer_id, OUR_CHAR_TIMER_INTERVAL, NULL);

m_our_char_timer_id : ID Variable : 

timer interval : OUR_CHAR_TIMER_INTERVAL

timer expire 되면 불려지는 함수 - 신경 안쓰기 때문에 NULL

 

 

 

  • advertising_init() 함수

advdata 변수에는 첫 advertising packet을 구성할 때 이용하는 정보가 들어있다. Advertising packet 은 31바이트보다 클 수 없다는 것을 기억해야 한다. Device Name 을 길게하면 글자가 잘리는 이유가 되기 때문이다. ble_advertising_init_t 의 속성 중 하나인 advdata 의 멤버를 원하는 advertising 되는 방식에 맞게 설정해주어야 한다.