Problems reading a bluetooth data stream

SteveSFX

Well-known member
Hi all

I have a simple app written in MIT App inventor 2. It's throwing out a text data stream once a second as a text file arranged as the following:

Y
###
###
###
\n

The Y at the beginning lets me know the set of data that I am receiving (in this case, 3 sets of 3 digits). That appears to work fine.
I am using the first letter to determine the following data's job.

The following 9 digits are 3x sets of numerical data. If the Bluetooth module sends a 1 for instance, then it always sends the data as 3 digits (so it sends 001). The variable is always between 0-100.

Maybe this is an odd way of sending the data, but I thought it would work.

But, HC-06 is connected to my Teensy 3.2 and I am having difficulty reading this data effectively. Is once a second too often? I would have thought not.

Excuse the scruffy code, it's prototyping time.

Now there is a delay(30) in the serial reading loop which I know is a big no-no, but it actually works better like that.
I will bin all the serial prints, once I know it is working.

What is a better way to read the incoming BT data? Surely it need to decide that there is data, then loop putting that data into commandbuffer[btcount] until it reaches \n.

Any assistance gratefully received.

Code:
#include <wavTrigger.h>                           //Wav trigger library for SFX and music

wavTrigger wTrig;                                   //Initialise the wav trigger

int led = 13;

//------------------ Variables ----------------------

int  gRateOffset = 0;                              // WAV Trigger sample-rate offset
int  gNumTracks;                                   // Number of tracks on SD card

char gWTrigVersion[VERSION_STRING_LEN];            // WAV Trigger version string

char commandbuffer[50];
int Size_of_Assembled_array;                       // The length of the assembled array, including empty spaces
int btcount;

long actualenginevolume;                           // The volume we are currently using
long pitch = -32767;                                 // Current pitch of the engine sound effect

byte enginevolumelevel;                            // Incoming data
byte sfxvolumelevel;
byte vehiclespeed;
byte startsound;
byte startgyro;
byte stopsound;
byte stopgyro;
byte enginesound;
byte sfx1;
byte sfx2;
byte sfx3;

byte oldenginevolumelevel;
byte oldsfxvolumelevel;
byte oldvehiclespeed;
//----------------------------------------------------------------------------------------------------------------------------------------------
void setup() {

  pinMode(led, OUTPUT);

  Serial.begin(9600);                              // Debug serial
  Serial2.begin(9600);                             // Serial comms to the BT module

  delay(1000);

  //-------- Setup the Wav Trigger board -------------

  wTrig.start();                          // Setup the wav trigger
  delay(100);
  wTrig.stopAllTracks();                  // Stop all the tracks
  delay(100);
  wTrig.samplerateOffset(0);              // Set the sample rate to 0
  wTrig.setReporting(true);
  delay(100);

  wTrig.masterGain(-70);                  // Reset the master volume gain off the WAV trigger (-70 to +4)

  delay(500);

  if (wTrig.getVersion(gWTrigVersion, VERSION_STRING_LEN)) {
    Serial.print(gWTrigVersion);
    Serial.print("\n");
    gNumTracks = wTrig.getNumTracks();
    Serial.print("Number of WAV tracks = ");
    Serial.print(gNumTracks);
    Serial.print("\n");
  }
  else {
    Serial.print("WAV Trigger response not available");
  }

  //---------------- Set up the Bluetooth ----------------

  Serial.println("Setting up Bluetooth");

  delay(1000);
  Serial2.write("AT+NAMEBornSFX");                                                                                     // Set up the bluetooth
  delay(1000);
  Serial2.write("AT+PIN1234");
  delay(1000);
  Serial2.write("AT+BAUD4");
  Serial.println(F("Bluetooth configuration complete"));

  //------------------------------------------------------


  wTrig.trackPlayPoly(64);                               // Play track 64
  delay(1000);

  wTrig.samplerateOffset(-32767);                        // -32767 = one octave down.    +32767 = Up one octave
  wTrig.trackPlayPoly(90);                               // Play track 90
  wTrig.trackLoop(90, 1);                                // Turn looping of the track on

  delay(1500);

}


