How to build an ultra-reliable serial Bluetooth channel

I'm looking for some expert guidance on how to build a truly robust/reliable serial bluetooth channel for exchanging moderately large and varied data between two Arduino MEGA boards.

Over several (many!) years I've developed a large sketch running on a single MEGA that monitors a small electric vehicle, and displays and records the data as the vehicle moves around. The sketch compiles to around 60,000 bytes and is pretty reliable.

I'm working on a major revision to split the sketch between two MEGA boards connected by HC-05 serial bluetooth modules. I refer to these as the BASE and HEAD.

The BASE has all the sensors including GPS, voltage, current, temperature and air pressure.

The HEAD has an LCD display with keypad and microSD for data recording.

I've attached an example of the CSV data file that was recorded by the sketch prior to it being split. The data rate is moderate - one row is written to the CSV file every 200ms.

This same data will be recorded by the HEAD in the new dual MEGA with bluetooth design. I'm contemplating two alternatives for recording this data:

A) the BASE transmits each row of CSV data to the HEAD which then records each row to the SD card, and also breaks the data row up into constituent parts for display purposes, OR ...

B) the BASE transmits each piece of data (probably with a unique identifier for each type) to the HEAD which displays them, and also builds the data pieces into a row for recording in the CSV file.

My preference is Option A but either way I need the serial bluetooth channel between BASE and HEAD to be ultra robust i.e. no characters lost or dropped, ever! :slight_smile:

I've have a prototype work-in-progress with the two MEGA boards and two HC-05 communicating "hearbeats" using typical serial code, like this:

const char CJ_ID[] = "BlueEcho.a";
/* Assumes HC-05 Bluetooth module connected to MEGA  */

#include <Streaming.h>
#define bt Serial1                    // MEGA: TX1/RX1 (pins 18,19)
#define bt_baud 38400

void setup() {
  Serial.begin(115200);
  Serial << '\n' << CJ_ID << " [bt:" << bt_baud << ']'   << '\n';
  Serial << "==> Echo BT strings to Serial Monitor ... " << '\n';
  bt.begin(bt_baud);                  // if 38400 then compatible with AT command mode
  }

void loop() {
  processBTchars();
  //ocessBTbytes();
  delay(100);                         // small delay so we don't process faster than character/baud rate
  } 

void processBTchars(){
  char readChar;
  if (bt.available() > 0){
    Serial << "RX> ";
    while(bt.available() > 0){
      readChar = bt.read();
      //readChar = toupper(readChar);                    // convert lower case characters to upper case
      if (readChar !=  '\r' && readChar !=  '\n'){       // ignore CR/LF (hex: A/D)
        Serial << readChar;
        }
      }
    Serial << '\n';
    }
  }

void processBTbytes(){
  byte inByte; // = int inByte;
  if (bt.available() > 0){
    Serial << "RX> ";
    while(bt.available() > 0){
      inByte = bt.read();
      if (inByte !=  '\r' && inByte !=  '\n'){       // ignore CR/LF (hex: A/D)
        Serial << _HEX(inByte) << '|';
        }
      }
    Serial << '\n';
    }
  }

So far this is working quite well. It doesn't seem to be dropping any characters, but it occasionally starts a new line before reaching the line terminator, as shown in the Serial Monitor screenshots attached. Playing with the short delay(100) can change the displayed line length, or at the extreme if I leave the delay out altogether it will print just one character per line. So it seems I'll have to load the characters one by one into a buffer and only process the buffer after the terminator is received.

I went back and had a careful read of the Arduino language reference for Serial. I see several possible commands that may offer a better way to do this, like Serial.readBytesUntil() ... maybe !? But I see lots of options there that I'm not familiar with, leaving me wondering which one I should choose.

So to my question: how best to build a really robust/reliable serial bluetooth channel.

I've posted this under Project Guidance because I'm not just asking a coding question, I'm also keen for any alternatives for doing this over bluetooth. e.g. perhaps there is a better way using interrupts?

TIA

SCOO8u.zip (5.48 KB)

I missed the part where you explain why you can't have a wire beteeen them.

