h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
700 stars 145 forks source link

NRF5240 DK CODED_PHY with ESP32 #581

Closed j45p41 closed 4 months ago

j45p41 commented 1 year ago

Discussed in https://github.com/h2zero/NimBLE-Arduino/discussions/580

Originally posted by **j45p41** August 14, 2023 Hi, I have been able to achieve CODED_PHY connection between two ESP32 devices but can't seem to find a way to setup NRF52840_DK as a server sending CODED_PHY. I'm using the NimBLE_Server example but don't understand what I need to add to get the device to advertise with CODED_PHY. I believe the parameters in the nimcong.h file only relevant to esp32. Any guidance will be very much appreciated.
h2zero commented 1 year ago

Please see the examples in the nimble-arduino library for BT5. You will need to enable extended advertising in the config.

j45p41 commented 1 year ago

Hi but this example is for the ESP32 and not the NRF52, when I enable extended advertising in nimconfig.h it say it's only for ESP32. I am reading this wrong? Thanks for your help!

it says:

/****

h2zero commented 1 year ago

That note can be safely ignored for you use, it will be removed later.

j45p41 commented 12 months ago

Hi h2zero,

so to be clear I have this setup:

  1. ESP32-S3 running Bluetooth 5 client example with service and charateristc IDs shared with Server.
  2. When I use NimBLE_Server.ino to connect to this device it connects but not over over coded PHY. I say this because when I use the ESP-32 Bluetooth 5 server example I get the following message:
"Extended Advertising Demo.\r\n"
                                                                "Extended advertising allows for "
                                                                "251 bytes of data in a single advertisement,\r\n"
                                                                "or up to 1650 bytes with chaining.\r\n"
                                                                "This example message is 226 bytes long "
                                                                "and is using CODED_PHY for long range."

but I don't get this with the NRF52 code.

  1. Should I just expect the NR52 to connect to ESP32-Client with coded PHY (eg it only needs to be specified at the client side) or do I need to specify this is the code for the client? As you stated above I should use the ESP32 server example on the NRF52 but this does not seem to compile when I set #define CONFIG_BT_NIMBLE_EXT_ADV 1 in nimconfig.h.

Sorry, been struggling with this for a while, so any help would be of great use! Even better if I could just understand what needs to be specified at the server on the NRF52 to enable then that would be very helpful indeed.

Thanks once again for an excellent library.

h2zero commented 11 months ago

Sorry, been busy with work. Admittedly I haven't tried the extended advertising on the nrf52 yet, I'll see if I can test this this week.

j45p41 commented 11 months ago

Thank you very much indeed. I try and compile but it doesn't when I remove the esp32 related content.

j45p41 commented 11 months ago

Hi,

did you get a chance to test? sorry just chasing because this is one of the final steps before I send my project out for test. I will try myself in the meanwhile and update if I have any success. Thanks again!

j45p41 commented 11 months ago

Here is the output I get when I use the multi advertising example:

`Processing nrf52840_dk_adafruit (platform: https://github.com/h2zero/platform-n-able.git#1.0.0; board: nrf52840_DK; framework: arduino)

Verbose mode can be enabled via -v, --verbose option CONFIGURATION: https://docs.platformio.org/page/boards/n-able/nrf52840_DK.html PLATFORM: n-able (1.0.0+sha.fee3577) > Nordic nRF52840 DK (PCA10056) HARDWARE: NRF52840_XXAA 64MHz, 256KB RAM, 1008KB Flash DEBUG: Current (jlink) On-board (cmsis-dap, jlink) External (blackmagic, stlink) PACKAGES:

j45p41 commented 11 months ago

Also here is the output I get (a bit shorter!) when using just the extended server on the nrtf52 with esp32 sleep commented out.

`Processing nrf52840_dk_adafruit (platform: https://github.com/h2zero/platform-n-able.git#1.0.0; board: nrf52840_DK; framework: arduino)

Verbose mode can be enabled via -v, --verbose option CONFIGURATION: https://docs.platformio.org/page/boards/n-able/nrf52840_DK.html PLATFORM: n-able (1.0.0+sha.fee3577) > Nordic nRF52840 DK (PCA10056) HARDWARE: NRF52840_XXAA 64MHz, 256KB RAM, 1008KB Flash DEBUG: Current (jlink) On-board (cmsis-dap, jlink) External (blackmagic, stlink) PACKAGES:

nunomiguelferreira commented 11 months ago

Same thing happened to me, it seems it cannot load the ble functions (trying to load from the ESP32 library?)

Would like to get NRF52 working with coded PHY if possible

j45p41 commented 11 months ago

HI @h2zero - delighted to see that you are looking into this.

I have done a bit of research in the background and found that:

https://github.com/tjpetz/Coded-Advertiser/blob/main/main.cpp

seems to work for coded_phy but it is based on Mbed :(. However when I run the example your esp32 BT5 client example detects the coded_phy device. Just thought I would put it out there incase it helps!

h2zero commented 10 months ago

@j45p41 @nunomiguelferreira I'm not sure what is going on with your environments. I have tested with the following and is compiling just fine.

[env:nrf52840_dk]
platform = https://github.com/h2zero/platform-n-able.git#1.0.0
board = nrf52840_dk
framework = arduino
platform_packages = framework-n-able @ https://github.com/h2zero/n-able-Arduino
lib_deps = h2zero/NimBLE-Arduino
build_flags =
 '-DCONFIG_NIMBLE_CPP_LOG_LEVEL=3'
 '-DCONFIG_BT_NIMBLE_EXT_ADV=1'

With this code (multi advertiser): ext_adv_nrf.txt

j45p41 commented 10 months ago

Hi @h2zero,

really appreciate you looking into this. I can confirm that it now compiles. However I get tis in the console:

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
E NimBLEExtAdvertising: Advertising config error: rc = 530
Failed to register advertisment data

I also can't see the device on nrfConnect or ESP32.

h2zero commented 10 months ago

@j45p41 that return code is odd.

0x0212 0x12 BLE_ERR_INV_HCI_CMD_PARMS Invalid HCI Command Parameters

I need more info and and possibly an example code to resolve this.

j45p41 commented 10 months ago

hi @h2zero I used the code and platform.ini you posed in the reply. I am using nrf52840 DK. Let me know if there is any other info that would be useful. Thanks!

j45p41 commented 8 months ago

HI @h2zero - Can you pls let me know how we can troubleshoot this. I used the example code you sent me with requested debug level - will really help if I can get the nrf52840 working with coded-PHY. Do you have any code that you have tested?

j45p41 commented 7 months ago

Hi, any help would really be appreciated:)

h2zero commented 7 months ago

Hi @j45p41, I have pushed some changes to the n-able core that should have fixed this. Please try that out.

j45p41 commented 7 months ago

Hi,

@h2zero thank you very much indeed.

I have used the following platformio.ini:

[env:nrf52840_dk]
platform = https://github.com/h2zero/platform-n-able.git#1.0.0
board = nrf52840_dk
framework = arduino
platform_packages = framework-n-able @ https://github.com/h2zero/n-able-Arduino
monitor_speed = 115200
monitor_port = /dev/cu.usbmodem0010502223231 
upload_protocol = jlink

build_flags =
    -D USE_LFRC
    '-DCONFIG_NIMBLE_CPP_LOG_LEVEL=3'
    '-DCONFIG_BT_NIMBLE_EXT_ADV=1'

lib_deps =
    h2zero/NimBLE-Arduino@^1.4.1

and the code you provided.

I am still getting same serial output:


Failed to register advertisment data
�I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
E NimBLEExtAdvertising: Advertising config error: rc = 530

I did platform clean before compiling. Do I need to do anything else to pull in your new changes?

h2zero commented 7 months ago

That should work, it's likely using a cached version of the core.

h2zero commented 7 months ago

I just tested here, if you delete the .platformio/packages/framework-n-able-arduino folder and .platformio/.cache folder it should pull the repo and you'll see the commit ID in the log.

j45p41 commented 7 months ago

Hi @h2zero that works! I can't believe after 7 months it's finally working! Thank you very much for your help!

If I can get a bit more range than the legacy BT in an indoor environment then this will really help our project.

Is it possible to:

  1. switch between the two data schemes? S=2 512 kbps and S=8 125kbps?
  2. Set power level to 8dbm.

Thanks Again!

h2zero commented 7 months ago

Glad to hear, sorry it took so long, wasn't easy to find the issue.

  1. Yes you can change the PHY settings before connecting/advertising etc.
  2. NimBLEDevice::setPower(8); should do it.

You're very welcome 😄

j45p41 commented 7 months ago

It all in good time!

so after adapting the project last night and with your comments above here is my experience.

  1. Extended advertising is now working on both sides ESP32 and NRF52840. I know this because I am getting extended service data.
  2. The performance seems to be the same as BLE4 - I have two devices, one within range and one just outside of range. After implementing CODED_PHY I do not experience an increase or decrease in range.
  3. I have tried using the following:
/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED_S8;

/* Secondary PHY used for advertising and connecting,
 * can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
 */
