Serial Communication Between Arduinos with Bluetooth

Hi!

I’ve been trying to have two Beetle BLEs to communicate to each other with Bluetooth. One reads two analog sensors and constantly transmits data (two ints) to the other, so I use example 5 from the serial input basics tutorial by putting it in the receiving Arduino:

// Example 5 - Receive with start- and end-markers combined with parsing

const byte numChars = 255;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
    Serial.println("Enter data in this style <HelloWorld, 12, 24.7>  ");
    Serial.println();
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
}

The code works fine when I put something in the serial monitor (even when I put only two pieces of data in a bracket)…but not when I actually transmit data from another Arduino. Instead, the serial monitor of the receiving Arduino would either show nothing but the prompt or print the transmitting data verbatim. I wonder why? The transmitting Arduino is powered by external power.
Code of transmitting Arduino:

int const piezo1Pin = A3;
int const piezo2Pin = A2;

void setup() {
  Serial.begin(9600);
  pinMode(piezo1Pin, INPUT);
  pinMode(piezo2Pin, INPUT);
}

void loop()
{
 unsigned long timer = millis();
 int piezo1Value = analogRead(piezo1Pin);
 int piezo2Value = analogRead(piezo2Pin);
 Serial.print("<");
 Serial.print(piezo1Value);
 Serial.print(", ");
 Serial.print(piezo2Value);
 Serial.print(">");
 delay(20-millis()+timer);
}

Thanks!

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

You are sending 2 ints, why are you reading the first into a string? You are sending 2 bits of data but parsing for 3 (and the third is a float). You can't use that code unmodified. You need to modify the parse and show data functions to work with the 2 ints.

Hi Parabellum000, do you just want to get this to work or do you want to use Bluetooth LE as it was intended?

Right now, it looks like you are using the Bluetooth connection as a transparent bridge. You are basically turning your Bluetooth module into a RS-232 cable. You are creating serial protocol which you need to handle manually.

Bluetooth LE allows you to create characteristics that are discoverable. For instance, for your two sensors you would specify what those sensors measure. e.g. temperature and you would just store the values in those characteristics. But you would not “constantly transmit” them. Actualy your application layer would never send them.

If another Bluetooth device connects to your sensor device, it would discover the characteristics and read them when it wants/needs to. Also, the receiver can decide to only read one characteristic. e.g. a cheap display unit would read only the temperature but any expensive display unit would read temperature and humidity. The whole system is very open, flexible and low power.

Maybe your board does not allow you to use the full functionality of BLE and the manufacturer decided to make this look like a serial link.

Klaus_K:
Hi Parabellum000, do you just want to get this to work or do you want to use Bluetooth LE as it was intended?

I’m thinking about attaching two of the same sensors as the transmitting Arduino to the receiving Arduino, read the 4 sensors at the same time, and make some to-be-determined calculations based on these readings. Not sure which way works the best.

It's simpler and more reliable to use a proven serial transfer library instead of trying to create your own "packetizer" and "parser"

I would definitively give the library suggested by Power_Broker a go for now. It sounds like you want to do other stuff than the communication between your Arduinos.

Klaus_K: You are basically turning your Bluetooth module into a RS-232 cable.

How is it possible?

BT converts TTL signal to radio wave and vice versa.

RS232 cable converts RS232 logic to USB logic and vice versa.

How is it possible?

BT converts TTL signal to radio wave and vice versa.

RS232 cable converts RS232 logic to USB logic and vice versa.

It’s not literally, but from a functional point of view. The module reads the serial data and then provides them to the other module using BLE. The second module gives your application that serial stream. In your application you use Serial.print and Serial.read functions. And you need to handle all that. When do you send the data, how often, how do you encode the data ...

In BLE you can do this much more elegant, future prove, lower power, easier to program and flexible using characteristics.

Klaus_K: It’s not literally, but from a functional point of view. The module reads the serial data and then provides them to the other module using BLE. The second module gives your application that serial stream. In your application you use Serial.print and Serial.read functions. And you need to handle all that. When do you send the data, how often, how do you encode the data ...

In BLE you can do this much more elegant, future prove, lower power, easier to program and flexible using characteristics.

A proverb: A scientist becomes a popular writer when he describes his findings in public language.