Hi Ondrej, Some tips inline below.
On Thu, Apr 9, 2020 at 5:46 PM Ondrej Pilat <ondrej.pi...@ozobot.com> wrote: > Hi, > > I cannot find any documentation about Nimble connection events scheduling. > I have following scenario: > > NRF52 Nimble is in dual role setting. Peripheral device connected to a PC > with at least BLE 4.2 and MTU more than 153B. Central is connected to 18 > peripheral devices BLE 4.1 with MTU 27B. > > Do you think that Nimble can keep interval window 12.5ms with the PC and > 37.5ms with all peripherals? > > My assumption are following: > > - only one packet per each connection event > - send/receive 132B packet between NRF52 and PC each connection event > - send/receive 20B packet between NRF52 and peripheral each connection > event > > I made following rough computation: > > PC <-> NRF52: 132B data + 21B header => (153B * 8) / 1Mbps => 1224 uS + > 150 uS IFR + 80 uS ACK + 150 uS IFR => 1604 uS * 2 (send/receive) => 3208 > uS > > NRF52 <-> peripheral: 20B data + 21B header => (41B * 8) / 1Mbps => 328uS > + 150 uS IFR + 80 uS ACK + 150uS IFR => 708uS * 2 (send/receive) => 1416 uS > > It means one big and six small packets should fit in each PC <-> NRF52 > connection event 3208 + 6 * 1416 = 11 704 < 12.5ms interval window. For 18 > peripherals it means 3 such cycles to serve them all therefore 37.5ms > interval window between NRF52 and a peripheral. > You need to take NimBLE scheduling into account here. Each connection event is preallocated a fixed amount of time in 1250us slots - see BLE_LL_CONN_INIT_SLOTS. This means effectively connection events cannot be scheduled less than 1250us apart. Also, scheduler overhead is ~200us (for nRF52, may be different for nRF51) for each connection event so effective connection event time with 1 slot allocated is 1050us. Note that this is min time since connection events can be extended pretty much indefinitely as long as there is no other activity scheduled so e.g. until another connection event. I do not know if "20B packet" means "20 bytes of LL payload", but will assume so since we are talking LL level here. This can fit into a single scheduled slot: 240us + 150us + 80us = 470us < 1050us. Let's assume 1ms for each connection event including scheduler overhead so you need 18ms to serve all 18 devices in one direction. If you need to send data in both directions you need 240us + 150us + 240us = 630us < 1050us so nothing changes and you still have quite a lot of extra time to spare in each connection event (e.g. for retransmissions). It will be a bit different if you need to transfer data in both directions in separate connection events as basically you need twice as much connection events, this means you need at least 36ms to serve all peripherals. One possible problem here is that connection may not be scheduled exactly 1.25ms apart and this will create gaps where no connection can be scheduled, you can't really control this with default scheduler. Possible solution would be to use BLE_LL_STRICT_CONN_SCHEDULING which schedules connections in central role at fixed intervals, although I never used it so not sure if there's anything that requires more configuration than just enabling this feature. So dealing with peripherals should not be a problem. Connection with a PC is a more troublesome since NimBLE has a slave role here so it needs to use anchor point imposed by a master. In theory, as a slave you can request to move anchor point but you would need to guarantee there is slot of proper duration and at proper intervals (so slave connections need to be arranged properly) for this to make any sense. NimBLE does not yet allow to move anchor point since it does not have any logic to do this in a way that makes any sense. Perhaps the best solution you could try for now is just to ignore connection with a PC in your scheduling so it will be scheduled at the time of some peripheral connection. In such case, NImBLE will let the least recently active connection run so it will skip connection events on "random" connections. It should not impact data throughput since outstanding data will be sent at next connection interval, but it will likely impact latency so you just need to check it this is acceptable in your case. Are following parameters good to achieve this: > > NRF52 <-> PC > > static const struct ble_gap_conn_params ble_gap_conn_params_ideal = { > .scan_itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN, > .scan_window = BLE_GAP_SCAN_FAST_WINDOW, > .itvl_min = 10, > .itvl_max = 10, > .latency = 0, > .supervision_timeout = 500, > .min_ce_len = 5, // 3.208 / 0.625 = 5.1328 > .max_ce_len = 6, > }; > > NRF52 <-> Peripheral > > static const struct ble_gap_conn_params ble_gap_conn_params_ideal = { > .scan_itvl = BLE_GAP_SCAN_FAST_INTERVAL_MIN, > .scan_window = BLE_GAP_SCAN_FAST_WINDOW, > .itvl_min = 30, > .itvl_max = 30, > .latency = 0, > .supervision_timeout = 500, > .min_ce_len = 2, // 1.416 / 0.625 = 2.2656 > .max_ce_len = 3, > }; > NimBLE controller does not use min/max ce len parameters, you can just leave them at default values. > Regards > > Ondrej > Best, Andrzej > -- >