ESP32 IDF

ESP32 IDF BLE 서버

임베디드 친구 2024. 11. 5. 17:42
반응형

안녕하세요, '소프트웨어 공장'입니다. 오늘은 ESP32를 이용한 BLE 서버 설정에 대해 이야기해보겠습니다. BLE는 블루투스 저전력(Bluetooth Low Energy)의 약자로, 간단한 데이터 전송이 필요한 다양한 IoT 애플리케이션에서 널리 사용되고 있습니다. ESP32는 BLE 기능을 내장하고 있어 저전력 통신을 구현하기에 매우 적합합니다. 이번 포스팅에서는 ESP32 IDF 환경에서 BLE 서버를 설정하고 간단한 예제를 통해 사용하는 방법을 알아보겠습니다.

BLE 개요

BLE는 블루투스 4.0 이후부터 지원되는 기능으로, 저전력 데이터 전송을 목적으로 합니다. BLE는 기본적으로 중앙(Central)과 주변(Peripheral) 역할로 나뉘어 동작하며, 데이터를 교환할 때는 GATT(Generic Attribute Profile) 프로토콜을 사용합니다. GATT는 데이터를 읽고 쓰는 동작을 규정하며, 각 데이터는 서비스를 통해 노출됩니다. 이번 포스팅에서는 ESP32를 주변 장치(Peripheral)로 설정하여, 다른 BLE 중앙 장치(예: 스마트폰 등)에서 데이터를 읽고 쓸 수 있는 BLE 서버를 구성해보겠습니다.

개발 환경

ESP32 IDF와 VS Code 개발 환경을 사용합니다. 이미 개발 환경이 준비되었다는 가정 하에 바로 BLE 서버 설정 방법을 소개하겠습니다.

BLE 서버 설정하기

ESP32에서 BLE 서버를 설정하기 위해서는 esp-idf의 BLE 라이브러리를 활용합니다. BLE 서버는 기본적으로 서비스(Service)와 특성(Characteristics)을 제공하여 클라이언트가 데이터를 읽고 쓸 수 있도록 합니다.

BLE 서버 구현 예제

아래는 ESP32에서 BLE 서버를 구현하는 예제 코드입니다. 이 예제에서는 BLE 서버를 생성하고, 서비스를 등록하며, 특성을 생성하여 데이터를 교환할 수 있도록 합니다.

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"

#define GATTS_TAG "BLE_SERVER"

// 서비스 UUID 및 특성 UUID 정의
#define SERVICE_UUID        0x00FF
#define CHARACTERISTIC_UUID 0xFF01

static uint8_t char_value[] = {0x00};

// GATT 서버 이벤트 핸들러
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
    switch (event) {
        case ESP_GATTS_REG_EVT:
            ESP_LOGI(GATTS_TAG, "GATT 서버 등록 완료, 서비스 시작");
            esp_ble_gatts_create_service(gatts_if, &service_id, 4);
            break;
        case ESP_GATTS_CREATE_EVT:
            ESP_LOGI(GATTS_TAG, "서비스 생성 완료");
            esp_ble_gatts_start_service(param->create.service_handle);
            esp_ble_gatts_add_char(param->create.service_handle, &char_uuid,
                                   ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                                   ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE,
                                   &char_value, NULL);
            break;
        case ESP_GATTS_ADD_CHAR_EVT:
            ESP_LOGI(GATTS_TAG, "특성 추가 완료");
            break;
        default:
            break;
    }
}

// GAP 이벤트 핸들러
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
    switch (event) {
        case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
            ESP_LOGI(GATTS_TAG, "광고 데이터 설정 완료");
            esp_ble_gap_start_advertising(&adv_params);
            break;
        case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
            if (param->adv_start_cmpl.status == ESP_BT_STATUS_SUCCESS) {
                ESP_LOGI(GATTS_TAG, "광고 시작 성공");
            } else {
                ESP_LOGE(GATTS_TAG, "광고 시작 실패");
            }
            break;
        default:
            break;
    }
}