static uint8_t secondaryPhy = BLE_HCI_LE_PHY_CODED_S2;

However I am getting the following message (all ok when using BLE_HCI_LE_PHY_CODED).

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
D NimBLEServer: >> createService - 0xabcd
D NimBLEServer: << createService
D NimBLEService: << Adding a duplicate characteristic with UUID: 0x1234
D NimBLEService: >> start(): Starting service: UUID: 0xabcd, handle: 0xffff
D NimBLEService: Adding 2 characteristics for service UUID: 0xabcd, handle: 0xffff
D NimBLEService: << start()
primary service
           uuid 0x1800
         handle 1
     end_handle 5
characteristic
                         uuid 0x2a00
     def_handle 2
     val_handle 3
   min_key_size 0
          flags [READ]
characteristic
                         uuid 0x2a01
     def_handle 4
     val_handle 5
   min_key_size 0
          flags [READ]
primary service
           uuid 0x1801
         handle 6
     end_handle 9
characteristic
                         uuid 0x2a05
     def_handle 7
     val_handle 8
   min_key_size 0
          flags [INDICATE]
ccc descriptor
                         uuid 0x2902
         handle 9
   min_key_size 0
          flags [READ|WRITE]
primary service
           uuid 0xabcd
         handle 10
     end_handle 16
