This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Approach for serial over BLE?

Hello, we have kind of an in-house serial command protocol that we have used over Rs232, sockets, wifi, etc, and we would like to implement it over BLE. I am inheriting a good Nordic BLE project from a coworker, so I'm not expert in BLE yet, so please bear with me...

Our serial protocol is simple and framed, something like [command param1, param2... paramN|crc]. There is no max message length.

My understanding of BLE (from research and looking at my inherited code) is that a BLE interface is made up of one or more attributes which are a fixed length and act more or less like mailboxes... one side writes to an attribute, other side gets a notification that it has been updated and can read/use the data, and vice versa.

I need this interface to act like a serial port. My understanding from posts such as this:

devzone.nordicsemi.com/.../

is that if I want this, I need to implement it myself. So, the approach I'm toying around with is something like the below, which breaks the message up into several updates and uses the first two bytes as a length parameter. Pseudocode below.

Questions:

  • Do I suffer from some gross misunderstanding?
  • Is this a good way to implement serial over BLE (honestly this feels like the long way around; I'm surprised I have to do all this, maybe this is square peg round hole?)
  • Will I have timing issues? Seems like if the sender sends too fast, old updates could get overwritten with new before properly processed by other end (which is okay for a measurement, but very bad for serial data). For robustness do I have to incorporate some sort of "ready to receive" message back (what a pain this would be), or does BLE buffer these updates for me somehow?

Thanks very much for any thoughts.

SENDER PSEUDOCODE:

define ATTRIBUTE_LENGTH 20

void SerialOverBLEServer_TX(char *data, int length)
{
   while (length > 0)
   {
       if (length >= ATTRIBUTE_LENGTH)
       {   
          [set first two bytes to 20]
          [set rest of attribute to the next 18 bytes of serial data]
          length-=ATTRIBUTE_LENGTH);
          *data+=ATTRIBUTE_LENGTH);
       }
       else
       {   
          [set first two bytes to remaining length]
          [set rest of attribute to remaining serial data]
          length=0;
       }
       send_value (using sd_ble_gatts_hvx?)
   }       
 }

RECEIVER PSEUDOCODE:

void SerialOverBLE_RxHandler()  // notification on receiver that attribute is updated
{
    [Read the first two bytes as a length]
    [Process the appropriate remaining data as serial data]
}
Parents
  • You have a fairly good understanding of the situation I'd say.

    You may or may not need to implement anything though. Nordic were kind enough to give us a pre-programmed uart service. It can be found in the latest SDK docs here: this is a really good read

    Embrace this well-crafted and nearly comprehensive documentation. If you want to check out another SDK version, that's available too. I recommend getting a BLE book as well depending on how much you care to learn about the spec.

  • A little more info. I reviewed both the Nordic iOS app (which they provide as an example to use with the NUS -- Nordic UART service) source code and the NUS code itself. Below is an excerpt. Both ends seem to send strings with no regard for length, which suggests to me that the calling code has to be careful not to send too-long strings, so for long input I'd have to slice and dice it myself, as above, anyway. Correct? And if the NUS assumes data that fits into a message. I would presume that it's not doing anything for me in terms of timing high-speed input. Would you agree?

    The valuable thing I've learned pulling that thread is that there is a "length" parameter, maybe I could use this instead of my two-byte encoding?

    (code to follow)

Reply
  • A little more info. I reviewed both the Nordic iOS app (which they provide as an example to use with the NUS -- Nordic UART service) source code and the NUS code itself. Below is an excerpt. Both ends seem to send strings with no regard for length, which suggests to me that the calling code has to be careful not to send too-long strings, so for long input I'd have to slice and dice it myself, as above, anyway. Correct? And if the NUS assumes data that fits into a message. I would presume that it's not doing anything for me in terms of timing high-speed input. Would you agree?

    The valuable thing I've learned pulling that thread is that there is a "length" parameter, maybe I could use this instead of my two-byte encoding?

    (code to follow)

Children
No Data
Related