ComThings/PandwaRF

Best way to send large buffers

Closed this issue · 19 comments

If I have a data buffer of 15-20 Kbytes to be transmitted, how can I minimize the probability of Tx failure:

  • by calling txSend() once for the whole data
    or
  • by dividing the data into multiple blocks and calling multiple instances of txSend() ?

Originally posted by @Massimaux in #76 (comment)

both solution should work, but:

  • if you call txSend() once with a large buffer, PandwaRF will try to send all buffer as a single packet, ie. without time between packets. Note that only Rogue variant can achieve this. Regular PandwaRF will indeed have some gaps...
  • if you call txSend() multiple time, there will be gaps between packets

The experience with large buffers so far is as follows:

  1. LG K8 (Android 6.0 | API level 23)
  • It is noticeable that the BLE data rate between the phone and the dongle is not too high
  • Very low rate of Tx failures
  1. HUAWEI P10 Lite (Android 8.0 | API level 26)
  • It is noticeable that the data rate between the phone and the dongle is very high
  • Higher rate of Tx failures

I'm not certain about this observation, but it seems there is a correlation between the phone-dongle BLE data rate and the Tx failure rate. Is it possible that when PandwaRF receives large buffers from the phone with very high data rates, this may cause failure during the transmission?

Update: when talking about the phone-dongle BLE data rate I mean the effective data rate:

eff_data_rate = data / total_time

where, total_time = transmission time + gap_time

For example, if the bit rate is set to 16Kbit/s, then the effective data rate is much less than 16Kbit/s if there is a considerable gap time.

So, the gap time seems to vary between the two phones and my observation for large buffers is:
shorter gap time --> higher rate of Tx failures
longer gap time --> lower rate of Tx failures

What do you mean exactly by "TX failure" ?

  • some bytes not transmitted ?
  • No data transmitted ?
  • PandwaRF disconnect ?
  • ....

BTW you can measure the BLE data rate Android <-> PandwaRF in the BLE Perf page (you need to enable dev mode).

https://github.com/ComThings/PandwaRF/wiki/Android-Fragment-Ble-Perf

Tx failure:

  • only some part of the data is transmitted
  • PandwaRF disconnects
  • both LEDs blinking in alternate fashion
  • PandwaRF disconnects
  • both LEDs blinking in alternate fashion

==> these 2 points means PandwaRF has crashed, probably because there are too many data received by PandwaRF from phone.
So you need to wait until PandwaRF has freed some memory before sending more packets for TX.
I suggest using the asynchronous TX mode:
The txSend() method has a parameter called async. I guess you are transmitting with async = true (txSend(x, x, true, x)
This cause the txSend() method to return immediatly, before TX has started.

If you use the synchronous mode (txSend(x, x, false, x), the txSend() will block until TX is complete.

Maybe this can provide better results with large buffers.

Yes, I have used async=true. Do you suggest trying synchronous mode (async=false) for large buffers?

Yes, try with synchronous mode (async=false) for large buffers

It seems that transmitting larger data using the synchronous mode is more reliable.

Apart from this, can keeping the BLE connection permanently ON drain the PandwaRF battery in couple of hours?

thanks for feedback regarding large buffers.
Here are some power consumption values:

  • In BLE connected mode, while doing nothing on the RF, PandwaRF consumption is 10mA, so battery shall last from 20h to 35h according to your PandwaRF version.
  • In idle mode (not connected), consumption is 200uA, so battery shall last from 1000h to 1700h according to your PandwaRF version.

Thanks for the battery info. The consumption looks OK.

I have an issue for which your help will be appreciated.

How can I impose a delay of certain duration between two transmissions? For example, I call txSend() for one data buffer and then I want to wait for 10 seconds before I call txSend() for another data buffer.

txSend(buffer1)
wait for 10 seconds
txSend(buffer2)

TimeUnit.SECONDS.sleep(10);
?

try {
    Thread.sleep(10000);
} catch (InterruptedException e1) {
    e1.printStackTrace();
}

?

Thanks. I've been using several txSend(data, x, false, 1, GollumCallbackGetInteger) in sequence with a SLEEP between them but the behavior I'm seeing is:

  1. First, all txSend() methods including the SLEEP are called.
  2. Then the transmissions are performed but there is no delay between them.

I thought txSend(x,x,false,x) blocks so that no other code is executed until it returns.

How can I make sure that no next code is executed until txSend() completes the transmission?

I apologize for bothering, but I'm still struggling with this problem.

Is there a way to know when the data transmission caused by txSend(data, x, false, 1, cb) finishes?

This is crucial to my app because the next code (after txSend()) must NOT be executed before the real transmission finishes.

Thanks!

Synchronous mode + txSend() callback doesn't do the trick ?

For some reason, only txSend(data, x, false, 1, cb) works. And when I have this code:

txSend(data1, x, false, 1, cb);
TimeUnit.SECONDS.sleep(10);
txSend(data2, x, false, 1, cb);

What actually happens is that the 10 seconds sleep is executed before the data1 transmission finishes.

Is there a way that a certain timeout is imposed on the dongle before it proceeds with the next transmission?

txSend(data1, x, false, 1, cb) returns immediatly, but cb is here to notify you when txSend() finishes.
If you call sleep() or 2nd txSend() before first cb is called, then the code is executed before 1st TX finish.
If you want a txSend() function that is blocking, use the one without the cb parameter.

Thank you!

I will try with the txSend() without the cb parameter but I remember it didn't work as expected.

If it turns out that only txSend() with cb works well, could I somehow use the cb parameter to check if the first txSend() finished?