characteristic
                         uuid 0x1234
     def_handle 11
     val_handle 12
   min_key_size 0
          flags [READ|WRITE|NOTIFY]
ccc descriptor
                         uuid 0x2902
         handle 13
   min_key_size 0
          flags [READ|WRITE]
characteristic
                         uuid 0x1234
     def_handle 14
     val_handle 15
   min_key_size 0
          flags [READ|WRITE|NOTIFY]
ccc descriptor
                         uuid 0x2902
         handle 16
   min_key_size 0
          flags [READ|WRITE]
E NimBLEExtAdvertising: Advertising config error: rc = 530
Failed to register advertisment data
h2zero commented 7 months ago

The macros BLE_HCI_LE_PHY_CODED_S2 and BLE_HCI_LE_PHY_CODED_S8are invalid, thus the return code of 530.

j45p41 commented 7 months ago

The macros BLE_HCI_LE_PHY_CODED_S2 and BLE_HCI_LE_PHY_CODED_S8are invalid, thus the return code of 530.

Ok. How do I enable s2 or s8 modes?

j45p41 commented 7 months ago

Hi @h2zero - first of all thanks for all your help. I managed to get what I wanted out of it.

Referring to: https://github.com/h2zero/NimBLE-Arduino/issues/599

'-DMYNEWT_VAL_BLE_LL_TX_PWR_DBM=4'
'-DMYNEWT_VAL_BLE_LL_RX_PWR_DBM=4'

and now the range is MUCH better even from outdoors to indoors.

So it seem that this is the only way of increasing power.

Here is the power graph with it it on:

image

and here it is with it off:

image

so there is a clear increase in power. This does not work when using NimBLEDevice::setPower(8); as suggested above.

So I am happy now because my project is now in flight due to your kind help and the above change.

Only questions remain:

  1. How do I set power to 8dbm? any value above 4 seems to give the same results - I suspect there is some kind of ceiling.
  2. how to get 125Kbs.

I have used the following line but now sure if this is making any difference:

   NimBLEDevice::init("");
    //    NimBLEDevice::setPower(8);

  NRF_RADIO->MODE      = (RADIO_MODE_MODE_Ble_LR125Kbit << RADIO_MODE_MODE_Pos);
h2zero commented 7 months ago

Looks like the NimBLE driver caps the tx power to 4dbm, you can use the register to go to 8 NRF_RADIO->TXPOWER = 8;

j45p41 commented 7 months ago

Hey thanks. putting it in the code after init:

NimBLEDevice::init(""); NRF_RADIO->TXPOWER = 8;

gets overridden by the setting in the platform file for 4dbm. When I remove it the current drops back to the 0dbm reading approx 15mA (when higher (4dbm) value is actually set its 25mA). So it looks like placing

NRF_RADIO->TXPOWER = 8;

OR

NimBLEDevice::setPower(8);

it in the code does not seem to have any effect on actual power output.

I also looked at max values:

image

so looks like only way to trigger the change is via:

'-DMYNEWT_VAL_BLE_LL_TX_PWR_DBM=4'
'-DMYNEWT_VAL_BLE_LL_RX_PWR_DBM=4'

in the platformio.inifile, but that caps it at 4dbm.

h2zero commented 7 months ago

Yes, I've just looked at this as well and the issue is the controller will change it when advertising starts to the macro value and hard cap the value when calling the setPower function. This will require changes to the controller code.

j45p41 commented 7 months ago

Well you have got me far enough my friend. This will be a welcome addition later. The 4dbm is enough for the current purpose.

I sent my board to Nordic who tested it and we performed radio optimisation over a few exchanges. So based on this a board with a pcb antenna and a plastic enclosure benefits massively with the extra power and is reliably usable in a home environment. 0 dbm is very hit and miss in my experience.

h2zero commented 7 months ago

Sounds good, glad that it's working for you. I will try to address the controller shortfalls when I update the core files.

j45p41 commented 7 months ago

Actually I was wondering, is there a quick bypass to get this working or does it require lots of investigation? Where would I look if I wanted to have a go?

h2zero commented 7 months ago

Do a search for the function called by setPower and follow it to where it is capped and change that.

j45p41 commented 7 months ago

When I look on ble_phy.hit is set to 10. So this is above 4dbm am I missing something?

image

h2zero commented 7 months ago

Okay, if you search for ble_phy_txpwr_set you'll find what I mentioned above with the calls to set the power level to the one in the macro but you'll also find that the macro is limited to 4dbm here. There is also a nice little TODO note for this reason 😄

h2zero commented 7 months ago

@j45p41 Here is a branch with the new NimBLE version and an extension to the tx power setting function to allow for 8dbm. https://github.com/h2zero/NimBLE-Arduino/tree/nimble-1.5.0

NimBLEDevice::setPower(8); should be all that is needed.

j45p41 commented 7 months ago

Whoa - thanks! I will be trying that when I get home!

j45p41 commented 7 months ago

Ok rushed home!

I get this:

image

Do I need to copy files manually?

h2zero commented 7 months ago

try this: https://github.com/h2zero/NimBLE-Arduino.git#nimble-1.5.0 Also, just FYI the default coded PHY is S=8

j45p41 commented 7 months ago

Hi @h2zero - so now it compiles. When I run it I get:

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
D NimBLEServer: >> createService - 0xabcd
D NimBLEServer: << createService
D NimBLEService: << Adding a duplicate characteristic with UUID: 0x1234
D NimBLEService: >> start(): Starting service: UUID: 0xabcd, handle: 0xffff
D NimBLEService: Adding 2 characteristics for service UUID: 0xabcd, handle: 0xffff
Unhandled exception 0x00000003 , exception sp 0x20003d10
R0: 0x200059b8, , R1: 0x66666666 , R2: 0x200059e0, R3: 0x00000004, R12: 0x000027bb
LR: 0x00000000, PC: 0x0000a74c, PSR: 0x01000200

seems to happen only with new version when I set or do not set power.

this is the output on version 1.4.1:

I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
D NimBLEServer: >> createService - 0xabcd
D NimBLEServer: << createService
D NimBLEService: << Adding a duplicate characteristic with UUID: 0x1234
D NimBLEService: >> start(): Starting service: UUID: 0xabcd, handle: 0xffff
D NimBLEService: Adding 2 characteristics for service UUID: 0xabcd, handle: 0xffff
D NimBLEService: << start()
primary service
           uuid 0x1800
         handle 1
     end_handle 5
characteristic
                         uuid 0x2a00
     def_handle 2
     val_handle 3
   min_key_size 0
          flags [READ]
characteristic
                         uuid 0x2a01
     def_handle 4
     val_handle 5
   min_key_size 0
          flags [READ]
primary service
           uuid 0x1801
         handle 6
     end_handle 9
characteristic
                         uuid 0x2a05
     def_handle 7
     val_handle 8
   min_key_size 0
          flags [INDICATE]
ccc descriptor
                         uuid 0x2902
         handle 9
   min_key_size 0
          flags [READ|WRITE]
primary service
           uuid 0xabcd
         handle 10
     end_handle 16