My preference is Option A but either way I need the serial bluetooth channel between BASE and HEAD to be ultra robust i.e. no characters lost or dropped, ever! :slight_smile:

So a communication method that is 'completly' error free ?

Sounds 'completly' unachievable to me, and you could never prove it of course.

If you find a way with Arduino, be sure to patent it, you would make Zillions.

MorganS:
I missed the part where you explain why you can't have a wire beteeen them.

The route between the BASE and the HEAD is very tight, difficult to access and exposed to the elements, passing hy moving parts that can chaff and wear wires. I've had all too frequent trouble with failures due to existing wires getting damaged.

Also I have a future aim to bluetooth data from Arduino to one of my old Android phones replacing the new HEAD.

srnet:
Sounds 'completly' unachievable to me, ...

hmmm maybe, but what if good error correction is added to the design so it becomes manageable.

I just had a quick scan of the Bluetooth Wikipedia page. It seems that the emulated serial port is a layer on top of the RFCOMM layer, which is reliable. If a packet is lost or corrupted, RFCOMM will catch it and send it again.

So long as you don't move out of range, this is likely to be more reliable than a piece of wire.

Job done!

ninja2:
I'm looking for some expert guidance on how to build a truly robust/reliable serial bluetooth channel for exchanging moderately large and varied data between two Arduino MEGA boards.

All you can do is send some data with an ID that allows the receiver to know if a complete message is missed and a checksum to allow the receiver to know if the data is corrupt. In either case the receiver can request a repeat.

I don't know what internal error checking exists in a Bluetooth system but I do know that the system used by a pair of nRF24L01+ modules is good - to the point where I would believe if the message is received it is the same as what was sent. To my mind using nRF24 modules gives you more control than Bluetooth as you can choose the channel (frequency) and the address of the recipient to minimise the risk of interference.

No wireless system is going to be as reliable as a wired system and no system that shares the work between 2 microprocessors will be as reliable as a system that only needs one.

...R
Simple nRF24L01+ Tutorial

MorganS:
So long as you don't move out of range, this is likely to be more reliable than a piece of wire.

Don't agree. Wireless is susceptible to interference in ways that a wired system is not.

...R

And a wire can pick up magnetic interference (from robot car motors) that don't affect a wireless system.

The wire is also subject to mechanical damage which is one of the OP's specific concerns.

ninja2:
hmmm maybe, but what if good error correction is added to the design so it becomes manageable.

Thats quite a very different requirement though.

Even if the Bluetooth comms itself is error checked, that error checking cannot be 100% reliable.

In particular even if the RF over the air Bluetooth has no errors, you still need to get the data out of the device itself. If that data is in the form of serial data then that serial data is prone to additional errors from supply noise and similar.

One of the very basic lessons of communications is that you need to plan for failure, not ignore it.

Your entire protocol logic is faulty, if you do not require a positive or negative feedback response to each sent message.

Paul

Thanks all for the ideas. I'm persisting with my current design and will see how I go.

The post by MorganS asking why don't I just use wires got me thinking - at least I can do this on my prototype to help assess if problems are due to bluetooth or not. So I tried hard wiring and it's immediately clear my current issues aren't due to bluetooth. So now I'm focussing on establishing reliable RX/TX design, hard wired for now, bluetooth later.

Robin2 your suggestion of WiFi is interesting, I'll save that idea in case Bluetooth proves too flakey. Meanwhile your post link led me to your Serial Input Basics tutorial, and that has been quite helpful. cheers

ninja2:
Robin2 your suggestion of WiFi is interesting, I'll save that idea in case Bluetooth proves too flakey.

I did not suggest WiFi - I suggested nRF24L01+ modules. They work on 2.4GHz but are completely different.

...R

Ak OK.
When I looked them up I just saw 2.4GHz and wireless ... and assumed WiFi, reading no deeper.

But now I know otherwise ...

ninja2:
When I looked them up I just saw 2.4GHz and wireless ... and assumed WiFi,

Bluetooth is also 2.4GHz wireless :slight_smile:

...R

learn something every day, and sometimes a few things :slight_smile: