constraints on data rates thru dongle

wjcroftwjcroft Mount Shasta, CA
edited May 2016 in Cyton
On another thread , @ceremona asked about bluetooth constraints on sample rate. I split that question out here to a separate thread. The original question:

Hiya folks,  ...

Wanting to
clarify (if anyone knows) where the data speed constraint is for the
250hz sample rate?  If I bypass the rfduino can I up the sample rate, or
does that sample speed limitation exist further upstream?

Thanks, Cere


Here is a previous thread where some data rate calculations were tossed around, along with the idea of compression schemes.

Joel @biomurph should add a comment here, but he once mentioned that the dongle link is using a special high speed bluetooth mode that Nordic provides, called Gazelle. And that this was getting us about 130K bits/sec. But note that the data rate without the dongle, BLE, is much lower.

Ignoring the extra bytes of packet overhead for the moment,

((8 channels * 24 bits) + (3 axes * 16 bits)) * 250 sps = (192 + 48) * 250 = 60 Kbps of data to move

I'd like to hear what the actual measured values are, since there is not only packet overhead, but possibly also interpacket delays / flow control as well.


PS some Gazelle docs,
PPS interesting note by the BlueGiga people on BLE data rates; these guys seem to have missed the GZLL concept,


  • biomurphbiomurph Brooklyn, NY
    There is a page in our Docs that discusses the data packet format here

    The uC (8bit or 32bit) sends the following to the RFduino Device:

    1 byte sample counter
    8x3 bytes ADS data
    3x2 bytes Accelerometer data

    The RFduino Device adds a packet counter byte as checksum, for a total of 32bytes per data packet.
    That happens to be the max number of bytes that can be put into a packet when using the RFduinos and the Gazelle stack.

    Right now, the limiting factor in terms of data transmission is the serial connection between the uC (ATmega or PIC) and the RFduino on the OpenBCI board. The RFduino on the board is setup as a Device, and the RFduino on the Dongle is setup as a Host. That's how they have to be. Turns out the Device is not able to run it's serial port above 115200 baud. I've tried a number of different tricks to get around this, and haven't got above that baud rate. Tried rolling my own software serial, fastest I can get is ~115200. Even took a stab at switching the UART into a I2C bus, but that was just too complicated. 

    If it becomes possible to increase the baud rate between the uC and the RFduino, then the limiting factor for data rates would be the radio link. Based on some tests done last summer, I think that with the right kind of buffering we should be able to get 500SPS, but the 115200 baud limit is not allowing that.

    That is one of the reasons for adding the SD card slot, for local raw data storage. 

    Something that we have not explored is compression...
  • wjcroftwjcroft Mount Shasta, CA
    edited January 2015
    Found some folks discussing both I2C and SPI transfers between RFduino's or another uC and RFduino. It appears neither library on RFduino support slave mode transfers. But...  The I2C case could be implemented in software (according to the RFduino team member).

    More related posts,


    PS one other thought on I2C master vs. slave modes. Couldnt the uC (ATmega or PIC) and the RFduino do some kind of "mode switching" operation where the uC alerts the RFduino that a packet is ready to send. Then the RFduino drops into I2C master mode for the transmission; and the uC acts as a I2C slave. When the packet is finished then the link goes back 'normal' mode.

  • edited January 2015
    I think there is one more idea (besides compression) which I don't think has been discussed: customizable data packet.

    Currently the V3 packet is constant (33 bytes), it delivers 8 (or 16) EEG channels at 250 (or 125) SPS. With 115kb serial port limitation this is all we can get over the wireless link.

    It would be great we the data packet could be dynamically customized, so that we can request independently:
    1. how many channels (1..16),
    2. how much precision (e.g. 16 bit or 24 bit samples)
    3. and at what SPS  (250, 500, 1000).

    That way, if someone wants 16 channels at 250sps, they can select lower precision (16 bit samples).

    Or, if someone needs just 1 or 2 channels but at higher SPS (this could be the most common use of the device!), it would be also possible even over slowest Bluetooth.

    As long as SAMPLE_RATE * CHANNEL_COUNT * BYTES_PER_SAMPLE is less than ~1150 it would work.

    Then it would be up to the client software (like BioEra or Brainbay) to make sure the required bandwidth is not exceeded.

    Something like that would be more challenging to implement in the firmware. In fact I don't know if such firmware is even possible.

    But it would provide ultimate flexibility so perhaps is something to consider.

  • biomurphbiomurph Brooklyn, NY
    That's a great idea Jarek!
    I will look into how best that could be integrated.
  • biomurphbiomurph Brooklyn, NY
    William, I have taken a look at using I2C, and there are some issues in both the 8bit and 32bit systems that limit usability.

    First, the ATmega and PIC are both tied to the RFduino Device via UART (TX, RX) pins. We use the UART to communicate, and it is the only way to upload new firmware to the target uC (ATmega or PIC), so UART functionality is necessary on these pins.

    I did look into switching their functionality (from UART to I2C), but it is profoundly difficult because the I2C bus is a hardware peripheral with dedicated pins on both the ATmega and the PIC32. In the case of the ATmega, the I2C is a hardware peripheral with dedicated SDA and SCL pins (they are A4 and A5). And on the PIC, there are two I2C buses on dedicated pins (I2C is not re-mappable using PPS). So, I did take a stab at working an I2C connection between the pins that are already connected by rolling a software I2C, but that was a disaster. The RFduino really doesn't like to do much when it's got a radio stack running. In all my attempts at increaseing data rates in software (soft Serial, soft I2C) I wasn't able to get anything faster than 115200.

    I2C may be possible if the boards are hacked (green-wired) to connect the hardware specific I2C pins from ATmega/PIC, and run the RFduino as a I2C Master.

    That would require some extra hand-shaking at least so that the RFduino can ask for new sample data in a timely fashion. For example, when ATmega or PIC gets new ADS data, it would toggle a pin connected to RFduino HIGH. Then the RFduino would request data from the uC via I2C... Not a bad little hack. I should lash something together and do a write up about it.

    As far as SPI, well it would be possible to connect the RFduino to the SPI bus, essentially bypassing the uC, and have it talk to the ADS1299 directly. We debated doing that over the summer (throwing out the ATmega and PIC) but we felt we had committed to our Kickstarter backers...

  • wjcroftwjcroft Mount Shasta, CA
    edited January 2015

    re: 115200 max serial receive baud rate for data packets sent to onboard RFduino

    Do you think this is due to some "interference" from interrupts / callbacks from the radio link? In other words the UART on the RFduino may only have a single byte for buffering and if a radio callback causes that to overflow, your data packet sent gets garbled.

    Is there any way to adjust the radio interrupt to avoid this? Such as either temporarily disabling it (for the duration of one packet.) Or setting up your serial receive interrupt at a higher priority level?

    31 bytes @ 230400 bps = 1.3 ms
     @250000 bps = 1.2 ms
     @921600 bps = .33 ms

    Some UARTs even support "hardware flow control" such that an extra line logic level stays low until the UART receive buffer is available. But you've probably thought of these already...  :-)



    PS in the BLE world, since it is so much more intrusive interrupt wise, they have this API call,

    PPS this post suggests using baud rates that divide well into the 16Mhz clock, assuming that is divided down by the UART. Such as 250K or 500K bps. (looks like RFduino can do 250K but not 500K)
  • biomurphbiomurph Brooklyn, NY
    In short, yes. 

    There is something happening under the RFduinoGZLL wrapper and inside the Nordic Gazelle stack that disrupts the serial connection when the RFduino is set up as a Device. 
    When RFduino is set up as a Host (like on the Dongle) I am able to run the serial (via FTDI) up to 1M baud. 

    The RFduino libraries that we have up on our github are custom builds from RFdigital. We got them to address a problem that we were having over the summer that was causing us to drop alot of packets. From what I understand, they forced Gazelle to not do channel hopping, or something like that. They also gave us the multiple channels to select from.

    Whatever Gazelle is doing, it also limits (at least my) ability to roll my own software serial or soft I2C.
    Writing soft I2C is not trivial, by the way...
    It's not wise to turn Gazelle on and off, I don't think. Haven't tried it tho...

    Your timing is correct. If we can decrease the transmit time between the uC and the RFduino on OpenBCI board, then we can 
    acquire more samples per second
    sample more channels of input

    These are the available baud rates from the RFduino library
    From the file RFduino/system/RFduino/include/nrf51_bitfields.h

    #define UART_BAUDRATE_BAUDRATE_Baud1200 (0x0004F000UL) /*!< 1200 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud2400 (0x0009D000UL) /*!< 2400 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud4800 (0x0013B000UL) /*!< 4800 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud9600 (0x00275000UL) /*!< 9600 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud14400 (0x003B0000UL) /*!< 14400 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud19200 (0x004EA000UL) /*!< 19200 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud28800 (0x0075F000UL) /*!< 28800 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud38400 (0x009D5000UL) /*!< 38400 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud57600 (0x00EBF000UL) /*!< 57600 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud76800 (0x013A9000UL) /*!< 76800 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud115200 (0x01D7E000UL) /*!< 115200 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud230400 (0x03AFB000UL) /*!< 230400 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud250000 (0x04000000UL) /*!< 250000 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud460800 (0x075F7000UL) /*!< 460800 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud921600 (0x0EBEDFA4UL) /*!< 921600 baud. */
    #define UART_BAUDRATE_BAUDRATE_Baud1M (0x10000000UL) /*!< 1M baud. */

  • biomurphbiomurph Brooklyn, NY
    Further issues to bear in mind regarding UART baud rate increase.

    avrdude uploads code to the PIC and ATmega at 115200 baud.
    When put into bootloader mode, both the PIC and the ATmega bootloaders run their serial ports at 115200. 

    Any changes in the Device or Host to the baud rate during run-time will have to switch back to 115200 in the event that the user want's to upload code to the target uC. That meands some kind of handshaking of sorts is going to be necessary...

    The Device doesn't care what the Host local baud rate is, and vice-versa, but the connection between the Host and PC, and the Device and target uC would need some extra care in baud rate switching on-the-fly. Not saying this is impossible, just more difficult.

    Best bet would be to change baud rates during streamingData mode only, and go back to 115200 during 'normal' mode in order to accomodate avrdude.
  • biomurphbiomurph Brooklyn, NY
    edited January 2015
    The 32bit board has some usability issues when it comes to the hardware I2C...

    This PIC has two I2C busses. They are committed to the following IC pins
    • SCL1
      • IC pin 17
      • chipKIT pin D2
      • OpenBCI Function: SC card SS
    • SDA1
      • IC pin 18
      • chipKIT pin D3
      • OpenBCI Function: Daisy SS

    • SCL2
      • IC pin 15
      • chipKIT pin D14
      • OpenBCI Function: Serial TX
    • SDA2
      • IC pin 14
      • chipKIT pin D13
      • OpenBCI Function: Available GPIO

    So, It looks like the hardware I2C bus is a bust for the PIC without doing some serious surgery.

    It still may be possible to roll a software I2C slave using the available pins that are broken out...

    the 8bit Board has A4 and A5 broken out, which are the I2C pins for Arduino UNO. That would require a simple lash-up....
  • biomurphbiomurph Brooklyn, NY
    I reached out to the folks at RFdigital about the notion of adjusting the NVIC to give the UART interrupts more priority. Here's what they said.

    The version of GZLL that you are using uses 700uS timeslots.

    You can send 1 packet (32bytes max) every 1.4ms (2 timeslots).

    1000 / 1.4 * 32byte packets * 8 = 182kbit/s

    182kbit would be the absolute theoretical max you can achieve. If the software interruupt priorities for the radio are reduced to that which is lower than the UART, then you will begin to lose radio packets.

    The only way to increase the UART baud rate above 115200 at this point would be to use flow control.

    Our serial library currently doesn't have flow control implemented, so it will be something you would have to add support for. Also, the Arduino serial library doesn't have flow control support, so support would needed to be added for it as well.

    So, there you go
  • I take it that the RFduino stack is closed source and user code is running in a VM?

    This seems like this should be a fairly easy to deal with issue, if the source were available.

    I can't believe that they're so fraudulently misrepresenting the specs on this device!
Sign In or Register to comment.