void app_main() {
    // NVS 초기화
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // BLE 초기화
    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    ESP_ERROR_CHECK(ret);
    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    ESP_ERROR_CHECK(ret);
    ret = esp_bluedroid_init();
    ESP_ERROR_CHECK(ret);
    ret = esp_bluedroid_enable();
    ESP_ERROR_CHECK(ret);

    // GATT 서버 등록
    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(0);
}

코드 설명

위 코드는 BLE 서버를 설정하고 기본적인 서비스를 생성하는 과정입니다. 주요 단계를 살펴보겠습니다.

  1. NVS 초기화: BLE를 사용하기 전에 NVS 플래시를 초기화합니다. 이는 BLE 설정 정보를 저장하는 데 필요합니다.
  2. BLE 컨트롤러 초기화: BLE 모드를 설정하고 블루투스 컨트롤러를 초기화합니다. ESP32는 BLE와 클래식 블루투스를 동시에 지원하기 때문에, BLE 모드만 활성화하는 것이 좋습니다.
  3. GATT 서버 등록: GATT 서버를 등록하고, 이벤트 핸들러를 설정합니다. 이벤트 핸들러는 BLE 서버에서 발생하는 다양한 이벤트(서비스 생성, 특성 추가 등)를 처리합니다.
  4. 서비스와 특성 생성: 서비스와 특성을 생성하여 BLE 클라이언트가 이를 통해 데이터를 교환할 수 있도록 합니다.

주요 이벤트 처리

  • ESP_GATTS_REG_EVT: GATT 서버가 성공적으로 등록되었을 때 호출됩니다. 이 이벤트에서 서비스 생성을 시작합니다.
  • ESP_GATTS_CREATE_EVT: 서비스가 생성되면 호출됩니다. 이 이벤트에서 특성을 추가합니다.
  • ESP_GATTS_ADD_CHAR_EVT: 특성이 추가되면 호출됩니다. 이 특성은 BLE 클라이언트에서 읽고 쓸 수 있는 데이터를 정의합니다.

BLE 서버 테스트하기

BLE 서버를 성공적으로 설정하고 실행했다면, 이제 BLE 클라이언트를 통해 ESP32 BLE 서버에 접속할 수 있습니다. BLE 클라이언트는 스마트폰의 BLE 스캐닝 앱(예: nRF Connect)을 사용하면 쉽게 테스트할 수 있습니다.

  1. 스캔 시작: BLE 클라이언트를 실행하고 주변 장치를 스캔합니다. "ESP_GATTS_DEMO"라는 이름으로 장치가 검색됩니다.
  2. 연결: ESP32에 연결하고, 서비스와 특성을 확인합니다. 특성을 선택하여 값을 읽거나 쓸 수 있습니다.

이 과정을 통해 BLE 서버와 클라이언트 간의 데이터 교환을 실습할 수 있습니다.

마무리

이번 포스팅에서는 ESP32를 이용해 BLE 서버를 설정하는 방법을 살펴보았습니다. ESP32 IDF는 BLE를 매우 쉽게 사용할 수 있는 API를 제공하며, 이를 통해 IoT 장치 간의 저전력 데이터 통신을 구현할 수 있습니다. BLE 서버는 다양한 IoT 애플리케이션에서 활용될 수 있으며, 특히 센서 데이터 전송이나 원격 제어와 같은 시나리오에서 유용합니다.

다음 포스팅에서는 BLE 클라이언트를 구현하여 BLE 서버와의 통신을 더욱 심도 있게 다뤄보겠습니다. BLE에 대해 궁금한 점이 있거나 도움이 필요하신 경우 언제든 댓글로 남겨주세요. 감사합니다!

반응형

'ESP32 IDF' 카테고리의 다른 글

ESP32 IDF FreeRTOS  (0) 2024.11.07
ESP32 IDF BLE 클라이언트  (0) 2024.11.06
ESP32 IDF 웹 서버(Web Server)  (0) 2024.11.04
ESP32 IDF Wi-Fi 기능 살펴보기  (0) 2024.11.03
ESP32 IDF GPIO 핀 구성 및 활용 가이드  (0) 2024.11.02