//==============================================================================================================================================
void loop() {

  if (Serial2.available()) {                                                                                                 // If there is BT data, go and get it

    do {
      commandbuffer[btcount++] = Serial2.read();
      delay(30);
    } while ((Serial2.available()) && (btcount < 50));
    Size_of_Assembled_array = sizeof(commandbuffer);

      Serial.print("Incoming data: ");Serial.println(commandbuffer);


    if (btcount > 0) {                                                                                                      // If something has arrived, then check it
      Serial.println(" ");
      btcount = 0;

      if (commandbuffer[0] == 'X') {                                                                                        // Full data received (after leaving settings or at app boot)
        enginevolumelevel = (((commandbuffer[1] - 48) * 100) + ((commandbuffer[2] - 48) * 10) + (commandbuffer[3] - 48));
        Serial.print("Engine Volume: "); Serial.println(enginevolumelevel);

        sfxvolumelevel = (((commandbuffer[4] - 48) * 100) + ((commandbuffer[5] - 48) * 10) + (commandbuffer[6] - 48));
        Serial.print("SFX Volume: "); Serial.println(sfxvolumelevel);

        vehiclespeed = (((commandbuffer[7] - 48) * 100) + ((commandbuffer[8] - 48) * 10) + (commandbuffer[9] - 48));
        Serial.print("Vehicle speed: "); Serial.println(vehiclespeed);

        startsound = (((commandbuffer[10] - 48) * 100) + ((commandbuffer[11] - 48) * 10) + (commandbuffer[12] - 48));
        Serial.print("Start sound: "); Serial.println(startsound);

        startgyro = (((commandbuffer[13] - 48) * 100) + ((commandbuffer[14] - 48) * 10) + (commandbuffer[15] - 48));
        Serial.print("Start gyro: "); Serial.println(startgyro);

        stopsound = (((commandbuffer[16] - 48) * 100) + ((commandbuffer[17] - 48) * 10) + (commandbuffer[18] - 48));
        Serial.print("Stop sound: "); Serial.println(stopsound);

        stopgyro = (((commandbuffer[19] - 48) * 100) + ((commandbuffer[20] - 48) * 10) + (commandbuffer[21] - 48));
        Serial.print("Stop gyro: "); Serial.println(stopgyro);

        enginesound = (((commandbuffer[22] - 48) * 100) + ((commandbuffer[23] - 48) * 10) + (commandbuffer[24] - 48));
        Serial.print("Engine sound: "); Serial.println(enginesound);

        sfx1 = (((commandbuffer[25] - 48) * 100) + ((commandbuffer[26] - 48) * 10) + (commandbuffer[27] - 48));
        Serial.print("SFX 1: "); Serial.println(sfx1);

        sfx2 = (((commandbuffer[28] - 48) * 100) + ((commandbuffer[29] - 48) * 10) + (commandbuffer[30] - 48));
        Serial.print("SFX 2: "); Serial.println(sfx2);

        sfx3 = (((commandbuffer[31] - 48) * 100) + ((commandbuffer[32] - 48) * 10) + (commandbuffer[33] - 48));
        Serial.print("SFX 3: "); Serial.println(sfx3);


      }

      else if (commandbuffer[0] == 'Y') {                                                                                         // Partial data received
        enginevolumelevel = (((commandbuffer[1] - 48) * 100) + ((commandbuffer[2] - 48) * 10) + (commandbuffer[3] - 48));
        Serial.print("Engine Volume: "); Serial.println(enginevolumelevel);

        sfxvolumelevel = (((commandbuffer[4] - 48) * 100) + ((commandbuffer[5] - 48) * 10) + (commandbuffer[6] - 48));
        Serial.print("SFX Volume: "); Serial.println(sfxvolumelevel);

        vehiclespeed = (((commandbuffer[7] - 48) * 100) + ((commandbuffer[8] - 48) * 10) + (commandbuffer[9] - 48));
        Serial.print("vehiclespeed: "); Serial.println(vehiclespeed);
      }

      else if (commandbuffer[0] == 'T') {          // SFX 1
        Serial.println("Play SFX 1");
        wTrig.trackPlayPoly(110);
        wTrig.update();
      }

      else if (commandbuffer[0] == 'U') {          // SFX 2
        Serial.println("Play SFX 2");
        wTrig.trackPlayPoly(111);
        wTrig.update();
      }

      else if (commandbuffer[0] == 'V') {          // SFX 3
        Serial.println("Play SFX 3");
        wTrig.trackPlayPoly(112);
        wTrig.update();
      }


      wTrig.update();
      memset(commandbuffer, 0, sizeof(commandbuffer));

    }
  }



  if (enginevolumelevel != oldenginevolumelevel) {                               // Adjust the engine volume on the fly
    actualenginevolume = map(enginevolumelevel, 0, 100, -70, 10);
    wTrig.masterGain(actualenginevolume);
    wTrig.update();
    oldenginevolumelevel = enginevolumelevel;
  }

  if (sfxvolumelevel != oldsfxvolumelevel) {                                     // Adjust the SFX on the fly
    // Change SFX volume here
    oldsfxvolumelevel = sfxvolumelevel;
  }
  

  if (vehiclespeed != oldvehiclespeed) {                                         // Adjust the engine sound on the fly                                              // This may need fine tuning
    pitch = map(vehiclespeed, 0, 100, -32767, 32767);
    wTrig.samplerateOffset(pitch);
    wTrig.update();
    oldvehiclespeed = vehiclespeed;
  }


}
//==============================================================================================================================================
 
A couple of questions come up, is the module paired ok? Oops, that's only one.

If you are having problems communicating, I would set up a terminal program and see what is being sent.

You could use a PC or write a quick terminal program using the Teensy to echo everything received from the serial port (Serial2) and write it to the screen (Serial).

That way you will know where the problem lies, in the sending code or your decoding code.

Have a look at this.

EDIT:
After looking at your code I am confused. I believe you are throwing a lot of data away.
In your data gathering loop you wait for 50 characters, but you don't always use all those 50.
You seem to use what you require for the command character and throw the rest away.

You are also ignoring the CR/LF at the end of line.
 
Last edited:
It suddenly started working fine. Bizarrely, if I throw the data at it quicker, it seems to work very well.

Well, like I said. I know it isn't correct. I know it reads the whole 50 characters (which now could be less). I will adjust so that it looks for the CR/LF at the end (is the the \n?)
 
Code:
#include <wavTrigger.h>                           //Wav trigger library for SFX and music

#define BlueTooth Serial2
char commandChar;

wavTrigger wTrig;                                   //Initialise the wav trigger

int led = 13;

//------------------ Variables ----------------------

int  gRateOffset = 0;                              // WAV Trigger sample-rate offset
int  gNumTracks;                                   // Number of tracks on SD card

char gWTrigVersion[VERSION_STRING_LEN];            // WAV Trigger version string

char commandbuffer[50];
int Size_of_Assembled_array;                       // The length of the assembled array, including empty spaces
int btcount;

long actualenginevolume;                           // The volume we are currently using
long pitch = -32767;                                 // Current pitch of the engine sound effect

byte enginevolumelevel;                            // Incoming data
byte sfxvolumelevel;
byte vehiclespeed;
byte startsound;
byte startgyro;
byte stopsound;
byte stopgyro;
byte enginesound;
byte sfx1;
byte sfx2;
byte sfx3;

byte oldenginevolumelevel;
byte oldsfxvolumelevel;
byte oldvehiclespeed;
//----------------------------------------------------------------------------------------------------------------------------------------------
void setup() {

    pinMode(led, OUTPUT);

    Serial.begin(9600);                              // Debug serial
    BlueTooth.begin(9600);                             // Serial comms to the BT module

    delay(1000);

    //-------- Setup the Wav Trigger board -------------

    wTrig.start();                          // Setup the wav trigger
    delay(100);
    wTrig.stopAllTracks();                  // Stop all the tracks
    delay(100);
    wTrig.samplerateOffset(0);              // Set the sample rate to 0
    wTrig.setReporting(true);
    delay(100);

    wTrig.masterGain(-70);                  // Reset the master volume gain off the WAV trigger (-70 to +4)

    delay(500);

    if (wTrig.getVersion(gWTrigVersion, VERSION_STRING_LEN)) {
        Serial.print(gWTrigVersion);
        Serial.print("\n");
        gNumTracks = wTrig.getNumTracks();
        Serial.print("Number of WAV tracks = ");
        Serial.print(gNumTracks);
        Serial.print("\n");
    }
    else {
        Serial.print("WAV Trigger response not available");
    }

    //---------------- Set up the Bluetooth ----------------

    Serial.println("Setting up Bluetooth");

    delay(1000);
    BlueTooth.write("AT+NAMEBornSFX");                                                                                     // Set up the bluetooth
    delay(1000);
    BlueTooth.write("AT+PIN1234");
    delay(1000);
    BlueTooth.write("AT+BAUD4");
    Serial.println(F("Bluetooth configuration complete"));

    //------------------------------------------------------


    wTrig.trackPlayPoly(64);                               // Play track 64
    delay(1000);

    wTrig.samplerateOffset(-32767);                        // -32767 = one octave down.    +32767 = Up one octave
    wTrig.trackPlayPoly(90);                               // Play track 90
    wTrig.trackLoop(90, 1);                                // Turn looping of the track on

    delay(1500);

}
#define lineBufferSize 10
uint8_t lineBufCharCount = 0;
char    lineBuffer[lineBufferSize];

