Android Question Bluetooth Connection - Reception Fail

rodmcm

Active Member
Licensed User
I have just started to reuse a program that successfully ran a while ago on a Levono TB- X103F running 6.01

If I send from an ESP32 a multiple array (100 sets with a delay of 5mS between each set) of integers with 4 fields I get a crash of the Bluetooth reception

When the BT reception crashes I always get "Buffer Length 0".

(Oddly enough I can still send for a while until a separate reception watchdog activates)

Tried lots of options with no luck.. When I use WIFI as the connection, and the same send/receive method, no problems...

Any ideas?

The following is the standard B4A reception procedure using prefix mode each end and B4rSerialization


Sub AStream_NewData (Buffer() As Byte)
Log("Buffer Length "& Buffer.length)
Dim Data() As Object = ser.ConvertBytesToArray(Buffer)
If Data.Length = 0 Then Return
Log("From ESP32 "& Data(0) & " "& Data(1) &" " & Data(2) & " " & Data(3)&" "& Data(4))

Do Stuff here....


End Sub
 

emexes

Expert
Licensed User
Firstly, you mention 4 fields but in the Log line you are accessing 5 array elements... perhaps that is causing the problem. If not:

I don't have an ESP32 to hand, but it looks like a capable and comprehensive module. Which Bluetooth mode are you using?
  • Classic Bluetooth for legacy connections, also supporting L2CAP, SDP, GAP, SMP, AVDTP, AVCTP, A2DP (SNK) and AVRCP (CT)
  • Support for Bluetooth Low Energy (BLE) profiles including L2CAP, GAP, GATT, SMP, and GATT-based profiles like BluFi, SPP-like, etc
If you are using BLE (eg SPP-like per HM10/HC08 BLE UART module) then it's only reliable for sending up to 20 bytes each BLE connection interval. The smallest connection interval is 7.5 ms, so the highest reliable throughput you could get (if you like living on the edge) is (1000 / 7.5) = 133 packets per second * 20 bytes = 2660 bytes per second.

But the connection interval is whatever period the master and slave agree on, and BLE specs go all the way up to 4 s (ie 4000 ms) although obviously that's intended for super-low-power usage scenarios. A more typical connection interval is between 20 and 50 per second. If you try sending more than 20 bytes per connection event, you'll often start to get missed data.

So... perhaps try increasing your 5 ms interval to 55 ms (and watch out for the trick/trap of Sleep(55) forking to an instant return from a Sub) and see if that makes a difference. If it then works, then start backing it down until the connection falls over, and then personally I'd double that minimum period to allow for the occasional missed connection event.
 
Last edited:
Upvote 0

rodmcm

Active Member
Licensed User
Thanks for that... Classic Bluetooth used.. I am actually sending 6 data points, extracting the first four for this part of the program. In other parts of the program extracting 6, but at a much reduced rate.

Are you saying that the connection interval is invoked each time a write happens? If so what is the range of the connection period and where would I find this information?

Can you explain 'trick/trap of Sleep(55)" please
 
Upvote 0

emexes

Expert
Licensed User
Classic Bluetooth used.. Are you saying that the connection interval is invoked each time a write happens?
Bar one brief foray with Classic Bluetooth when I accidentally ordered a non-BLE wireless relay board, I have only dealt with BLE. I haven't studied Classic Bluetooth much. With BLE, once a connection is established, the two devices schedule regular communications, so that they don't need to keep their radios operating continuously (which helps with the low energy aspect), and that schedule is at intervals of 7.5 to 4000 ms. Low speed stuff like tyre pressure sensors would tend towards long periods, high speed stuff like accelerometers would tend towards shorter periods.

where would I find this information?
For BLE, Google: ble connection interval

For Bluetooth Classic, this limit shouldn't apply, but nonetheless I tried Googling: bluetooth connection interval -ble -"low energy" spp
and got https://scholarworks.iupui.edu/bitstream/handle/1805/12496/LIBBY_ECET491_POSTER.pdf which mentions:

Sniff Mode – This is a power-saving mode, where the
device is less active. It’ll sleep and only listen for
transmissions at a set interval (e.g. every 100ms).

and also a paragraph about SPP.
Can you explain 'trick/trap of Sleep(55)" please
The trick (in the good sense of the word) is that Sleep is an efficient way to do a delay.

The trap is that, in B4X, Sleep(x) doesn't work the way you might be used to. Instead, it forks into two program flows: one returns immediately from the current Sub, before the delay takes effect, and thus the calling Sub does not see/experience the delay, and the other continues in the current Sub after delaying for the specified period.

Thus, if you had something like:
B4X:
Sub Main

    Log("Open warehouse")
    For I = 1 To 4
        SendRoses(I)
    Next I
    Log("Close warehouse")

End Sub

Sub SendRoses(N As Int)

    Log("Packing " & N & " roses")
    Sleep(300)
    Log("Sending " & N & " roses")
    Sleep(700)
    Log("Sent " & N & " roses")

End Sub
you would probably be surprised to find that your warehouse closed much sooner than you'd expected, per the log:
B4X:
Waiting for debugger to connect...
Program started.
Open warehouse
Packing 1 roses
Packing 2 roses
Packing 3 roses
Packing 4 roses
Packing 5 roses
Close warehouse
Sending 1 roses
Sending 2 roses
Sending 3 roses
Sending 4 roses
Sending 5 roses
1 roses sent
2 roses sent
3 roses sent
4 roses sent
5 roses sent
The fix for this is to declare the Sub "As ResumableSub":
B4X:
Sub SendRoses(N As Int) As ResumableSub
and then call the Sub using Wait For() Complete:
B4X:
For I = 1 To 5
    Wait For (SendRoses(I)) Complete
Next
This example is for a Sub that nominally does not return a value (well, it does, but it's an unspecified Object and will default to Null, and B4X will be warning you about not returning a value). If your sub needs to return a value, read:
https://www.b4x.com/android/forum/threads/b4x-resumable-subs-that-return-values-resumablesub.82670/
 
Last edited:
Upvote 0
Top