characteristic
                         uuid 0x1234
     def_handle 11
     val_handle 12
   min_key_size 0
          flags [READ|WRITE|NOTIFY]
ccc descriptor
                         uuid 0x2902
         handle 13
   min_key_size 0
          flags [READ|WRITE]
characteristic
                         uuid 0x1234
     def_handle 14
     val_handle 15
   min_key_size 0
          flags [READ|WRITE|NOTIFY]
ccc descriptor
                         uuid 0x2902
         handle 16
   min_key_size 0
          flags [READ|WRITE]
D NimBLEExtAdvertising: >> Extended Advertising start
D NimBLEExtAdvertising: << Extended Advertising start
Started advertising
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnect(): Default
Client connected:: ec:da:3b:1e:40:aa
D NimBLEServer: >> handleGapEvent: 
Advertising instance 0 stopped
Client connecting
                 D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: mtu update event; conn_handle=1 mtu=255
D NimBLEServerCallbacks: onMTUChange(): Default

Thanks again!

h2zero commented 7 months ago

I'm not surprised, I haven't really tested this yet. I'll look into the issue shortly.

j45p41 commented 7 months ago

I'm not surprised, I haven't really tested this yet. I'll look into the issue shortly.

Take your time bro. Happy to offer any testing needed.

h2zero commented 7 months ago

Just pushed the fix, please let me know if it works for you.

j45p41 commented 7 months ago

OK so did some testing here is what I found:

It is possible to get to 8dbm by setting:

build_flags =
    '-DMYNEWT_VAL_BLE_LL_TX_PWR_DBM=8'
    '-DMYNEWT_VAL_BLE_LL_RX_PWR_DBM=8'

I can see this now on power graph:

image

No setting - RSSI: -82 - 15mA 4dbm setting - RSSI : -70 - 24mA 8dbm setting - RSSI: -59 - 38mA

I can also see it connecting on the client:

Connected to: cb:68:8d:5f:69:d3 RSSI: -68
Characteristic value: 
cb:68:8d:5f:69:d3 Disconnected - Starting scan
Done with this device!
Connected to: fd:d1:a1:13:df:22 RSSI: -67
Characteristic value: 
fd:d1:a1:13:df:22 Disconnected - Starting scan
Done with this device!
Connected to: f6:f0:bb:a6:ad:33 RSSI: -68
f6:f0:bb:a6:ad:33 Disconnected - Starting scan
Done with this device!
Connected to: f5:4f:a3:66:b0:84 RSSI: -66
f5:4f:a3:66:b0:84 Disconnected - Starting scan
ABCD service not found.
Done with this device!
Connected to: fb:4e:dd:70:b8:ac RSSI: -67
Characteristic value: 
fb:4e:dd:70:b8:ac Disconnected - Starting scan
Done with this device!
Connected to: c7:ff:c7:79:e1:1b RSSI: -71
Characteristic value: 
c7:ff:c7:79:e1:1b Disconnected - Starting scan
Done with this device!
Connected to: fe:69:1b:9e:95:bf RSSI: -60
Characteristic value: 
fe:69:1b:9e:95:bf Disconnected - Starting scan
Done with this device!
Connected to: d3:8a:ed:a0:aa:d5 RSSI: -59
Characteristic value: 
d3:8a:ed:a0:aa:d5 Disconnected - Starting scan
Done with this device!

However it seems that the incoming Mac address keeps changing. This happens with or without power setting so I think is something else in the updated library.

using setpower / SET_TXPOWER before or after init does not seem to change anything but now the power is not capped when specifying through plaformio.ini.

Thanks for the great progress!

h2zero commented 7 months ago

Thanks for the feedback, glad to see the progress. You should be able to set the power level in code before starting advertising or connecting without the need for defining it on the command line.

Interesting about the MAC address, what is the client device?

j45p41 commented 7 months ago

client device is esp32 c3 running BLE5 client example. When I switch back to 1.4.1 address is ok.

h2zero commented 7 months ago

Hmm, in that case I'm going to assume that random mac is enabled on the esp. is it also running on this updated branch?

j45p41 commented 7 months ago

yes because the client side is running the same example. When I switch to 1.4.1 it's consistent but with 1.5.0 it's changing.

h2zero commented 7 months ago

That's what I was curious about, thanks for confirming that suspicion. I'll look into that, quite strange that it has been changed.

Thanks for testing, please report any other issues or errors encountered.