Skip to content

Conversation

@thekurtovic
Copy link
Collaborator

@thekurtovic thekurtovic commented Nov 15, 2024

  • Revert NimBLEDevice::setPower to take esp_power_level_t.
    • Fixes examples which set tx power.
    • Avoids limiting valid power levels, using the datatype ensures valid input option.
    • Since preprocessor was used inside function, separate implementations for ESP and non-ESP platforms at compile-time.
  • Added NimBLEDevice::getPowerLevel for ESP platform to get esp_power_level_t return value.
  • NimBLEDevice::getPower support full power range based on IDF version.

@h2zero
Copy link
Owner

h2zero commented Nov 16, 2024

This is nice but I was trying to remove as much espressif specific functions/types as I could so it's seamless with other devices/oses.

@thekurtovic
Copy link
Collaborator Author

I see. What about just making the functions do nothing for ESP and emit a warning for the application to use esp_ble_tx_power_set/esp_ble_tx_power_get directly?

@h2zero
Copy link
Owner

h2zero commented Nov 16, 2024

That's also a possibility but I think the controller command might work with the newer esp32 chips, need to test.

@thekurtovic
Copy link
Collaborator Author

Closing due to excessive platform specific handling.

@h2zero
Copy link
Owner

h2zero commented Nov 30, 2024

Too soon, I will do something with this :)

@h2zero
Copy link
Owner

h2zero commented Nov 30, 2024

I think this could work, the only request I would make is to have the values specified in dbm, which is what NimBLE natively works with. Just need to remove the esp_power_level_t references and add conversions from dbm back and forth to esp_power_level_t.

It's unfortunate that Bluetooth never specified a standard for this. Unfortunately espressif decided on a quite stage way to go about it as well.

@h2zero h2zero reopened this Nov 30, 2024
@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

@thekurtovic I have added a commit and rebased to master, please take a look when you can.

@thekurtovic
Copy link
Collaborator Author

thekurtovic commented Dec 2, 2024

Would something like this make sense for the repo? If other platforms are supported in the future which require specific handling for power this could get ugly. This cleans up the code within NimBLEDevice regarding TX power, and moves the platform specific stuff into their own headers. Created a single function for handling ESP32 conversion, which should be easier to maintain.
Not sure if it would require another option within the menuconfig to select the platform.
6b90d6c

@thekurtovic I have added a commit and rebased to master, please take a look when you can.

It doesn't fulfil the goal of the PR. There are edge cases where some chips do not follow the pattern of incrementing by 3. Most notably it appears that going forward all chips max out at 20 dbm, while 21 has become deprecated.

Edit: Wait I think I misunderstood what the code was doing. The 20 vs 21 problem should be avoided since it would cast into the same value. Also the ESP32-H2 enums get mapped into a shared values so they should be okay too.

return -127; // CONFIG_IDF_TARGET_ESP32P4 does not support esp_ble_tx_power_get
# endif

int pwr = esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_DEFAULT);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check if power is invalid here, otherwise a large value like 741 will be returned when equal to ESP_PWR_LVL_INVALID.
Would it make sense to return -127 in this case?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory the current power level should never be invalid I though think, also ESP_PWR_LVL_INVALID isn't defined for all chips/idf versions.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

Edit: Wait I think I misunderstood what the code was doing. The 20 vs 21 problem should be avoided since it would cast into the same value. Also the ESP32-H2 enums get mapped into a shared values so they should be okay too.

We could add a check for this, 20dbm is actually the max allowed by BLE specs so that's safe 😄

@thekurtovic
Copy link
Collaborator Author

thekurtovic commented Dec 2, 2024

Okay spent a bit more time looking at the changes, I didn't notice you added methods for setting power level for esp32.
The calculation for dbm to power level will not give the expected value under some combinations of input value, chip, and IDF version, but overall it will cover almost all cases and the user can always just set the power level using the enum instead.
LGTM, tested on esp32-s3.

This isn't related to the PR but are you able to get a valid reading on an esp32's power level? I get 0xFF anytime the value is read, so I can't properly test the getPower methods. There's no error when setting the power so I assume it's fine. The last time I remember being able to read the power level was in IDF 4.4.x, currently it doesn't matter if I check at initialization or when a client is connected, always get 0xFF.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

The calculation for dbm to power level will not give the expected value under some combinations of input value, chip, and IDF version

I'm curious if you have any examples? I know there are a couple settings out there that were not multiples of 3 but they are deprecated.

Just tested this on an esp32 with

    NimBLEDevice::setPower(-12);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(-9);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(-6);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(-3);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(0);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(3);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(6);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(9);
    printf("Power level: %d\n", NimBLEDevice::getPower());
    NimBLEDevice::setPower(12);
    printf("Power level: %d\n", NimBLEDevice::getPower());

And the output:

Power level: -12
Power level: -9
Power level: -6
Power level: -3
Power level: 0
Power level: 3
Power level: 6
Power level: 9
E (867) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

Some interesting results:

E (877) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -30
E (877) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -29
E (877) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -28
E (887) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -27
E (897) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -26
E (907) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -25
E (917) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -24
E (917) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -23
E (927) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -22
E (937) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -21
E (947) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -20
E (957) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -19
E (967) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -18
E (967) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -17
E (977) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -16
E (987) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested -15
Power level: -12, requested -14
Power level: -12, requested -13
Power level: -12, requested -12
Power level: -9, requested -11
Power level: -9, requested -10
Power level: -9, requested -9
Power level: -6, requested -8
Power level: -6, requested -7
Power level: -6, requested -6
Power level: -3, requested -5
Power level: -3, requested -4
Power level: -3, requested -3
Power level: 0, requested -2
Power level: 0, requested -1
Power level: 0, requested 0
Power level: 0, requested 1
Power level: 3, requested 2
Power level: 3, requested 3
Power level: 3, requested 4
Power level: 6, requested 5
Power level: 6, requested 6
Power level: 6, requested 7
Power level: 9, requested 8
Power level: 9, requested 9
Power level: 9, requested 10
E (1057) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 11
E (1067) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 12
E (1077) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 13
E (1087) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 14
E (1097) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 15
E (1097) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 16
E (1107) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 17
E (1117) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 18
E (1127) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 19
E (1137) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 20
E (1147) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 21
E (1147) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 22
E (1157) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 23
E (1167) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 24
E (1177) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 25
E (1187) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 26
E (1187) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 27
E (1197) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 28
E (1207) NimBLEDevice: esp_ble_tx_power_set: rc=258
Power level: 9, requested 29

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

And on the C6:

E (469) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -30
E (479) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -29
E (489) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -28
E (489) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -27
E (499) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -26
E (509) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -25
E (519) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -24
E (529) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -23
E (539) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -22
E (539) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -21
E (549) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -20
E (559) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -19
E (569) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 9, requested -18
Power level: -15, requested -17
Power level: -15, requested -16
Power level: -15, requested -15
Power level: -12, requested -14
Power level: -12, requested -13
Power level: -12, requested -12
Power level: -9, requested -11
Power level: -9, requested -10
Power level: -9, requested -9
Power level: -6, requested -8
Power level: -6, requested -7
Power level: -6, requested -6
Power level: -3, requested -5
Power level: -3, requested -4
Power level: -3, requested -3
Power level: 0, requested -2
Power level: 0, requested -1
Power level: 0, requested 0
Power level: 0, requested 1
Power level: 3, requested 2
Power level: 3, requested 3
Power level: 3, requested 4
Power level: 6, requested 5
Power level: 6, requested 6
Power level: 6, requested 7
Power level: 9, requested 8
Power level: 9, requested 9
Power level: 9, requested 10
Power level: 12, requested 11
Power level: 12, requested 12
Power level: 12, requested 13
Power level: 15, requested 14
Power level: 15, requested 15
Power level: 15, requested 16
Power level: 18, requested 17
Power level: 18, requested 18
Power level: 18, requested 19
Power level: 21, requested 20
Power level: 21, requested 21
Power level: 21, requested 22
E (679) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 23
E (689) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 24
E (699) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 25
E (709) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 26
E (709) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 27
E (719) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 28
E (729) NimBLEDevice: esp_ble_tx_power_set: rc=-1
Power level: 21, requested 29

