Embedded Bluetooth Classic, Apple, and The French
Back in the days of my last company, Bluetooth Low Energy wasn’t yet a ‘thing’ - so there weren’t that many modules out, and iOS/Android support wasn’t great either. Our product’s required data transfer from the hardware to phone was over 10kB/s and BLE wouldn’t remotely touch that number when talking to iOS.
Supposedly those numbers are ‘achievable’ today, but I haven’t seen it - I’m waiting for the BLE 5.0 chips to come around, then I’ll revisit this.
The needed bandwidth required us to use Bluetooth Classic, which I didn’t mind at all because on Android and Windows phones - it’s fast, stable, almost problem free… However, on iOS, it is a complete nightmare due to the requirement of joining the MFi program. Technically, I can’t speak much about MFi due to the NDAs you need to sign when joining, but in reality, I don’t want to talk about it because I’m trying to block that part of my life out.
MFi is the most black-box registration/information system I’ve encountered, and even worse and slower than trying to get information from the French bureaucracy.
Digression: I don’t say the “French bureaucracy” as a stereotype - I lived in France for 2 years and I applied for my health card 3 days after I arrived. The card was mailed to my apartment 2 years, 2 months, 2 days later.
Classic Doesn’t Mean Bad
In the Bluetooth Classic world, the RN42 is a staple because it’s usually pretty easy to interact with, Sparkfun sells it, etc… This module worked fine for us on Android and Windows. However, when building for MFi, there is a special authentication coprocessor you need to use and interact with - and this requires writing custom firmware to handle authentication, or getting a Bluetooth Classic module which has that authentication already programmed in.
In RN42-land, that is the RN42-iAP module, which was an exorbitant $700 development kit from Microchip - but it worked… Kinda…
After messing around with it for a month and trying to get ANY support along the way, I discovered that it has a pretty horrible throughput that was not documented ANYWHERE, and when I confronted the Microchip guys about it, they finally admitted they knew about it (after playing dumb for a month).
Because of their underpowered hardware, and what I will call very poor firmware development, the iAP version of the RN42 had many issues. In Android mode - everything worked basically the same as always (but a bit slower), however in Apple mode, the throughput was limited to a pathetic 3kB/s (which put it on par with BLE at the time).
Switching Away From Microchip
Throwing that module away, and due to the lost time, I didn’t want to get a CSR BlueCore5 and then write all the authentication firmware myself - I looked around for other modules.
In the past, I had contacted AmpedRF about their modules which looked pretty interesting - but I never heard a reply. A short while later, ST approached me about using their SPBT2632 modules which I saw were clearly the AmpedRF modules, but white-labeled.
Another Digression: It turns out that AmpedRF uses an STM32 under the hood, writes the firmware and Bluetooth stack, and both sells them directly and white-labels them back to ST. Pretty interesting relationship.
This was a nice little chip that was relatively easy to use, and we could get a reasonable price on. The real downside of this module is that ST has NO clue how to support it. All of my support questions were bounced back to AmpedRF, because the ST guys covering this module knew nothing about it.
ST Bluetooth Support Rant
This is unrelated to the post, however, I need to get this out (please note, this all happened almost 2 years ago and I’m still angry about it).
I’m a big fan of ST Microcontrollers, but man, from a support perspective, ST’s Bluetooth division was an absolutely horrible experience.
The following performance settings and results I’m displaying comes from 77 emails over 8 weeks.
There was an entirely other set of support complaints that took 5 weeks, 100 emails, and my circumventing the system to get information from ST in another continent/language to learn that (again) this was a known issue and that they were working on new firmware to fix it.
Yet in about 80 of my emails, the claim was “we cannot reproduce, this is a (your) hardware problem”… I don’t know if this was lying or just a big bureaucracy - but either one isn’t good. To convince them it wasn’t my issue, I had to literally debug a black box and show them that (e.g.) sending a full stream of data causes the module to reset after 30 seconds, however, streaming at full speed, then waiting for 5ms between packets will succeed. Sad…
Anyways, without further ado, here are my configuration settings for that module and the results I achieved on iOS with them (on Android, I could achieve about 30kB/s).
System Configuration Settings - Version 1.5 var01 BuildVersion = 130322D IDPS var03 BD_ADDR = 00043e250013 var04 DeviceName = Amp'ed Up! var05 StreamingSerial = false var06 PIN = 1234 var07 UartBaudrate = 460800 var08 UartParity = none var09 UartDataBits = 8 var10 UartStopBits = 1 var11 UartTimeout = 16 var12 AutoSniff = false var13 AutoSniffTimeout = 5 var14 AutoSniffInterval = 1000 var15 HostShallowSleepEnable = true var16 HostDeepSleepEnable = false var17 GPIO_HostKeepAwake = none var18 GPIO_HostWakeup = none var19 UseSmallPackets = false var20 EnableAFH = true var21 EnablePowerControl = true var22 HostFlowControl = 0 var23 ATReply = AT-AB var24 QoS_Latency = 20 var25 CpuMHz = 36 var26 HciBaudrate = 2250000 var27 SPIEnable = false var28 SPIMode = slave var29 I2CEnable = false var30 COD = 240404 var32 HostEvents = true var33 BondingAllowed = true var34 PageScan = true var35 InquiryScan = true var36 MPMode = 0 var37 UseExtLPO = false var39 EnableEncryption = true var40 DefaultSecurity = 4 var41 DefaultAuthentication = 5 var42 EnableIAP = true var43 AllowSniff = false var44 iAPAppID = A1B2C3D4E5 var45 iAPProtocolStrMain = com.AmpedRFTech.Demo var46 iAPProtocolStrAlt = com.AmpedRFTech.ProtocolAlt var47 CPI2CMode = 3 var48 SPP128UUID = true var49 EnableRPN = false var51 RmtEscapeSequence = false var52 SimpleRemoteLingo = false var53 CreditMax = 5 var54 PageScanInterlaced = false var55 MITMEvent = false var56 AltCPGPIO = true var57 InMtuSize = 520 var58 OutMtuSize = 520
The test configuration looked like this:
- BT33 dev board
- AmpedRF Firmware Test Tool
- ST Blue Term
- Sending 300,000 bytes total
I modded the ST Blue Term app which may have helped to improve the speed slightly. I removed all UI text updating and also increased EAD_INPUT_BUFFER_SIZE from 350 to 520. Updating the buffer size seemed to give an extra 1000 bytes/s or so.
The dev board and device were sitting right next to each other (best case distance scenario), and there were 3-4 tests per device.
iOS Test Results
With the default chip settings, the throughputs were generally 8,000-11,000 bytes/s
Here are the much improved new settings, as listed above:
- iPad Mini running iOS 7.0.4 - 18,500-20,500 bytes/s
- iPhone 5S running iOS 7.0.4 - 14,000-15,000 bytes/s
- iPod Touch running iOS 7.0.4 - 16,000-17 000 bytes/s
- iPod Touch running iOS 6.1.3 - 19,000-20,000 bytes/s
An overall note is that the HCI baud rate and the MTU sizes were the two biggest factors affecting throughput speed (with iOS device coming in a close 3rd).
Finally, here and here are some StackOverflow posts related to this hellish journey.