This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Reducing latency - BLE nano as MIDI controller

Hi All, I am building a wireless MIDI controller using the BLE nano v2.0 from RedBearLab. MIDI is a protocol to control software musical instrument, therefore latency needs to be <10ms and at the moment it ranges roughly between 20 and 100ms.

I am using UART service to send data between the BLE peripheral and the central device (my laptop). The way I test the latency is by sending a single number or character from the ble module (using the serial monitor) to a connection utility using UART (I am using the Bluefruit Connect from Adafruit).

I use Arduino IDE to upload the firmware on the board and I have already tried to decrease the connection interval to reduce the latency. It has improved with this modification, but is not short enough yet.

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(1, UNIT_1_25_MS)
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(1, UNIT_1_25_MS)

static Gap::ConnectionParams_t conn_params = {
  .minConnectionInterval = MIN_CONN_INTERVAL,
  .maxConnectionInterval = MAX_CONN_INTERVAL,
  .slaveLatency = 0,
  .connectionSupervisionTimeout = 10000
};

I noticed that sometimes the latency is short and sometimes is longer and that makes me assume there is a sort of period which controls how often packets gets sent, but I am not totally sure.

Do you know what other parameters or settings I can change in order to solve the issue?

I want to point out that I have already done this with the Adafruit Feather 32u4 with very short latency, therefore is definitively possible, but I need to use a smaller board.

Thanks in advance for any help!

  • Hi, few comments:

    • You cannot set min and max connection interval in Peripheral Preferred Connection Parameters or anywhere else) because the lowest allowed interval by BT SIG core specification is 7.5ms.
    • As visible from previous point the latency can be under 10ms only if you are sure there will be no packet loss which won't be the case. Even in 2.4GHz "quite" environment there will be some loses sooner or later. On the other side it might be fine for you in the end, it's all probabilistic game which might have acceptable values from your application point of view.
    • I've seen MIDI over low-power radio implemented on nRF24, 51 and 52 but as there are always two sides io the transfer and such solution won't be probably interoperable (so you will need to put HW+FW to both sides of the link) then you might want to explore other radio protocols then BLE. I've seen at least two "MIDI over BLE" implementations on nRF chips but all of them used "proprietary" protocols like gazell or ESB, mainly because of latency requirements (I've even heard from two musicians that already 1ms out of sync will cause troubles and basically kills current song if it happens... however I'm not musical guy so you probably know what you are doing...
  • Thanks for the comments, it all makes sense. In fact, my latency requirements are a target, but there can be a comfortable compromise where the application still works.

    There is an Apple iOS BLE service exactly for MIDI and that might be something that gives the solution.

    On the other end, I have already experience much shorter latency with the Adafruit Feather 32u4, using the same exact configurations and utilities on my laptop, therefore I am pretty sure that are settings or firmware updates I can do on the BLE nano to improve the current latency, I just don't know what.

    Any other comment is appreciated :)

  • It is the central (your laptop) that ultimately decides on the connection interval the min max values that you use on the peripheral side is just there to show the central the preferred intervals. I don't know what your laptop does when you try setting the intervals to 1.25 which is outside the legal range according to the BLE spec. I didn't even think it was possible to do without making the Softdevice complain. Have you tried setting the min/max intervals to

    #define MIN_CONN_INTERVAL               BLE_GAP_CP_MIN_CONN_INTVL_MIN;
    #define MAX_CONN_INTERVAL               BLE_GAP_CP_MAX_CONN_INTVL_MIN;
    
  • Thanks for the suggestion. I have tried to use these settings, but the latency actually increased.

    Any other ideas?

    1. What kind of central device do you use? A phone? Apple? Android? If my memory serves me right, I believe all iOS devices have some limits of how short your connection intervals can be, except on the MIDI service which allows 7.5ms intervals. So if you are using the UART service for testing that probably won't work very well in terms of latency. Here is a useful write up on the matter: Maximizing BLE Throughput on iOS and Android.
    2. Do you have a way of figuring out what connection intervals are being used? Logs?
Related