Seems like all the devices start at 9dbm, interesting that the C6 actually goes to 21dbm and not capped at 20.
Edit: my bad, didn't set a max on the return value of getPower, fixed now.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

I've added the powerType parameters to set/getPowerLevel just in case anyone wants to use them.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

This isn't related to the PR but are you able to get a valid reading on an esp32's power level? I get 0xFF anytime the value is read, so I can't properly test the getPower methods. There's no error when setting the power so I assume it's fine. The last time I remember being able to read the power level was in IDF 4.4.x, currently it doesn't matter if I check at initialization or when a client is connected, always get 0xFF.

Looks like the is a bug with the esp32s3, seems to work well with other versions.

* Add powerType parameter to getPowerLevel and setPowerLevel.
@h2zero h2zero merged commit 6c85cfa into h2zero:master Dec 2, 2024
58 checks passed
@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

Aaaand just like that I found the problem with the esp32s3 right after merging this lol.

@thekurtovic if we call esp_ble_tx_power_get_enhanced(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); instead of esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_DEFAULT); the esp32s3 will return the expected value.

@thekurtovic
Copy link
Collaborator Author

I'm curious if you have any examples? I know there are a couple settings out there that were not multiples of 3 but they are deprecated.

20 dbm was the main concern, but I see you've addressed it. Other than that I think only esp32-h2 could get an incorrect value if on IDF 5.1.0-5.1.1 and trying to use 16,17, or 19; though the values are now deprecated and round up to 18 and 20 now.

CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL defaults to P9 so that makes sense regarding the start value.

if we call esp_ble_tx_power_get_enhanced(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); instead of esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_DEFAULT); the esp32s3 will return the expected value.

Interesting, good find.
I wonder if the enhanced functions can be used in place of the standard ones for all variants of esp32.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

I wonder if the enhanced functions can be used in place of the standard ones for all variants of esp32.

Sadly not but I also found that the same result is achieved by calling esp_ble_tx_power_get(**ESP_BLE_PWR_TYPE_CONN_HDL3**); As the lower level call gets the same value that way. I will PR the proper fix upstream but this will need to be worked around here regardless.

@h2zero
Copy link
Owner

h2zero commented Dec 2, 2024

Looks like this was fixed upstream for v5.4. espressif/esp-idf@4108a5c

@h2zero
Copy link
Owner

h2zero commented Dec 3, 2024

@thekurtovic What idf version are you on? Looks like the only version with this issue that has been release is 5.2.3. 5.2.2 and 5.3 don't have the "enchanced" function that broke this.

@thekurtovic
Copy link
Collaborator Author

Thanks for looking into it.
5.1.4.241008, according to version.txt. I tried esp_ble_tx_power_get_enhanced out on esp32-s3 and it works for me.
I'll check if 5.3 is any different.

@h2zero
Copy link
Owner

h2zero commented Dec 3, 2024

Interesting, I had a look and that commit you're using is not released, the actual 5.1.4 release does not contain the offending code. If you update the commit to fddbca1 it contains the fix.

@thekurtovic
Copy link
Collaborator Author

I'll give it a try, though planning on migrating over to 5.3 sometime soon.

I forgot to mention this earlier but esp_ble_tx_power_get can supposedly return a negative value. Should a check be added for this and return 0xFF to indicate error?
https://github.com/espressif/esp-idf/blob/master/components/bt/include/esp32c3/include/esp_bt.h#L503-L509

@h2zero
Copy link
Owner

h2zero commented Dec 3, 2024

@thekurtovic I have updated the PR to check for this as well.

@thekurtovic thekurtovic deleted the fix-tx-power branch December 4, 2024 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants