Page 1 of 1

BLEDevice::setPower has no effect?

Posted: Wed May 19, 2021 9:14 pm
by rbrakhya
Im trying to set the TX power on BLE advertising to +18dbm on a esp32-C3.
Using the provided sample code, BLE_extended_scan and BLE_multi_advertising, i modified it to hopefully only advertise on CODED PHY and flashed two devices, one with each code.
But the settings for the TX power have no effect on the RSSI on either device. I have tried N27 to P18 without any change. The RSSI stays at around -50 at a distance of 1m. I read somwhere that the config is precompiled and tried editing the sdkconfig.h in the
C:\Users\rbrak\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.0-alpha1\tools\sdk\esp32c3\include\config folder and recompile, but this didn´t have any effect either.
What am i missing?

Modified advertiser:

Code: Select all

#include <BLEDevice.h>
#include <BLEAdvertising.h>
uint8_t tx_power;

esp_ble_gap_ext_adv_params_t ext_adv_params_coded = {
    .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE,
    .interval_min = 0x50,
    .interval_max = 0x50,
    .channel_map = ADV_CHNL_ALL,
    .own_addr_type = BLE_ADDR_TYPE_RANDOM,
    .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
    .primary_phy = ESP_BLE_GAP_PHY_CODED,
    .max_skip = 0,
    .secondary_phy = ESP_BLE_GAP_PHY_CODED,
    .sid = 3,
    .scan_req_notif = false,
};


static uint8_t raw_scan_rsp_data_coded[] = {
        0x37, 0x09, 'V', 'E', 'R', 'Y', '_', 'L', 'O', 'N', 'G', '_', 'D', 'E', 'V', 'I', 'C', 'E', '_', 'N', 'A', 'M', 'E', '_',
        'S', 'E', 'N', 'T', '_', 'U', 'S', 'I', 'N', 'G', '_', 'E', 'X', 'T', 'E', 'N', 'D', 'E', 'D', '_', 'A', 'D', 'V', 'E', 'R', 'T', 'I', 'S', 'I', 'N', 'G', 0X0
};

uint8_t addr_coded[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x04};

BLEMultiAdvertising advert(1); // max number of advertisement data 

void setup() {
  Serial.begin(115200);
  Serial.println("Multi-Advertising...");

  BLEDevice::init("CODEServer +18dBm");
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_DEFAULT);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL0);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL1);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL2);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL3);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL4);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL5);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL6);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL7);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL8);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_ADV);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_SCAN);     

  esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING, ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING);

  advert.setAdvertisingParams(0, &ext_adv_params_coded);
  advert.setDuration(0);
  advert.setScanRspData(0, sizeof(raw_scan_rsp_data_coded), &raw_scan_rsp_data_coded[0]);
  advert.setInstanceAddress(0, addr_coded);

  delay(1000);
  advert.start(1, 0);
}

void loop() {
tx_power=esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_DEFAULT);

Serial.println(tx_power);
  delay(2000);
}
Modified scanner:

Code: Select all

#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#warning "Not compatible hardware"
#else 
#include <esp_bt.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

uint32_t scanTime = 100; //In 10ms (1000ms)
BLEScan* pBLEScan;
uint8_t tx_power;

class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks {
    void onResult(esp_ble_gap_ext_adv_reprot_t report) {
      if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){
        // here we can receive regular advertising data from BLE4.x devices
        Serial.println("BLE4.2");
      } else {
        // here we will get extended advertising data that are advertised over data channel by BLE5 divices
        Serial.printf("RSSI: data_le: %d, prim phy: %d \n", report.rssi, report.primary_phy);
        digitalWrite(8,HIGH);
      }
    }
};

void setup() {
  pinMode(8,OUTPUT);
  Serial.begin(115200);
  Serial.println("Scanning...");
  BLEDevice::init("Coded +18dBm");
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_DEFAULT);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL0);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL1);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL2);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL3);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL4);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL5);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL6);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL7);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL8);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_ADV);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_SCAN); 
  esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING, ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING);
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setExtendedScanCallback(new MyBLEExtAdvertisingCallbacks());
  pBLEScan->setExtScanParams(); // use with pre-defined/default values, overloaded function allows to pass parameters
  delay(1000); // it is just for simplicity this example, to let ble stack to set extended scan params
  pBLEScan->startExtScan(scanTime, 3); // scan duration in n * 10ms, period - repeat after n seconds (period >= duration)
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
  digitalWrite(8,LOW);
  tx_power=esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_DEFAULT);
Serial.println(tx_power);

}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED

Re: BLEDevice::setPower has no effect?

Posted: Thu May 20, 2021 5:03 am
by chegewara
Hi,
nice to see you find BLE5 features in arduino useful.

