Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Micropython BLE has higher latency than Arduino. Is there any way to reduce it? #15418

Closed
jd3096-mpy opened this issue Jul 7, 2024 · 8 comments
Labels
enhancement Feature requests, new feature implementations

Comments

@jd3096-mpy
Copy link

Description

I tried to use MicroPython's BLE to make a BLE MIDI instrument.
like this
But I found that there was a delay when testing. There was no such feeling when using Arduino or espidf. I want to know where the problem lies. Is there any solution, such as modifying the source code and recompiling the firmware? Will using a function like esp_ble_gap_set_prefer_conn_params be effective?

Code Size

No response

Implementation

I hope the MicroPython maintainers or community will implement this feature

Code of Conduct

Yes, I agree

@jd3096-mpy jd3096-mpy added the enhancement Feature requests, new feature implementations label Jul 7, 2024
@jonnor
Copy link
Contributor

jonnor commented Jul 7, 2024

Hi and thank you for reporting. Is this the code that you are using? https://github.com/ospanic/MIDI_Boy/blob/master/Kalinmba/main.py - if not, please provide the exact code being used.

How much delay do you experience?

@jd3096-mpy
Copy link
Author

jd3096-mpy commented Jul 8, 2024

Hi and thank you for reporting. Is this the code that you are using? https://github.com/ospanic/MIDI_Boy/blob/master/Kalinmba/main.py - if not, please provide the exact code being used.

How much delay do you experience?

Yes,it is.
Because it's sensitive to delay when using musical instruments. I plan to test it with other boards later, such as esp32c3 and pico w, to compare whether there is any difference in delay.
I did not test the specific delay, but according to my personal feeling, it is about 50ms or more, which is not a good experience for playing musical instruments. Whether on Android or Windows computers, the delay feels similar and is very stable. I hope the delay can be less than 30ms, so that playing midi instruments will have a better experience.

BLE seems to be able to reduce latency by setting parameters, but the cost is that it will increase the power consumption of the device. Obviously, in the use scenario of BLE MIDI instruments, latency is more important for the device.
The main task at present is to find out where the problem is. I will also try to directly add a BLE module to test the latency problem.

@jonnor
Copy link
Contributor

jonnor commented Jul 13, 2024

@jd3096-mpy your code has a sleep_ms(10) per each key. And there are 17 keys checked sequentially, meaning that it is 170 ms between each key being checked / BLE being updated for that key. So that is a huge problem for low latency uses. And independent of the BLE stack...

@dpgeorge
Copy link
Member

We have a BLE test in tests/multi_bluetooth/perf_gatt_notify.py that tests latency of this scenario, of sending BLE notifications. The test sends a notification from one device to another, and then a notification back again immediately, and then the first device times how long it takes for this notification ping-pong.

Testing this with two PYBD-SFx boards (running either NimBLE or BTstack) the latency of a notification can get down to the minimum of 7.5ms (15ms round trip for two).

Testing with an ESP32, it seems the best you can get is 11.5ms, which is still very good.

By default the latency is about 50ms.

This is all dependent on the connection interval that is negotiated when the two BLE devices connect. And it's the central (the one initiating the connection) that can set the connection interval parameters.

@jd3096-mpy your MIDI program is the peripheral. What central are you using to connect to the MIDI peripheral? The central is the one you need to set the connection interval on.

Will using a function like esp_ble_gap_set_prefer_conn_params be effective?

Yes, that's the correct function to use to set the connection interval parameters. But it's for the central, the device initiating the connection (not the MIDI peripheral).

In MicroPython it's possible to set the connection interval using gap_connect() like:

ble.gap_connect(addr_type, addr, 5000, 11500, 11500)

That will give a connection interval of 11.5ms, which will be the latency of a notify.

@jd3096-mpy
Copy link
Author

jd3096-mpy commented Jul 19, 2024

your code has a sleep_ms(10) per each key. And there are 17 keys checked sequentially, meaning that it is 170 ms between each key being checked / BLE being updated for that key. So that is a huge problem for low latency uses. And independent of the BLE stack...

I tested it with just one key program, and I felt that the delay still existed. I am sure that there is no delay in the key reading, because when I used UART wired MIDI, the same program, the delay obviously did not exist.

@jd3096-mpy
Copy link
Author

We have a BLE test in tests/multi_bluetooth/perf_gatt_notify.py that tests latency of this scenario, of sending BLE notifications. The test sends a notification from one device to another, and then a notification back again immediately, and then the first device times how long it takes for this notification ping-pong.

Testing this with two PYBD-SFx boards (running either NimBLE or BTstack) the latency of a notification can get down to the minimum of 7.5ms (15ms round trip for two).

Testing with an ESP32, it seems the best you can get is 11.5ms, which is still very good.

By default the latency is about 50ms.

This is all dependent on the connection interval that is negotiated when the two BLE devices connect. And it's the central (the one initiating the connection) that can set the connection interval parameters.

@jd3096-mpy your MIDI program is the peripheral. What central are you using to connect to the MIDI peripheral? The central is the one you need to set the connection interval on.

Will using a function like esp_ble_gap_set_prefer_conn_params be effective?

Yes, that's the correct function to use to set the connection interval parameters. But it's for the central, the device initiating the connection (not the MIDI peripheral).

In MicroPython it's possible to set the connection interval using gap_connect() like:

ble.gap_connect(addr_type, addr, 5000, 11500, 11500)

That will give a connection interval of 11.5ms, which will be the latency of a notify.

First of all, thank you very much for your hard and meticulous testing.
I use ESP32 as a BLEMIDI instrument to connect to a computer or Android phone, so ESP32 as the broadcaster cannot use the gap_connect function, but the Android phone or computer uses a similar function.
I tried to use an external Bluetooth module to send serial data using BLE MIDI, and the delay was not significantly improved, which also proves that your test is accurate and there is no problem with the delay of MicroPython BLE.
I also ruled out the cause of the key delay. I am still working on this Bluetooth project. I will post the results here in time.
Thanks again to the MicroPython contributors for their hard work!

@jonnor
Copy link
Contributor

jonnor commented Jul 19, 2024

Thank you for the feedback. I think we can close this issue then. When you have something more to share about your project, then create a post in our Show & Tell on the discussion board: https://github.com/orgs/micropython/discussions/categories/show-and-tell - does not have to be polished - can be work in progress :) Probably there are others interested in BLE MIDI things!

@dpgeorge
Copy link
Member

It would be good to have a working BLE MIDI example in examples/bluetooth (see #6559), or even better a helper library in micropython-lib. But that's separate to this issue.

I'll close this then. If it turns out that MicroPython does have latency issues with working BLE MIDI code, please reopen with more details how to reproduce the problem (ie both central and peripheral).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests, new feature implementations
Projects
None yet
Development

No branches or pull requests

3 participants