| Mynewt FAQ: Bluetooth |
| ===================== |
| |
| .. contents:: |
| :local: |
| :depth: 1 |
| |
| NimBLE on nRF52840 |
| ------------------ |
| |
| **Q**: Is the nRF52840 supported by NimBLE? |
| |
| **A**: The nRF52840 is supported, including Bluetooth 5 features. |
| |
| Trigger Exactly One BLE Advertisement Immediately |
| ------------------------------------------------- |
| |
| **Q**: Is there a way to trigger exactly one BLE advertisement immediately? I basically want to use BLE as a means |
| to advertise to a whole group of devices and it needs to be relatively time-precise. Hoping for about 1ms precision, |
| but it's okay if there's a delay as long as it's deterministic. |
| |
| **A**: With extended advertising you can enable an advertising instance for exactly 1 advertising event but there will |
| be some delay before controller starts advertising which depends on the level of precision. The NimBLE controller always |
| schedules the 1st advertising event with a constant 5ms delay. However, if there are other things scheduled in the |
| controller it may need to schedule it later so it’s not guaranteed to be deterministic. Periodic advertising is currently |
| not supported. |
| |
| |
| Supported Bluetooth Radio Transceivers |
| -------------------------------------- |
| |
| **Q**: Are there any other Bluetooth radio transceivers that are supported already or anyone working on? If there is a |
| Bluetooth radio that can be integrated using the HCI, we can use the NimBLE host? If so, I suppose we don't need detailed |
| specs of the Bluetooth radio? |
| |
| **A**: You should be able to run the NimBLE host against pretty much any controller using HCI. We have a BLE controller |
| implementation for Nordic only, but host (in theory) should work with all. More likely, it will work with 5.0 controller. |
| For 4.x controllers it may fail on initialization since we do not check controller features - but this can be fixed as |
| for other radio transceivers. For example, there's NXP KW41Z which has BLE-compatible radio documented. However, NXP |
| documentation is more or less a description of zillions of different registers so not as friendly as the one from Nordic |
| which explains how to actually use it. |
| |
| NimBLE Operational Questions |
| ---------------------------- |
| |
| **Q**: Can I update firmware via BLE for multiple devices simultaneously using a single device/phone supporting Bluetooth? |
| |
| **A**: Yes, it is possible to update several Nimble devices simultaneously from a single phone (e.g., central) as long as |
| the central can handle all the simultaneous Bluetooth connections. You can also do it using your computer as a central with |
| newtmgr. Just open two terminals and initiate a newtmgr image upload command in each, each to a different device. You will, |
| however, get better overall throughput if you limit yourself to one upgrade at a time. |
| |
| **Q**: I have the following doubts on NimBLE: The document says 32+ concurrent connections, multiple connections in simultaneous |
| central and peripheral roles. Does that mean the “device running NimBLE” can connect to 32 different other devices like phones? |
| |
| **A**: Yes, with one caveat: each of the 32 centrals needs to be sufficiently cooperative in choosing connection partners |
| (http://www.novelbits.io/ble-connection-intervals/). Your app might need to request different connection parameters from |
| the centrals (using ``ble_gap_update_params``). |
| |
| Of course, you will also need to build the Mynewt image device with a configuration suitable for 32 concurrent connections |
| (e.g., ``NIMBLE_MAX_CONNECTIONS=32``, etc.) |
| |
| ``blemesh`` Forgets All Keys on Restart |
| --------------------------------------- |
| |
| **Q**: Is it expected that the blemesh example forgets all the keys on restart and needs to be provisioned again? If so, |
| how can I implement key persistence myself? Is there any API to obtain / provide mesh keys before the mesh node is started? |
| I found bt_mesh_provision, but the comment there seems to indicate that this is not the right way to use it. |
| |
| **A**: Mesh implementations do not persist keys at the moment. There is a plan to add it but not sure about timeline. It |
| probably needs to be implemented inside mesh implementation so there's no API, but if you'd like to hack something I suggest |
| taking a look at shell.c and testing.c - there are some testing functions to add/display keys. Another area to look if you |
| actually want to persist keys to flash is ``net/nimble/host/store/config/src/ble_store_config.c``. This is the code that |
| persists and restores security material for (non-mesh) Bluetooth. |
| |
| L2CAP Connection |
| ---------------- |
| |
| **Q**: I want to do an L2CAP connection, and am trying the auth-passkey command, but am not sure about the parameters ``psm``, |
| ``action``, and ``oob``. What is ``psm``, and what is the value of that parameter in the btshell command ``l2cap-connect``? How |
| do I set the parameters ``action`` and ``oob``? |
| |
| **A**: ``psm`` stands for Protocol Service Multiplexer. You pass the ``psm`` value to either ``l2-cap-connect`` or |
| ``l2cap-create-server``. The parameters ``action`` and ``oob`` are just passing constant values as defined in the API. |
| |
| Bitbang, BLE Mesh, BLE Advertising |
| ---------------------------------- |
| |
| **Q**: Is it possible to run bitbanging and BLE mesh at the same time? How about running BLE Mesh and BLE advertising at |
| the same time? |
| |
| **A**: It is possible to run bitbanging and BLE mesh at the same time, but the bitbanging UART takes a lot of CPU on Nordic. |
| We’ve run it at 9600 which would probably be okay for lower rate devices, but for reliability it is recommended to run at |
| 4800. If this is just for the console and your UART port is tied up, ``rtt`` is recommended. Take a look at |
| :doc:`Segger RTT Console <../../tutorials/tooling/segger_rtt>` for more information. However, bitbanger can be handy given limited UARTs. |
| |
| You can certainly continue advertisements during connections, if you are using the GATT bearer for mesh. Mesh is also tied |
| into the ext-adv bearer in Mynewt, which also allows for interleaving, even if you’re transmitting mesh data on advertising channels. |
| |
| Extended Advertising with ``btshell`` |
| ------------------------------------- |
| |
| **Q**: I am using ``btshell`` for advertising with nRF52. When I use 31 bytes, ``mfg_data`` accepts the data with extended |
| advertising. But when I use more bytes than that, ``mfg_data`` doesn’t accept it. Is 251 byte payload supported in extended |
| advertising? How can I send more than a 251 byte payload on extended advertising? |
| |
| **A**: You need to set the ``BLE_EXT_ADV_MAX_SIZE`` syscfg to your required value. For example: |
| |
| .. code-block:: console |
| |
| newt target amend <your_target> syscfg=BLE_EXT_ADV=1:BLE_EXT_ADV_MAX_SIZE=1650 |
| |
| The default is 31 bytes, and the max is 1650. |
| |
| Keep in mind that with extended advertising, you cannot set advertising data for an instance configured as scannable |
| (e.g. ``advertise-configure scannable=1``). Either set scan response data using ``advertise-set-scan-rsp`` command |
| (parameters are the same as for ``advertise-set-adv-data``) or configure the instance as non-scannable. For example, |
| ``advertise-configure`` alone will configure the instance as non-connectable and non-scannable which means you can |
| set advertising data. Also note that if you continue to use a scannable instance you will need to perform active |
| scanning in order to get scan response data. |
| |
| FYI, legacy advertising instances can accept both advertising and scan response data but since they use legacy PDUs |
| the limit is still 31 bytes. |
| |
| Configuring Maximum Number of Connections for ``blehci`` |
| -------------------------------------------------------- |
| |
| **Q**: How do I set the maximum number of connections for the ``blehci`` :doc:`example <../../tutorials/ble/blehci_project>`? |
| I see there is a ``MYNEWT_VAL_BLE_MAX_CONNECTIONS``, but I don't know how to set it. |
| |
| **A**: You can to set it in target settings: |
| |
| .. code-block:: console |
| |
| newt target amend <target> syscfg=BLE_MAX_CONNECTIONS=2 |
| |
| and then rebuild using ``newt build <target>``. ``MYNEWT_VAL_BLE_MAX_CONNECTIONS`` is just a symbol that is defined in |
| ``syscfg.h`` which is autogenerated by ``newt`` tool and contains all the settings set at package/app/target level. |
| |
| **Q**: What if I need to set 2 constants? What's the syntax? |
| |
| **A**: You can set each setting in separate commands or separate ``key=value`` pairs with colon: |
| |
| .. code-block:: console |
| |
| newt target amend <target> syscfg=FOO=1:BAR=2 |
| |
| **Q**: How do you know the constant is ``BLE_MAX_CONNECTIONS`` and not ``MYNEWT_VAL_BLE_MAX_CONNECTIONS``? |
| Is there a place I can see those names? |
| |
| **A**: This is actually one of NimBLE’s settings - you can find these settings available for different packages in the |
| ``syscfg.yml`` files in the repository. You can also use ``newt target config show <target>`` to show all settings with |
| their current values, and then change any of these settings accordingly. Each setting will get a symbol prefixed by |
| ``MYNEWT_VAL_`` in the autogenerated ``syscfg.h`` file so you can get the actual setting name from this symbol. For more |
| info on System Configuration and Initialization, please visit the :doc:`Compile-Time Configuration and Initialization <../../../../os/modules/sysinitconfig/sysinitconfig>` page in the OS User Guide. |
| |
| Disconnect/Crash While Writing Analog Value From Central Module |
| --------------------------------------------------------------- |
| |
| **Q**: I’m trying to write analog sensor data from my central module to my peripheral module. I can receive the values |
| from the ADC callback perfectly, but I’m not able to write them to the peripheral module. The peripheral module disconnects |
| right when the ``ble_gattc_write_flat`` command is called. What could be causing the issue? |
| |
| **A**: First, check the reason for the disconnect. The gap event callback should indicate the reason in ``disconnect.reason``. |
| If the code never reaches the disconnect callback, then the code most likely crashed. If so, check whether ``ble_gattc_write_flat`` |
| is called from an interrupt context. Calling into the BLE host from within an interrupt is a bad idea in general, and may cause a |
| crash to occur because the Bluetooth host attempts to log to the console during the write procedure. Logging to the console uses |
| quite a bit of stack space, so it is likely that the interrupt stack is overflowing. |
| |
| Instead, you should send an event to the event queue and handle this in a task context. You’ll need to associate the characteristic |
| data with the event so that your event callback knows what payload to pass to the ``ble_gattc_write_flat()`` function. If you don’t |
| need to perform multiple writes in rapid succession, then you can just use a single global event and single global buffer. However, |
| you will still need to make sure your buffer doesn’t become corrupted by a subsequent ADC interrupt while you are in mid-write. |
| |
| Documentation for ``ble_gap_disc_params`` |
| ----------------------------------------- |
| |
| **Q**: Is there documentation somewhere on correct values for ``ble_gap_disc_params``? I'm trying to do a passive discovery and getting |
| ``BLE_HS_EINVAL``. |
| |
| **A**: Unfortunately, not at the moment. Here is a brief description of the fields: |
| |
| - ``itvl``: This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE |
| scan. (units=0.625 msec) |
| - ``window``: The duration of the LE scan. ``LE_Scan_Window`` shall be less than or equal to ``LE_Scan_Interval`` (units=0.625 msec) |
| - ``filter_policy``: The only useful documentation is the table in the Bluetooth spec (section 2.E.7.8.10). This field controls which |
| types of devices to listen for. |
| - ``limited``: If set, only discover devices in limited discoverable mode. |
| - ``passive``: If set, don't send scan requests to advertisers (i.e., don't request additional advertising data). |
| - ``filter_duplicates``: If set, the controller ignores all but the first advertisement from each device. |
| |
| Multicast Messaging and Group Messaging |
| --------------------------------------- |
| |
| **Q**: Is it possible to send a broadcast message by one of the devices present in the mesh (e.g. broadcast an event which happened)? Something like a push notification instead of continuously polling for it by a client. |
| |
| **A**: It is possible to do so with a publish model. Group address or virtual address should help here, according to the Mesh spec. There is no real documentation on it but you can try it out on our ``btmesh_shell`` app. There is a ``shell.c`` file which exposes configuration client which you can use for testing (e.g. you can subscribe to virtual addresses). You can also trigger sending messages to devices. By playing with the ``dst`` command, you probably should be able to set destination to some group. However, since we do not support the provisioner role, there is a command provision which sets fixed keys so you can create a mesh network out of a couple of nodes without the actual provisioner. |