In the previous posts you learned how to use the esp32 chip to receive and parse the advertising packets transmitted by BLE peripherals. As a practical example, I developed a program to detect the presence of a particular iBeacon and activate an output accordingly.
In today’s tutorial, you’ll learn how to transmit advertising packets instead.
Advertising process
You’ve already discovered that the Bluetooth driver included in the esp-idf stack is executed in a dedicated thread. Whenever the driver needs to send a notification to your program, it calls a callback function indicating which event has triggered.
The advertising process is very simple:
- the program configures the data to be transmitted with esp_ble_gap_config_adv_data()
- the driver reports that it has finished the configuration with the event ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
- the program can now start the advertising process with esp_ble_gap_start_advertising()
- the driver reports that the process has started with the event ESP_GAP_BLE_ADV_START_COMPLETE_EVT
Advertising DATA
It’s possible to tell the driver which data to include in the advertising packet with the following command:
esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data); |
The command accepts as parameter a pointer to an esp_ble_adv_data_t struct:
The meaning of the different fields is explained in the Supplement to the Bluetooth Core Specification document.
First let’s find out how to transmit the device name. You have to use the esp_ble_gap_set_device_name() function to pass the name to the driver and set the field include_name to true in the struct:
static esp_ble_adv_data_t adv_data = { .include_name = true, }; [...] ESP_ERROR_CHECK(esp_ble_gap_set_device_name("ESP32_BLE")); ESP_ERROR_CHECK(esp_ble_gap_config_adv_data(&adv_data)); |
Using the flags, you can publish some features of your device. The available constants are:
you can combine them with the OR operator. If, for example, you want to tell the world that your device is limited discoverable (i.e. it sends the advertising packets only for a limited time, usually 30 seconds) and that it doesn’t support classic Bluetooth (BR/EDR, Basic Rate/Enhanced Data Rate) you’ll write:
static esp_ble_adv_data_t adv_data = { .flag = ESP_BLE_ADV_FLAG_LIMIT_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT, }; |
Advertising PARAMETERS
After configuring the content of the advertising packet, you have also to tell the driver how to send the packet.
The command:
esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params); |
accepts as parameter an esp_ble_adv_params_t struct:
You can configure the minimum and maximum transmission interval of the packet. The two parameters can assume a value from 0x20 to 0x4000. To calculate the interval in milliseconds, the value specified must be multiplied for 0.625. This means that the minimum value (0x20) corresponds to an interval of 12.5ms.
The esp_gap_ble_api.h file lists the constants that can be used for the other parameters (esp_ble_adv_type_t, esp_ble_addr_type_t …).
For example, let’s configure the advertising process as it follows:
[checklist]
- minimum transmission interval: 0x20, maximum: 0x40
- non connectable device (it doesn’t accept incoming connections and only sends data in broadcast)
- public MAC address
- transmission on all the 3 channels dedicated to advertising packets
- no filter on devices who can perform a scan or connect
[/checklist]
static esp_ble_adv_params_t ble_adv_params = { .adv_int_min = 0x20, .adv_int_max = 0x40, .adv_type = ADV_TYPE_NONCONN_IND, .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; [...] esp_ble_gap_start_advertising(&ble_adv_params); |
Demo
I prepared a program that includes what explained above. The source code is available in my Github repository.
Here’s how it works:
Hey there, Luca
thanks for all of these tutorials
they are quite useful!
I just noticed that minimum advertising interval you calculated is actually wrong.
0x20*0.625 = 32*0.625 = 20ms
Not a big deal but may lead to errors.
Thanks again!
Karlo, thanks for your comment!
Hello Luca,
First of all thanks to you for your great effort. Very nice and useful tutorial. I am eagerly waiting for more tutorial from you.
My best regards.
Asish