← index #7769PR #906
Related · medium · value 4.582
QUERY · ISSUE

How to set BLE connection interval?

openby jd3096-mpyopened 2021-09-10updated 2021-09-16
extmod

SO,how to set BLE connection interval?
when the devices are connected,i want to save more power,so i want to increase the conncetion interval ,but i can't find how to redefine this param.
adv and scan interval is easily to set,i can't find the way to set connnection interval
i notice that IRQ has this event:
elif event == _IRQ_CONNECTION_UPDATE:
conn_handle, conn_interval, conn_latency, supervision_timeout, status = data
how to update connection,to change conn_interval, conn_latency, supervision_timeout

CANDIDATE · PULL REQUEST

aioble: Pass additional connection arguments to gap_connect.

mergedby Joris-van-der-Welopened 2024-08-02updated 2024-11-01

In my project I am connecting using aioble to a human input device. There is noticeable input lag. Turns out the RTT latency is a little over 200ms (I test this by timing await char.write(b'foo', response=1)). I suspect this is because the BLE connection interval is being set to 100ms. The gap_connect function allows setting min_conn_interval_us and max_conn_interval_us, however there is no way to do so using aioble.

This PR allows the following additional arguments to be passed to device.connect():

  • scan_duration_ms
  • min_conn_interval_us
  • max_conn_interval_us

These are passed as-is to gap_connect(). The default value for all of these is None, which causes gap_connect to use its own defaults.

With this change I managed to get the RTT latency down to ~60ms, this feels a lot better in my project.

Package: https://joris-van-der-wel.github.io/micropython-lib/mip/gap_connect_params/

3 comments
ekspla · 2024-09-09

I personally have no objection against this PR related to conn_intervals.

However, I sometimes saw an error when using characteristic.notified() with the arguments as followings.
I am not sure about the other possible errors that might be introduced by using these arguments.

scan_duration_ms=5000 or 2000
min_conn_interval_us=7500 or 11250
max_conn_interval_us=7500 or 11250

BOARD: ESP32-S3-WROOM-1
FIRMWARE: MPY-1.23.0 and also MPY-1.24.0-preview

Important part of the error trace:

  File "/lib/aioble/client.py", line 384, in notified
  File "/lib/aioble/client.py", line 378, in _notified_indicated
IndexError: empty

A fix for me to this error was to simply add asyncio.sleep_ms(5) just before reading the notified queue in client.py .
async def _notified_indicated(self, queue, event, timeout_ms):

    async def _notified_indicated(self, queue, event, timeout_ms):
        # Ensure that events for this connection can route to this characteristic.
        self._register_with_connection()

        # If the queue is empty, then we need to wait. However, if the queue
        # has a single item, we also need to do a no-op wait in order to
        # clear the event flag (because the queue will become empty and
        # therefore the event should be cleared).
        if len(queue) <= 1:
            with self._connection().timeout(timeout_ms):
                await event.wait()

        # Either we started > 1 item, or the wait completed successfully, return
        # the front of the queue.
+       await asyncio.sleep_ms(5)
        return queue.popleft()
dpgeorge · 2024-10-18

Thanks @Joris-van-der-Wel for the contribution. This looks like a good enhancement to me. You definitely need to lower the connection interval to improve latency, and that should be possible to do in aioble (and this PR enables that).

@ekspla this PR does not change any of the defaults, it's an opt-in feature. For your case, it looks like a possible bug which needs to be discussed separately.

ekspla · 2024-11-01

@dpgeorge Apologies. After tinkering my code, the issue I wrote in my previous comment was found to be not caused by AIOBLE, but caused by an error in handling a successive burst of notified data in the notified queue.

The reason was that the event was not cleared after reading data in the queue from another coroutine. A better fix in my case was to use characteristic._notify_event.clear() explicitly after reading in my code.

Though I am not sure what is the better way to handle a burst of successive notified packets using AIOBLE, the working server/client POC code for Nordic UART service is shown.

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied