At this point we are basically using the current user base as a testing platform to find and confirm bug fixes. There is nothing better than giving it to a few hundred people and getting feedback.
This is fine, but please "fix" things and don't "cover up".
The bluetooth transmission is broken by design and by implementation.
- There is no data integrity, aka. CRC or something on records (design error)
- The ASCII decimal/hex coding wastes more then 2/3 of the already scarce bluetooth bandwidth (design error)
- You have to check every single byte received for plausibility (and you'll fail in a lot of cases) (implementation error)
- If you look at the errors in the data it's clear that some buffer in the firmware get's overwritten (implementation error)
Would current owner prefer we not make interim firmware releases available for testing?
I'm fine with testing, no problem.
But the 1.07 -> 1.09 is not a fix, it's just trying to cover up above mentioned errors a bit better.
Start with fixing the missing CRC. Then errors can be detected reliably and automatically and one can trust the data received is what the firmware wanted to send.
No need to implement CRC, because BLE has this already integrated on the lower levels and automatically resends packets, if they are wrong, so no need to implement it on the data layer. Usually you can be sure that the transmitted data is right, so it must be another problem.
I personally tested a Blue Gecko chip from Silicon Labs with BLE and at the application level only the packet rate drops when I increase the distance. Here are some numbers where the device was sending 20 byte packets with max speed, which I recorded with a Python script :
measuring in 1 m distance:
number of packets: 348697
transfer time: 255 s
lost packets: 0
average transfer rate: 27310 bytes per second
max delay between two packets: 79.6 ms
min delay between two packets: 0.0 ms
measuring in 7m distance, with 2 walls in between:
number of packets: 265549
transfer time: 331 s
lost packets: 0
average transfer rate: 16044 bytes per second
max delay between two packets: 284.1 ms
min delay between two packets: 0.0 ms
This was with a standard BLE dongle on a PC, which identifies in Linux as this with lsusb:
Bus 001 Device 012: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
I implemented the nRF UART protocol on the BLE chip for easier testing, as described here:
https://www.silabs.com/community/wireless/bluetooth/forum.topic.html/how_to_implementuar-ovZ7Because I really don't like all the complexity of BLE, give me just a reliable UART link, which works for me now. Maybe UEI should hire me to fix their bluetooth implementation
Here is the Python script which received the data on the PC:
import struct
from bluepy.btle import *
# callback class
class MyDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleNotification(self, cHandle, data):
print(data)
# connect to device
per = Peripheral("00:0B:57:1D:B3:93", "public")
try:
# set callback for notifications
per.setDelegate(MyDelegate())
# enable notification
setup_data = b"\x01\x00"
notify = per.getCharacteristics(uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e')[0]
notify_handle = notify.getHandle() + 1
per.writeCharacteristic(notify_handle, setup_data, withResponse=True)
# send test string
c = per.getCharacteristics(uuid='6e400002-b5a3-f393-e0a9-e50e24dcca9e')[0]
c.write("Hello Gecko")
# wait for answer
while True:
if per.waitForNotifications(1.0):
continue
finally:
per.disconnect()
And here is the Python script which evaluated the received data to create the statistics:
#!/usr/bin/python
import sys
filename = sys.argv[1]
# statistic variables
count = 0
lastPacketNumber = 0
lastTimestamp = 0
deltaSum = 0
maxDelta = 0
minDelta = 1e9
packetsLost = 0
absoluteTimestamp = 0
# read file and calculate statistics
with open(filename, "r") as ins:
for line in ins:
values = line.split(";")
packetNumber = int(values[0])
timestamp = int(values[1])
delta = timestamp - lastTimestamp
if count > 0:
if timestamp < lastTimestamp:
delta = 32768 - lastTimestamp + timestamp
if delta > maxDelta:
maxDelta = delta
if delta < minDelta:
minDelta = delta
absoluteTimestamp = absoluteTimestamp + delta
if packetNumber - lastPacketNumber > 1:
packetsLost = packetsLost + packetNumber - lastPacketNumber - 1
lastPacketNumber = packetNumber
lastTimestamp = timestamp
count = count + 1
# format milliseconds with suffix and one digit after the comma
def formatMs(ms):
return "{:.1f} ms".format(ms)
# convert ticks to seconds
def ticksToS(tick):
return float(tick) / 32768.0
# convert ticks to miliiseconds
def ticksToMs(tick):
return ticksToS(tick) * 1000.0
# calculate some more statistics
transferTimeInSeconds = ticksToS(absoluteTimestamp)
bytesTransfered = count * 20
bytesPerSecond = float(bytesTransfered) / transferTimeInSeconds
# show result
print("number of packets: %d" % (count))
print("transfer time: %d s" % (int(transferTimeInSeconds)))
print("lost packets: %d" % (packetsLost))
print("average transfer rate: %d bytes per second" % (int(bytesPerSecond)))
print("max delay between two packets: " + formatMs(ticksToMs(maxDelta)))
print("min delay between two packets: " + formatMs(ticksToMs(minDelta)))