For extended advertising you have to set TX power in esp_ble_gap_ext_adv_params_t struct (which was omitted in examples).
https://docs.espressif.com/projects/esp ... v_params_t

Also you may need to use custom gap handler in client app:
https://github.com/espressif/arduino-es ... vice.h#L61
to get ESP_GAP_BLE_PERIODIC_ADV_REPORT_EVT event, because in library it is not fully implemented, and from it read RSSI:
https://docs.espressif.com/projects/esp ... v_report_t

Re: BLEDevice::setPower has no effect?

Posted: Sat May 29, 2021 8:53 pm
by rbrakhya
Thanks!
Amazing performance! Was able to scan advertisements at +18dBm at a distance of 2.7km LOS! :o

Re: BLEDevice::setPower has no effect?

Posted: Sun May 30, 2021 8:42 am
by chegewara
rbrakhya wrote:
Sat May 29, 2021 8:53 pm
Thanks!
Amazing performance! Was able to scan advertisements at +18dBm at a distance of 2.7km LOS! :o
It is mind blowing. In theory range with coded phy is about 1000 m.
Could you tell us more how did you achieve this? I mean with devkit modules or custom device, antennas etc.

Re: BLEDevice::setPower has no effect?

Posted: Tue Jun 01, 2021 7:38 pm
by rbrakhya
Probably i am missing something, but my aim was to check at what range two ESP32-C3-DevkitM-1 with the pcb trace antenna could scan an advertisement. I started with the examples. I just had the modules and usb power sources with me, so i could not check any serial data, i used an led to indicate the detection of a device advertising over the data channels. This means that it should detect any advertisment, not only from my device. We did however turn on and off the advertiser several times to check that it was indeed the advertisment from our advertiser that had been detected. Can the data be garbled and still seen as an advertisement? We tried over an ever longer distance of about 3.2km LOS and then we only detetcted maybe 1/10 advertisements.
Did i misunderstand everything totally? :oops:


Advertiser:

Code: Select all

#include <BLEDevice.h>
#include <BLEAdvertising.h>
uint8_t read_TX_power;

esp_ble_gap_ext_adv_params_t ext_adv_params_coded = {
    .type = ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE,
    .interval_min = 0xC8,
    .interval_max = 0xC8,
    .channel_map = ADV_CHNL_ALL,
    .own_addr_type = BLE_ADDR_TYPE_RANDOM,
    .filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
    .tx_power=18,
    .primary_phy = ESP_BLE_GAP_PHY_CODED,
    .max_skip = 0,
    .secondary_phy = ESP_BLE_GAP_PHY_CODED,
    .sid = 3,
    .scan_req_notif = false,
};


static uint8_t raw_scan_rsp_data_coded[] = {
        0x37, 0x09, 'V', 'E', 'R', 'Y', '_', 'L', 'O', 'N', 'G', '_', 'D', 'E', 'V', 'I', 'C', 'E', '_', 'N', 'A', 'M', 'E', '_',
        'S', 'E', 'N', 'T', '_', 'U', 'S', 'I', 'N', 'G', '_', 'E', 'X', 'T', 'E', 'N', 'D', 'E', 'D', '_', 'A', 'D', 'V', 'E', 'R', 'T', 'I', 'S', 'I', 'N', 'G', 0X0
};

uint8_t addr_coded[6] = {0xc0, 0xde, 0x52, 0x00, 0x00, 0x04};

BLEMultiAdvertising advert(1); // max number of advertisement data 

void setup() {
  BLEDevice::init("CODEServer +18dBm");
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_DEFAULT);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL0);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL1);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL2);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL3);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL4);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL5);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL6);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL7);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL8);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_ADV);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_SCAN);     

  esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING, ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING);

  advert.setAdvertisingParams(0, &ext_adv_params_coded);
  advert.setDuration(0);
  advert.setScanRspData(0, sizeof(raw_scan_rsp_data_coded), &raw_scan_rsp_data_coded[0]);
  advert.setInstanceAddress(0, addr_coded);

  
  advert.start(1, 0);
  delay(1000);
}

void loop() {
}
Scanner:

Code: Select all

#ifndef CONFIG_BT_BLE_50_FEATURES_SUPPORTED
#warning "Not compatible hardware"
#else 
#include <esp_bt.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

uint32_t scanTime = 20; //In 10ms (1000ms)
BLEScan* pBLEScan;
uint8_t tx_power;
gap_event_handler handler;
esp_ble_gap_periodic_adv_report_t periodic_adv_report;
long scantimer;

// * @brief periodic adv report parameters
// */
// typedef struct {
//     uint16_t sync_handle;                          /*!< periodic advertising train handle */
//     uint8_t tx_power;                              /*!< periodic advertising tx power*/
//     int8_t rssi;                                   /*!< periodic advertising rssi */
//     esp_ble_gap_ext_adv_data_status_t data_status; /*!< periodic advertising data type*/
//     uint8_t data_length;                           /*!< periodic advertising data length */
//     uint8_t data[251];                             /*!< periodic advertising data */
// } esp_ble_gap_periodic_adv_report_t;

// /**


void onResult(esp_ble_gap_periodic_adv_report_t periodic_adv_report){
tx_power=periodic_adv_report.rssi;
};

class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks {
    void onResult(esp_ble_gap_ext_adv_reprot_t report) {
      if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){
        // here we can receive regular advertising data from BLE4.x devices
        Serial.println("BLE4.2");
      } else {
        // here we will get extended advertising data that are advertised over data channel by BLE5 divices
        Serial.printf("RSSI: data_le: %d, prim phy: %d \n", report.rssi, report.primary_phy);
        digitalWrite(8,HIGH);
      }
    }
};

void setup() {
  pinMode(8,OUTPUT);
 // Serial.begin(115200);
 // Serial.println("Scanning...");
  BLEDevice::init("Coded +18dBm");
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_DEFAULT);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL0);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL1);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL2);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL3);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL4);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL5);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL6);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL7);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL8);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_ADV);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_SCAN); 
  esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING, ESP_BLE_GAP_PHY_OPTIONS_PREF_S8_CODING);
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setExtendedScanCallback(new MyBLEExtAdvertisingCallbacks());
  pBLEScan->setExtScanParams(); // use with pre-defined/default values, overloaded function allows to pass parameters
  delay(20); // it is just for simplicity this example, to let ble stack to set extended scan params
  pBLEScan->startExtScan(scanTime, 1); // scan duration in n * 10ms, period - repeat after n seconds (period >= duration)
 BLEDevice::setCustomGapHandler( handler);
}

void loop() {
if (millis()>scantimer+70){
 digitalWrite(8,LOW);
 scantimer=millis();
}
}
#endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED

Re: BLEDevice::setPower has no effect?

Posted: Wed Jun 02, 2021 10:46 am
by chegewara
It is most likely there is no other BLE5 devices advertising around you, so you are receiving only esp32 C3.
There is few things you can do:
1) you dont need this code at all, it is BLE4 code:

Code: Select all

  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_DEFAULT);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL0);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL1);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL2);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL3);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL4);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL5);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL6);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL7);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_CONN_HDL8);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_ADV);
  BLEDevice::setPower(ESP_PWR_LVL_P18, ESP_BLE_PWR_TYPE_SCAN);     
2) you can add OLED like SSD1306 or similar, or
3) you can filter adv data by addr in callback and control LED only when you receive from other C3:

Code: Select all

class MyBLEExtAdvertisingCallbacks: public BLEExtAdvertisingCallbacks {
    void onResult(esp_ble_gap_ext_adv_reprot_t report) {
      if(report.event_type & ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY){
        // here we can receive regular advertising data from BLE4.x devices
        Serial.println("BLE4.2");
      } else {
        // here we will get extended advertising data that are advertised over data channel by BLE5 divices
        Serial.printf("RSSI: data_le: %d, prim phy: %d \n", report.rssi, report.primary_phy);
        https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/bluetooth/esp_gap_ble.html#_CPPv428esp_ble_gap_ext_adv_reprot_t
        digitalWrite(8,HIGH);
      }
    }
};
https://docs.espressif.com/projects/esp ... v_reprot_t

Re: BLEDevice::setPower has no effect?

Posted: Wed Dec 15, 2021 7:44 pm
by iamcalledusman
Hi All!

Thank you for the nice post. It's very helpful. I was facing the same issue that in startup RSSI was equal to -51. But when I read the post by @rbrakhya. Made changes and was able to get the RSSI equal to -31 which is good.

One question, if you can help me. When I tested the range test it was only 30 meters. The test was not LOS. There were two concrete walls between Tx and Rx. Can you please show me your RSSI ? and will it work if I test it LOS. Sorry, I was unable to test it LOS condition. Is there anything I was missing? I exactly followed your instructions and as a result, RSSI changed.

Thanks in Advance.

Re: BLEDevice::setPower has no effect?

Posted: Thu Dec 16, 2021 6:47 pm
by iamcalledusman
Hi All!

Today I again tested the Coded Phy Range test. @3dbm range was 141 meters and @18dbm it goes to 404 meters. It was still receiving the beacons but reception frequency goes down means it started missing the beacons. I can go further but am unable to do so because of the closed-end street. I believe it will work from 800 to 1000 meters range.

Thank you!

Re: BLEDevice::setPower has no effect?

Posted: Thu Apr 27, 2023 7:43 am
by stevasway
Hi all,
I didn't understand what is the final solution to set +18dBm. Can you explain me?
Thanks
Stevasway