Go Down

Topic: Arduino missing data from HC-05 (Read 364 times) previous topic - next topic

DragoSupremo

Jul 17, 2019, 12:11 pm Last Edit: Jul 17, 2019, 04:39 pm by DragoSupremo
Hi everybody,
i hope i am in the right section of the forum.

I am trying to receive a string through an hc-05 bluetooth module, with info about 4 dc motors power, sent with an application on my computer.

Here's the arduino code involved:

Code: [Select]
  //Receives motors info from the controller
  if (Serial.available() > 0)
  {
    //Reads data until end character
    data = Serial.readStringUntil('/');
    //Splits the collected data
    motorsPower[0] = data.substring(0, 4);
    motorsPower[1] = data.substring(4, 8);
    motorsPower[2] = data.substring(8, 12);
    motorsPower[3] = data.substring(12, 16);
   
  }
  //Sends the collected data to the application on my pc
  Serial.print(String(motorsPower[0]) + "|" + String(motorsPower[1]) + "|" + String(motorsPower[2]) + "|" + String(motorsPower[3]) + "/");


The string sent, to make a test, is "1001100210401046/".

However the data shown in my application shows up incorrect data, sometimes missing some chars from the string, and in fact if i send to the application the length of the string(with data.length()), sometimes it seems to be 15 instead of 16, and i think that my arduino is missing some incoming data from the hc-05.

Could it have something to do with data.substring()? In fact if i remove the 4 data.substring() the problem doesn't show up and data.length() is always 16. Also for this i would exclude that it's an application problem on my pc.

EDIT: ok, the problem doesn't seem to be data.substring(). In fact the problem doesn't show up if i send only the data string with nothing else (serial.print(data + "/")) instead of Serial.print(data + "|" + String(motorsPower[1]) + "|" + String(motorsPower[2]) + "|" + String(motorsPower[3]) + "/");
The fact is that i need to send all those info to my pc, is there a way i could do that?

Power_Broker

You are both formatting and parsing the bluetooth packets horribly (not trying to be mean). Take a look at this intro tutorial to using serial data - it will more clearly explain a better way to handle packetized serial data.
"The desire that guides me in all I do is the desire to harness the forces of nature to the service of mankind."
   - Nikola Tesla

DragoSupremo

#2
Jul 18, 2019, 03:05 pm Last Edit: Jul 18, 2019, 03:15 pm by DragoSupremo
Ok thank you for your answer . I tried doing a little benchmark of the previous code, and looks like it is really slow (almost 50 milliseconds between each cycle!). So i tried as said in the guide to parse and send data like this:
Code: [Select]

  while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
  }
  if (completeData == true)
  {
    String(elapsedTime).toCharArray(timeToStamp, 5);
    Serial.print(timeToStamp); //CAUSES THE ARDUINO TO GET STUCK
    Serial.print(dataC);
    completeData = false;
  }
 

It works perfectly if i just print dataC, with just 2 milliseconds between each cycle i think. However, a big problem comes when i try to print more than one string (for example the time between each cycle). In fact the arduino suddenly gets stuck and doesn't send anything anymore to the serial monitor... I checked if it could be stuck in the while loop, but it seems to be just completely blocked and i don't know why, i am pretty confused.

An output example on the serial monitor of the code over there might be:
"1.001001100210401046/2.001001100210401046/1.001001100210", until it suddenly stops sending anything.

Romonaga

So the program stops printing, the only area that does printing is if completeData == true.  Have you validated that completeData == true? 

I also wound remove the String and use c style strings. Using String can lead to memory fragmentation.

It is also hard to detemine if you have an issue with your char arrays as you did not post the complete code, as such we can not validate if you are over-running an array.



The universe exists only because we are aware of it.
We want a few mad people now. See where the sane ones have landed us!

DragoSupremo

#4
Jul 20, 2019, 10:22 pm Last Edit: Jul 20, 2019, 10:38 pm by DragoSupremo
The complete code of what is causing my problem is this:
Code: [Select]
char recData;
boolean completeData = false;
char dataC[17];
int index = 0;
void setup() {
 Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
 
    while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
    Serial.println(completeData) //To check if it's working
  }
  char dataCs[7] = "hello";
  if (completeData)
  {
    Serial.write(dataCs);
    Serial.write(dataC);
    completeData = false;
  }
 
}


I used a string "hello" instead of printing elapsedTime, but the problem is the same.

Here i'm using only C strings, so i don't think it's the problem.

The code simply receives a string from the application, and sends it back with "hello" in addition.

I also checked if completeData was correct and TRUE when it stops working, but Arduino seems not to send anything (as if it's blocked):smiley-roll-sweat:.

Another example of the Arduino output before it stops working is: hello1001100210401046/hello1001100210401046/hel⸮hello⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮z⸮⸮⸮⸮⸮⸮

Can it be that the hc-05 is communicating through RX and TX pins instead of using SoftwareSerial?

EDIT: i am using and Arduino Nano.


cattledog

Code: [Select]
char dataC[17];

1001100210401046/  This message has 17 characters with indexes 0 thru 16.

Code: [Select]
dataC[index + 1] = '\0';

You are now adding a terminating null outside the reserved bounds of the array. Writing to memory you don't "own" will produce all kinds of unpredictable errors.

Size dataC for the largest message plus the terminating null. If  the posted message is typical then
Code: [Select]
char dataC[18];

DragoSupremo

#6
Jul 21, 2019, 11:26 am Last Edit: Jul 21, 2019, 11:35 am by DragoSupremo
Ok i tried with char dataC[18] but it is still giving problem than before  :smiley-cry:.

The interesting thing is that by not writing the received data, but instead writing the same resulting string that has been manually initialized (dataC reads the data, but is not written; dataCs same as before; dataCcs = ""1001100210401046/") still gives me the same problem, can this suggest that is not a reading problem?

Code: [Select]
char recData;
boolean completeData = false;
char dataCcs[18] = "1001100210401046/";
char dataC[18];
int index = 0;
void setup() {
 Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
 
  while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
  }
  char dataCs[6] = "hello";
  if (completeData)
  {
    Serial.write(dataCs); //"hello"
    Serial.write(dataCcs);//"1001100210401046/", anyway dataC is still read
    completeData = false;
  }
 
}


However, writing the same resulting string, but as a single string (dataCs = "hello1001100210401046/") doesn't give me any problem at all! Can this suggest it's a problem with writing 2 strings on a row?

Code: [Select]
char recData;
boolean completeData = false;
char dataC[18];
int index = 0;
void setup() {
 Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
 
  while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
  }
  char dataCs[24] = "hello1001100210401046/";
  if (completeData)
  {
    Serial.write(dataCs); //"hello1001100210401046/", only writing one string (dataC from hc-05 is still read in background)
    completeData = false;
  }
 
}



DragoSupremo

#7
Jul 21, 2019, 02:54 pm Last Edit: Jul 21, 2019, 03:27 pm by DragoSupremo
Ok sorry but in the last post i must have done something wrong, since this:
Code: [Select]
char recData;
boolean completeData = false;
char dataCcs[18] = "1001100210401046/";
char dataC[18];
int index = 0;
void setup() {
 Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
 
  while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
  }
  char dataCs[6] = "hello";
  if (completeData)
  {
    Serial.write(dataCs); //"hello"
    Serial.write(dataCcs);//"1001100210401046/", anyway dataC is still read
    completeData = false;
  }
 
}

Works, exactly like this:
Code: [Select]
Code: [Select]
char recData;
boolean completeData = false;
char dataC[18];
int index = 0;
void setup() {
 Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:
 
  while (Serial.available() > 0 && completeData == false)
  {
    recData = Serial.read();
    if (recData != '/')
    {
      dataC[index] = recData;
      index++;
    }
    else
    {
      dataC[index] = '/';
      dataC[index + 1] = '\0';
      completeData = true;
      index = 0;
    }
  }
  char dataCs[24] = "hello1001100210401046/";
  if (completeData)
  {
    Serial.write(dataCs); //"hello1001100210401046/", only writing one string (dataC from hc-05 is still read in background)
    completeData = false;
  }
 
}


