Hello,
I'm working on a project where we are doing the following:
- Collecting sensor data and storing it in an external SPI flash
- Retrieving that sensor data from the SPI flash, reading it out into a module global array
- Sending that sensor data from the array, in <23 byte chunks, over BLE to a phone using notifications
The condensed version of our transfer protocol (a fairly standard one) is as follows (app == phone, device == nrf52):
- App sends message to device to begin recording data.
- App sends message to device to indicate that it is ready to receive the next page of data, when it is ready to be sent.
- Device collects data and when it has 1 SPI-flash-page's-worth of data, writes that data to SPI flash.
- If the app has sent a message to the device saying that it is ready for the next page of data, read that page out of SPI flash into an array and send it in chunks over BLE to the app.
- If the app has not yet sent a message to the device saying it is ready for the next page of data, wait until it does so, then repeat from 4.
- Repeat from 3.
The device always sends a page when it is available if the app has said that it is ready for it. Due to a variety of factors, sometimes the BLE data throughput is slower than the rate at which we are collecting data. In this case, "backlogged" pages are sent as soon as the app has indicated it is ready to receive another page (i.e. as soon as it has finished receiving the previous page).
Onto the interesting part:
- If, at the time the app sends the "ready for next page" command to the device, there is a backlog of pages to be sent, the page is retrieved from SPI flash immediately and sent over BLE at a rate of ~5000B/s.
- If, at the time the app sends the "ready for next page" command to the device, there is NOT a new page ready to be sent (i.e. the device is still collecting data and hasn't collected 1 pages worth yet), when the page is ready to be sent it gets read out of SPI flash and sent over BLE at a rate of ~750B/s.
The mechanism by which the page is retrieved from SPI flash is exactly the same in both cases (the same function even), and I've performed my measurements starting at the moment AFTER the page has already been loaded from SPI flash into an array, so this doesn't have anything to do with SPI transfer rates or priorities (I don't believe).
I've tested this both with our proprietary app and nRFConnect, on iOS and android, on multiple phones.
What I don't understand is why there is such disparity in the two scenarios described above. As I said, the code path from the time I start measuring is exactly the same for both cases. The only difference is that in the fast data rate case, there is very little time between the "I'm ready for another page" and when that page gets sent. In the slow data rate case, there is often some hundreds of milliseconds between when the "I'm ready for another page" command is received by the device and when that next page is actually ready to be sent. So far as I can tell, the negotiated connection parameters (conn interval in particular) aren't updated or changed in between the two scenarios. All else being equal, if the connection interval remained the same, and the size of the packets being sent remained the same, I'm not sure why I'm getting such inconsistent transfer rates and why they are so reliably different in the two scenarios provided.
Is there another BLE connection setting or nrf52 configuration that might give a clue as to why this is happening? Has anyone seen something similar? Are there any other tools I can use to get to the bottom of this issue?
Thank you
Matt