4
votes

I currently have a HC-06 Bluetooth device connected to my Arduino Mega 2560 in order to receive strings sent from an Android device. With the HC-06 on Serial 0, I am receiving the data without error with the following code:

String inString = "";
int index = 0;
boolean stringComplete = false;

void setup(){
  Serial.begin(9600);
  pinMode(pwmPin, OUTPUT);
}

void loop(){
  if(stringComplete){
    ParseSerialData();       //Parse the received data
    inString = "";           //Reset inString to empty
    stringComplete = false;  //Reset the system for further input of data
  }
}


void serialEvent(){
  while(Serial.available() && stringComplete == false){
    char inChar = Serial.read();
    inData[index] = inChar;       //Store it in char array
    index++;

    if (inChar == '\n'){          //Check for termination character
      index = 0;                  //Reset the index
      stringComplete = true;      //Set completion of read to true
    }else{
      inString += inChar;         //Also store as string
    }
  }
}

When I try to replace "Serial" with "Serial1" and "serialEvent()" with "serialEvent1()" and move the Bluetooth device to the TX1 and RX1, this program no longer works.

I have read that some people had similar problems when using AVR-GCC 4.4.x and solved the issue by downgrading to 4.3.x, but I have 4.3.2 (on Windows 8.1, same problem has arisen with Arduino IDE 1.0.3, 1.0.5-r2, and 1.5.6-r2).

I added the following print statements (with Serial 0 to print to the monitor on my PC) to the code with the BT device still on Serial 1:

String inString = "";
int index = 0;
boolean stringComplete = false;

void setup(){
  Serial1.begin(9600);
  Serial.begin(9600);
  pinMode(pwmPin, OUTPUT);
  Serial.println("Setting up...");
}

void loop(){
  if(stringComplete){
    ParseSerialData();
    inString = "";
    stringComplete = false;
  }
}


void serialEvent1(){

  Serial.println("In serialEvent1...");

  while(Serial1.available() && stringComplete == false){

    Serial.println("Char in...");

    char inChar = Serial1.read();

    Serial.println("WTF");
    Serial.println(inChar);
    Serial.println("WTF2");

      inData[index] = inChar;

      index++;

      if (inChar == '\n'){
        Serial.println("Termination char read...");

        index = 0;
        stringComplete = true;
      }else{
        inString += inChar;
      }
   }
}

Doing this, on the monitor I get:

Setting up...
In serialEvent1...
Char in...
WTF

WTF2

inChar typically prints as nothing, but during one test it was printing as an '@' character. The string sent is "s,1\n" from the Android device.

Based on the print out, the serial event is triggered by availability of serial data, but Serial1.available() remains true for only the first iteration, 's' is not read in (nor any of the other characters that do when Serial is used), and a termination character (newline char) is never read in so that I can begin parsing.

I also tried various baud rates with no difference in behavior. Based on reading Arduino documentation, serial port 1 should work just like serial port 0, and I did not miss substituting Serial for Serial1 in any part of the code.

Does anyone have any idea what could be causing errors in communicating over Serial1 in the same way that has worked flawlessly on Serial0?

Let me know if I have failed to include any relevant information.

Thanks in advance!

EDIT:

I also found a related SO question, which was solved with something similar to my code (which works perfectly with Serial0 and is based on the Arduino documentation) using an expected termination character (the difference being that his code implements serial reading in the main loop, whereas mine is in a serialEvent). For some reason it seems that both of us were having issues with Serial1 data not showing as available at the start of the next iteration. For some reason, serialEvent1 is not being called again for me. And I still don't understand why the first/only character read is not 's.' At first I was thinking that the stream was getting flushed before getting to the serial event again, but that still doesn't account for reading in an incorrect first character.

Also, I added the following Serial1 print statement to run multiple times in the Arduino setup and the Android device receives it each time with no errors, so sending data is working just fine:

   Serial1.print("b,1\n");

or even

   Serial1.print("A long test message. A long test message.\n");

EDIT 2:

I'm fairly close to answering my own question now with further testing/debugging. I actually think the answer may end up being hardware-related rather than software. I wanted to find out if the problem was with the data sent from the HC-06 to port 1, or with the reading function of port 1. I basically had serial port 0 read in data, then send it serially to port 1, which would read that data, and send feedback over bluetooth to the Android device. Serial port 1 read the data fine coming from port 0, so the issue is reading in data specifically from the HC-06. It may simply be a voltage level issue, so the answer may not belong with stackoverflow. I will leave the question unanswered though until I definitively have found the root cause (allowing for the possibility that I might need some define statement for the HC-06 or serial port 1 for data to be read correctly, though I'm guessing a voltage level conversion may do the trick. I'm not sure why there would be such a difference between Serial0 and Serial1 though).

3

3 Answers

6
votes

I solved the problem enabling the pullup resistor of the Rx1 pin:

  Serial1.begin(9600);

  pinMode(19, INPUT);  
  digitalWrite(19, HIGH);

Therefore the 3V is "overriden" by arduino's 5V for logical HIGH and zero is pulled down by bluetooth's TX for logical LOW.

0
votes

After checking the serial data lines on my oscilloscope, I was able to come up with a solution to my issue. With the setup described in EDIT 2 (bluetooth TX -> RX0, TX0 -> RX1, TX1 -> Bluetooth RX), I checked the signals sent by the bluetooth device and by the Arduino's serial port 0.

The bluetooth device's signal was low at 400 mV and high at 3.68V, while the Arduino's port 0 sent low at 0V and high at 5V. I knew the bluetooth device was a 3.3V level device, but the Arduino should read anything above about 3V as high, so this should have not been an issue (and it obviously wasn't on Serial 0).

Anyways, I replaced the HC-06 bluetooth device with a backup one I had purchased and everything works fine with the code using Serial1 that I posted in my question. This bluetooth device was transmitting low at about 160 mV and high at 3.3V.

It seems that my problem was rooted in the hardware (voltage levels) as expected, and that for some reason Serial1 is more sensitive to changes in digital levels than is Serial0. I supposed my question as to why that is would be better suited for StackExchange or somewhere similar. Let me know if you have any further info or a more in depth answer.

0
votes

Just to say thank you to Alison for this solution. I did it slightly differently by using the INPUT_PULLUP feature to pull the hardware Serial3 pin HIGH:

Serial3.begin(19200);        
pinMode(15, INPUT_PULLUP);  //Serial3 Rx pin

It works a treat, previously my serial comms between two arduino mega 256s had been mainly corruption with the occasional correct transmission. Now it is mainly correct transmission. Previously, the time taken to receive a valid serial value was up to 2.5 seconds (due to having to repeatedly retry to get a valid Tx). Now the time taken to get a valid Tx is 20ms. (I use a twisted pair of single core wires about 35 cm length).

Brilliant - thanks again.