{"id":4279,"date":"2015-12-19T19:20:04","date_gmt":"2015-12-20T03:20:04","guid":{"rendered":"http:\/\/www.corbinstreehouse.com\/blog\/?p=4279"},"modified":"2018-11-03T13:35:39","modified_gmt":"2018-11-03T20:35:39","slug":"adafruit-bluetooth-le-spi-friend-with-data-loss-and-stalls-infinite-loops","status":"publish","type":"post","link":"https:\/\/www.corbinstreehouse.com\/blog\/2015\/12\/adafruit-bluetooth-le-spi-friend-with-data-loss-and-stalls-infinite-loops\/","title":{"rendered":"Adafruit  Bluetooth LE SPI &#8220;Friend&#8221; with data loss and stalls (infinite loops)"},"content":{"rendered":"<p id=\"top\" \/>\n<p>I&#8217;m working on adding bluetooth support to my LED cyr wheel. \u00a0A long time ago I picked up an <a href=\"https:\/\/www.adafruit.com\/products\/1697\">Adafruit nRF8001 breakout board<\/a>\u00a0\u2014 I was worried it was too big to fit in my wheel, and once I started working with it I realized it sucked. Specifically, the API was limiting; you couldn\u2019t even set the peripheral\u2019s name to something longer than 8 characters! Luckily they now have an \u201c<a href=\"https:\/\/www.adafruit.com\/product\/2633\">Bluefruit SPI Friend<\/a>\u201d, so I got one of those. Well, I ended up accidentally getting two. The first one I had sent via USPS, and it took 3 weeks to arrive! I thought it was lost, and I had to order another one via UPS 3 day shipping, and of course\u2026they both arrive on the same day.\u00a0<\/p>\n<p>The Bluefruit LE Friend is interesting. Adafruit\u2019s produce page doesn\u2019t even mention what chip it runs. You can discover it if you read their \u201cintro page&#8221;; a long ways down they mention a\u00a0nRF51822 flash updated, and you realize it is a\u00a0nRF51 based ship from Nordic. \u00a0I\u2019m hoping they will fix their page to be a little more clear on what is being used. The way it works is they created some closed source code that runs on the\u00a0nRF51822 chip using the Nordic SDK. Their code talks to your microprocessor (Teensy\/Arduino\/etc) via SPI or UART. I picked SPI, because I thought it would be better and faster\u2026but their implementation basically forces it to be UART. I was really hoping for regular callbacks for characteristic updates\u2026but you don\u2019t get those. You have to poll it using \u201cAT\u201d commands, and then parse the AT response. This is horribly slow, and the underlying SPI mechanism uses some special \u201cSimple Data Transport\u201d mechanism that transfers at most a 16 byte payload at a time. That is not good considering bluetooth transfers 20 bytes max at a time. Well, you can do more if you have more control, like from iPhone to iPhone\u2026but not so with the nRF51 from what I can tell.\u00a0<\/p>\n<p>The only way for you to quickly read data with the Bluefruit LE friend is to use their UART service which provides a transmit and receive characteristic. When you do this, the SPI protocol lets you receive packets at their SPI transfer packet size (yeah, just 16 bytes of \u201cpayload&#8221;, which is terrible..). \u00a0I figured I\u2019d try it out.<\/p>\n<p>I wrote a Mac app that connects to the Bluefruit LE. I chunk up data into 20 byte sizes, and send it (until I\u2019m done) in: (Swift code):<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0\u00a0<span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">func<\/span> peripheral(peripheral: <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">CBPeripheral<\/span>, didWriteValueForCharacteristic characteristic: <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">CBCharacteristic<\/span>, error: <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">NSError<\/span>?) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\"><span>\u00a0 \u00a0 \u00a0 <\/span><span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">if<\/span> characteristic == <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_uartTransmitCharacteristic<\/span> {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">let<\/span> dataLeft = <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataToSend<\/span>!.<span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">length<\/span> &#8211; <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataOffset<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">if<\/span> dataLeft &gt; <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span> {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">let<\/span> amountToSend = <span style=\"font-variant-ligatures: no-common-ligatures; color: #3d1d81;\">min<\/span>(dataLeft, <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataChunkSize<\/span>)<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">let<\/span> subData: <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">NSData<\/span> = <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataToSend<\/span>!.<span style=\"font-variant-ligatures: no-common-ligatures; color: #3d1d81;\">subdataWithRange<\/span>(<span style=\"font-variant-ligatures: no-common-ligatures; color: #3d1d81;\">NSMakeRange<\/span>(<span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataOffset<\/span>, amountToSend))<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_dataOffset<\/span> += subData.<span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">length<\/span><\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #008400;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 peripheral.<span style=\"font-variant-ligatures: no-common-ligatures; color: #3d1d81;\">writeValue<\/span>(subData, forCharacteristic: <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">_uartTransmitCharacteristic<\/span>!, type: <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">CBCharacteristicWriteType<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #3d1d81;\">WithResponse<\/span>)<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;\">\u00a0\u00a0 \u00a0 \u00a0 \u00a0<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 }<\/p>\n<p>\u00a0 \u00a0\u00a0<\/p>\n<p>In my Teensy\/Arduino code, I would read it. This a pure hack for testing the sending of data:<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0<span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">if<\/span> (<span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">m_ble<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">available<\/span>()) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">int<\/span> count = <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">uint32_t<\/span> start = <span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">millis<\/span>();<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #008400;\"><span style=\"font-variant-ligatures: no-common-ligatures; color: #000000;\">\u00a0 \u00a0 \u00a0 \u00a0 <\/span>\/\/ Read in the size<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">int32_t<\/span> totalBytes = <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0\u00a0<span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">m_ble<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">readBytes<\/span>((<span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">char<\/span>*)&amp;totalBytes, <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">sizeof<\/span>(totalBytes)); <span style=\"font-variant-ligatures: no-common-ligatures; color: #008400;\">\/\/ skanky!<\/span><\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;\">\u00a0\u00a0 \u00a0 \u00a0 \u00a0<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #78492a;\">#define bufferSize <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">1024<\/span><\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">uint8_t<\/span> buffer[<span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">bufferSize<\/span>];<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;\">\u00a0\u00a0 \u00a0 \u00a0 \u00a0<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">DEBUG_PRINTF<\/span>(<span style=\"font-variant-ligatures: no-common-ligatures; color: #d12f1b;\">&#8220;totalBytes: %d\\r\\n&#8221;<\/span>, totalBytes);<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">if<\/span> (totalBytes &gt; <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">int<\/span> sizeLeft = totalBytes;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">uint32_t<\/span> lastReadTime = <span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">millis<\/span>();<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">while<\/span> (sizeLeft &gt; <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">while<\/span> (!<span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">m_ble<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">available<\/span>()) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">if<\/span> (<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">millis<\/span>() &#8211; lastReadTime &gt; <span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">BT_FILE_READ_TIMEOUT<\/span>) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">DEBUG_PRINTF<\/span>(<span style=\"font-variant-ligatures: no-common-ligatures; color: #d12f1b;\">&#8220;timeout! read: %d\/%d\\r\\n&#8221;<\/span>, count, totalBytes);<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sizeLeft = <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">break<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #008400;\">\/\/ TODO: errors<\/span><\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #008400;\">\u00a0<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">int<\/span> read = <span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">0<\/span>;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">while<\/span> (<span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">m_ble<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">available<\/span>()) {<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">int<\/span> amountToRead = <span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">min<\/span>(sizeLeft, <span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">bufferSize<\/span>);<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #bb2ca2;\">int<\/span> amountRead = <span style=\"font-variant-ligatures: no-common-ligatures; color: #4f8187;\">m_ble<\/span>.<span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">readBytes<\/span>(buffer, amountToRead);<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;\">\u00a0\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #008400;\">\/\/\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DEBUG_PRINTF(&#8220;%c&#8221;, m_ble.read());<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 count += amountRead;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sizeLeft -= amountRead;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 lastReadTime = <span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">millis<\/span>();<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 read += amountRead;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 }<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"font-variant-ligatures: no-common-ligatures; color: #703daa;\">uint32_t<\/span> time = <span style=\"font-variant-ligatures: no-common-ligatures; color: #31595d;\">millis<\/span>() &#8211; start;<\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: #d12f1b;\"><span style=\"font-variant-ligatures: no-common-ligatures; color: #000000;\">\u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-variant-ligatures: no-common-ligatures; color: #78492a;\">DEBUG_PRINTF<\/span><span style=\"font-variant-ligatures: no-common-ligatures; color: #000000;\">(<\/span>&#8221;\u00a0 read %d, time took: %d ms, %g s\\r\\n&#8221;<span style=\"font-variant-ligatures: no-common-ligatures; color: #000000;\">, count, time, time \/<\/span><span style=\"font-variant-ligatures: no-common-ligatures; color: #272ad8;\">1000.0<\/span><span style=\"font-variant-ligatures: no-common-ligatures; color: #000000;\"> );<\/span><\/p>\n<p style=\"margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;\">\u00a0 \u00a0 }<\/p>\n<p>\u00a0<\/p>\n<p>This works, but I was frequently seeing my Teensy \u201clock up\u201d. I realized some code was infinite looping in the SPI layer\u2026but adding in logs was allowing it to work. This told me they had timing issues with a fast chip. Doh! But\u2026even so packets wouldn\u2019t come complete..and guess what \u2014 they were 16 of the 20 bytes I was expecting! \u00a0So, clearly this was something in the Bluefruit SPI layer.<\/p>\n<p>I don\u2019t really know SPI, but I took the time to learn how all their code worked, and figured out what was wrong. It makes sense, and I fixed it on a clone\/fork:<\/p>\n<p><a href=\"https:\/\/github.com\/corbinstreehouse\/Adafruit_BluefruitLE_nRF51\">https:\/\/github.com\/corbinstreehouse\/Adafruit_BluefruitLE_nRF51<\/a><\/p>\n<p>\u00a0I sent them a pull request.. we\u2019ll see what happens!<\/p>\n<p>For everyone else\u2026use my code.<\/p>\n<p>\u00a0<\/p>\n<p>Unfortunately, this mechanism is too slow. It takes 9.5-10 seconds to transfer 1kB. 270kB files would take 45 minutes to send over! \u00a0So, I\u2019m looking into faster options..which I think means writing custom firmware with a RedBearLab BLE Nano.\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m working on adding bluetooth support to my LED cyr wheel. \u00a0A long time ago I picked up an Adafruit nRF8001 breakout board\u00a0\u2014 I was worried it was too big to fit in my wheel,&#8230; <a class=\"read-more\" href=\"https:\/\/www.corbinstreehouse.com\/blog\/2015\/12\/adafruit-bluetooth-le-spi-friend-with-data-loss-and-stalls-infinite-loops\/\">[read more]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4279","post","type-post","status-publish","format-standard","hentry","category-general"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/posts\/4279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/comments?post=4279"}],"version-history":[{"count":1,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/posts\/4279\/revisions"}],"predecessor-version":[{"id":4280,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/posts\/4279\/revisions\/4280"}],"wp:attachment":[{"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/media?parent=4279"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/categories?post=4279"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.corbinstreehouse.com\/blog\/wp-json\/wp\/v2\/tags?post=4279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}