bool BlueToothReadLine() {

    char c;

    while (BlueTooth.available() && (lineBufCharCount < lineBufferSize)){
        c = BlueTooth.read();
        if (c != '\r' ) {
            if (c == '\n') {
                lineBuffer[lineBufCharCount] = 0x0;
                lineBufCharCount = 0;
                return true;
            } else {
                lineBuffer[lineBufCharCount] = c;
                lineBufCharCount++;
            }
        }
        if (lineBufCharCount > lineBufferSize) {
            lineBufCharCount = 0;
            return false;
        }
    }
    return false;
}
uint8_t GetVauleFromLineBuffer() {
    return lineBuffer[0] * 100 + lineBuffer[1] * 10 + lineBuffer[2];
}
//==============================================================================================================================================
void loop() {

    if (BlueToothReadLine()) {

        Serial.println("Incomming Data");

        switch (lineBuffer[0]) {

            case 'X':
                while (!BlueToothReadLine());
                enginevolumelevel = GetVauleFromLineBuffer(); Serial.print("Engine Volume: "); Serial.println(enginevolumelevel);
                while (!BlueToothReadLine());
                sfxvolumelevel = GetVauleFromLineBuffer(); Serial.print("SFX Volume: "); Serial.println(sfxvolumelevel);
                while (!BlueToothReadLine());
                vehiclespeed = GetVauleFromLineBuffer(); Serial.print("Vehicle speed: "); Serial.println(vehiclespeed);
                while (!BlueToothReadLine());
                startsound = GetVauleFromLineBuffer(); Serial.print("Start sound: "); Serial.println(startsound);
                while (!BlueToothReadLine());
                startgyro = GetVauleFromLineBuffer(); Serial.print("Start gyro: "); Serial.println(startgyro);
                while (!BlueToothReadLine());
                stopsound = GetVauleFromLineBuffer(); Serial.print("Stop sound: "); Serial.println(stopsound);
                while (!BlueToothReadLine());
                stopgyro = GetVauleFromLineBuffer(); Serial.print("Stop gyro: "); Serial.println(stopgyro);
                while (!BlueToothReadLine());
                enginesound = GetVauleFromLineBuffer(); Serial.print("Engine sound: "); Serial.println(enginesound);
                while (!BlueToothReadLine());
                sfx1 = GetVauleFromLineBuffer(); Serial.print("SFX 1: "); Serial.println(sfx1);
                while (!BlueToothReadLine());
                sfx2 = GetVauleFromLineBuffer(); Serial.print("SFX 2: "); Serial.println(sfx2);
                while (!BlueToothReadLine());
                sfx3 = GetVauleFromLineBuffer(); Serial.print("SFX 3: "); Serial.println(sfx3);
            case 'Y':
                while (!BlueToothReadLine());
                enginevolumelevel = GetVauleFromLineBuffer(); Serial.print("Engine Volume: "); Serial.println(enginevolumelevel);
                while (!BlueToothReadLine());
                sfxvolumelevel = GetVauleFromLineBuffer(); Serial.print("SFX Volume: "); Serial.println(sfxvolumelevel);
                while (!BlueToothReadLine());
                vehiclespeed = GetVauleFromLineBuffer(); Serial.print("Vehicle speed: "); Serial.println(vehiclespeed);
            case 'T':
                Serial.println("Play SFX 1");
                wTrig.trackPlayPoly(110);
                wTrig.update();
            case 'U':
                Serial.println("Play SFX 2");
                wTrig.trackPlayPoly(111);
                wTrig.update();
            case 'V':
                Serial.println("Play SFX 3");
                wTrig.trackPlayPoly(112);
                wTrig.update();
            default:
                Serial.print("Unknown Command Line : ");
                Serial.println(lineBuffer);
        }

    }

    if (enginevolumelevel != oldenginevolumelevel) {                               // Adjust the engine volume on the fly
        actualenginevolume = map(enginevolumelevel, 0, 100, -70, 10);
        wTrig.masterGain(actualenginevolume);
        wTrig.update();
        oldenginevolumelevel = enginevolumelevel;
    }

    if (sfxvolumelevel != oldsfxvolumelevel) {                                     // Adjust the SFX on the fly
        // Change SFX volume here
        oldsfxvolumelevel = sfxvolumelevel;
    }


    if (vehiclespeed != oldvehiclespeed) {                                         // Adjust the engine sound on the fly                                              // This may need fine tuning
        pitch = map(vehiclespeed, 0, 100, -32767, 32767);
        wTrig.samplerateOffset(pitch);
        wTrig.update();
        oldvehiclespeed = vehiclespeed;
    }


}
//==============================================================================================================================================
I just did a quick (??!) re-write to handle CR/LF. I can't say that I have tested it as I don't have the hardware, but it does compile ok.
If it wasn't for the CR, you could just use Serial2.readStringUntil.
 
Thanks

I will try that later this evening, once I have tracked down a very elusive ground hum on my Wav Trigger board
 
Back
Top