espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.73k stars 7.3k forks source link

[TW#27416] Range of BLE scanner limited (to under 5m) #2696

Closed SharKCS11 closed 5 years ago

SharKCS11 commented 6 years ago

Hi all, sorry if this is the wrong place to post, but I can't seem to post on ESP32 forums. I'm running an application that uses ESP32 to perform BLE scans for Eddystone UID packets. I'm testing this on an Android phone running the Beacon Simulator app.

It works very well for short distances, but the scanner can't pick up anything past about 4 to 6 meters. Is this expected? I've heard the range of Bluetooth Low Energy can be anywhere from 10-40 meters. If I'm getting such small ranges, is this due to the phone not transmitting properly, or does the receiving antenna just not support this kind of range?

I'm using ESP32 Devkit C by the way, and the datasheet for the SoC it uses is here. The parameters I'm using are as follows:

static esp_ble_scan_params_t ble_scan_params = {
    .scan_type              = BLE_SCAN_TYPE_ACTIVE,
    .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,
    .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
    .scan_interval          = 320,
    .scan_window            = 96,
    .scan_duplicate         = BLE_SCAN_DUPLICATE_DISABLE
};

Thanks in advance!

chegewara commented 6 years ago

If your hardware is well designed and there is no obstacles between 2 peer devices then you can scan in range over 100m. ive been doing tests with devKitC and i am able to achieve this range easy (you can find other issue in this repo about range). Thiss suggests that your devKitC example can be defected or you have some thick wall between devices.

SharKCS11 commented 6 years ago

What is the client you are using? An Android device, or some other antenna? In my case, the Android phone is responsible for broadcasting.

chegewara commented 6 years ago

Yes, i am using android smartphones, but i never been doing tests this way. Ive been testing esp32 broadcasting range and android was scanner.

negativekelvin commented 6 years ago

What did you set the transmission power to in the app?

SharKCS11 commented 6 years ago

The transmission power is set to "Medium: -66dBm" and frequency mode is set to "Balanced - 3Hz" There's also a "TX Power" field in the Eddystone simulator that's set to "-65", but I'm not sure what that field is used for.

negativekelvin commented 6 years ago

It seems like that app has very limited values for transmit power for short range beacons. Did you try another app like dobeacon?

SharKCS11 commented 6 years ago

I have tried a couple apps, but not that one. There were some that didn't support eddystone. I'll give it a shot.

Yulong-espressif commented 6 years ago

@SharKCS11, Can you used other SmartPhone to scan the adv you have sent by the AndroidPhone when the distance is 5~6m, and then record the RSSI value. We want to confirm if it is because the Advertising power of your Android phone is too small, resulting in a shorter ESP32 reception distance.

SharKCS11 commented 5 years ago

My Android phone broadcasts the following: Medium Power (-66dBm), Balanced Frequency Mode (3Hz).

Scanning on another smartphone does not produce reliable RSSI values. It's always stuck between -60dBm and -80dBm, regardless of how far I go.

On the ESP32, the scans are more consistent depending on the parameters set. So about 5-6m away, the obtained RSSI by the ESP is around -92dBm. It will stay around -92dBm until I move about 8m or further and then stop receiving. Less than 1m away, RSSI is -50 to -65dBm. In summary, the RSSI scales well with distance up to ~4m and then just drops off to -80 to -95 and stops scanning.

I'm wondering if the scan parameters have anything to do with this as well. Snippet of my ESP32 code is below:

static esp_ble_scan_params_t ble_scan_params = {
    .scan_type              = BLE_SCAN_TYPE_ACTIVE,
    .own_addr_type          = BLE_ADDR_TYPE_PUBLIC,
    .scan_filter_policy     = BLE_SCAN_FILTER_ALLOW_ALL,
    .scan_interval          = 300,
    .scan_window            = 0x30,
    .scan_duplicate         = BLE_SCAN_DUPLICATE_DISABLE
};
//event handler
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param)
{
    esp_err_t err;

    switch(event)
    {
        case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
            ESP_LOGI(DEMO_TAG, "Scan parameters set.");
            break;
        }
        case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: {
            if((err = param->scan_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(DEMO_TAG,"Scan start failed: %s", esp_err_to_name(err));
            }
            else {
                ESP_LOGI(DEMO_TAG,"Start scanning...");
            }
            break;
        }
        case ESP_GAP_BLE_SCAN_RESULT_EVT: {
            //ESP_LOGI(DEMO_TAG, "****Got result****");
            esp_ble_gap_cb_param_t* scan_result = (esp_ble_gap_cb_param_t*)param;
            switch(scan_result->scan_rst.search_evt)
            {
                case ESP_GAP_SEARCH_INQ_RES_EVT: {
                    esp_eddystone_result_t eddystone_res;
                    memset(&eddystone_res, 0, sizeof(eddystone_res));
                    esp_err_t ret = esp_eddystone_decode(scan_result->scan_rst.ble_adv, scan_result->scan_rst.adv_data_len, &eddystone_res);
                    if (ret) {
                        // error:The received data is not an eddystone frame packet or a correct eddystone frame packet.
                        // just return
                        return;
                    } else {   
                        // The received adv data is a correct eddystone frame packet.
                        // Here, we get the eddystone infomation in eddystone_res, we can use the data in res to do other things.
                        // For example, just print them:
                        ESP_LOGI(DEMO_TAG, "--------Eddystone Found----------");
                        esp_log_buffer_hex("EDDYSTONE_DEMO: Device address:", scan_result->scan_rst.bda, ESP_BD_ADDR_LEN);
                        ESP_LOGI(DEMO_TAG, "RSSI of packet:%d dbm", scan_result->scan_rst.rssi);
                        range_found = scan_result->scan_rst.rssi;
                        esp_eddystone_show_inform(&eddystone_res);
                    }
                    break;
                }
                default:
                    break;
            }
            break;
        }
        case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:{
            if((err = param->scan_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS) {
                ESP_LOGE(DEMO_TAG,"Scan stop failed: %s", esp_err_to_name(err));
            }
            else {
                ESP_LOGI(DEMO_TAG,"Stop scan successfully");
            }
            break;
        }
        default:
            break;
    }
}
/* I also modified ble_show_inform to include http post of the received RSSI */

Thanks!

Yulong-espressif commented 5 years ago

@SharKCS11 Can you change the scan_type from BLE_SCAN_TYPE_ACTIVE to BLE_SCAN_TYPE_PASSIVE and then try again. We want to make sure in the case of only receiving the package, will the same situation occur? Because from your description, when 5~6m, the value of rssi drops to only -95, it will definitely have a great impact on the performance of the collection.

SharKCS11 commented 5 years ago

I changed to BLE_SCAN_TYPE_PASSIVE, and the timing is definitely more reliable now! The RSSI hasn't changed much. I get around -85 when 5~6m away and can go about 8-10m at -90 to -95dBm until it stops scanning.

chegewara commented 5 years ago

I did some test with my samsung S9+ which seats next to devKitC and somewhere in the room is also Mi band 2. For comparison i have also samsung S4 performing scan. Here is result:

I (1037) SampleScan: Found BLE new device!  address: 43:6b:0a:b8:2d:04, RSSI: -54 // <-- samsung S9+ with tx power -7dBm, less than half meter from esp32
I (37192) SampleScan: Found BLE new device!  address: f6:6a:02:2c:b4:2c, RSSI: -90 // <-- mi band 2

Both RSSI values consistent with samsung S4 scan readings.

SharKCS11 commented 5 years ago

I'm closing this issue, since switching to passive scan type is giving good enough range for our application. But let me know if there's anything else I should try, or updates regarding the BLE scan. Thanks for the help.

alviyandi commented 4 years ago

ble scan maximum can scan how much?

gengyuchao commented 4 years ago

This distance is related to the following factors: peer device transmit power, ambient wireless conditions, and receiving sensitivity of the device. So it is hard to say how far it can scan. Due to spec, it may Up to 100m outdoors.

alviyandi commented 4 years ago

i mean, how many device can be scanned using ESP32 BLE feature?

gengyuchao commented 4 years ago

Sorry I got it wrong. Do you need to connect the device? If you just need to scan the advertising package, there is not a limit. But if you want to scan and connect with the device, the number of the max connections is 9.

alviyandi commented 4 years ago

thank you for the information

gengyuchao commented 4 years ago

@alviyandi Although the Controller supports up to 9 links, there are some limitations. Currently, the software supports up to 7 links in Bluedroid. You can config it in the menuconfig.