It looks like it crashes when i try to print the same string i have just read from the hc-05 together with something else, but that doesn't make much sense(?).

cattledog

Quote
It looks like it crashes when i try to print the same string i have just read from the hc-05 together with something else, but that doesn't make much sense(?).
I can not confirm your findings. Whether I send data from the serial monitor with no HC05 connected, for from the HC05 connected to hardware serial after uploading the program I seen no crashes. There are some formatting issues with line endings used from both the serial monitor or the phone app but no crashes.

If things work as expected from the Serial monitor, I would focus on the HC05 and the terminal app on the phone.

Are you using a voltage divider on the HC05 RX line to drop the Arduino 5v to 3.3v?
I use Kai Morich's  Serial Bluetooth Terminal.

DragoSupremo

#9
Jul 22, 2019, 12:16 am Last Edit: Jul 22, 2019, 12:17 am by DragoSupremo
First of all really thanks for your time  :smiley:
Yea the Rx pin uses a voltage divider and it's connected to Tx pin on the Nano.

Actually i am not using an application on my phone but a program on my pc that i made with node js, so the problem might be also here.

What the application does is to create a connection with my hc-05 and then start sending the string every 1 milliseconds. It then prints what receives from the hc-05.

I have now tried to increase the interval between each string, can 1 milliseconds be too fast? It works if i set an interval of 100 milliseconds but i really need to send data much faster than that rate (at max 10 milliseconds i think?).


cattledog

Quote
I have now tried to increase the interval between each string, can 1 milliseconds be too fast? It works if i set an interval of 100 milliseconds but i really need to send data much faster than that rate (at max 10 milliseconds i think?).
Each character is 10 bits, and at 9600 baud, it takes about a millisecond per character. You are trying to send 17 characters. What timing value between 1 and 100 milliseconds for the sending/reply interval works reliably.

Using command mode and AT commands, you can try to change the HC05 communication mode baud rate from 9600 to something faster.  Google search for how to enter command mode for the HC05, and how to change the baud rate for the communication mode.


DragoSupremo

Ok i'm gonna change the baudrate of my hc-05, i hope this will finally solve the problem.

I'll try changing it to 115200 which is more than 10 times faster so that it should need no more than 10 ms to receive/send data.

I see that while changing baudrate it asks about the number of stop bits and my default was 0. Is it important to have at least 1 stop bit and can it cause problem not to have one?

cattledog

Quote
I see that while changing baudrate it asks about the number of stop bits and my default was 0. Is it important to have at least 1 stop bit and can it cause problem not to have one?
Since you know things are working at the current setting of 9600 with enough time between transmissions, I would check the current baud rate, with "AT+UART". The Arduino default is 8N1. 8 bits, No parity, 1 stop bit,  Given how the HC05 AT commands are formatted, I think you should see 9600,1,0 in reply.

Then adjust the baud rate to 115200 in the same format as you get back from the query.




DragoSupremo

I checked the actual baud rate the answer was: 9600,0,0; so i changed it to 115200,0,0. It works for a longer period of time, but after a period that varies from 2 to 10 minutes stops working again and it's quite unpredictable...



cattledog

#14
Jul 22, 2019, 04:04 pm Last Edit: Jul 22, 2019, 05:21 pm by cattledog
I'm unclear as to the actual program structure you want, the role of the computer, and arduino, and what data is passed Arduino>computer and computer>Arduino. The blue tooth wireless transmission over the air is very fast, compared to the Serial at either end.

You may need more robust serial methods rather than a simple end marker. Start and end marker may be better. See Robin3's tutorial at Serial Input Basics.

You may also need a check sum on the transmission and reject anything that's corrupted.

Go Up