Problem with split char into strings and print on serial

Hi all,

I have two devices based on arduino nano. One of them have different sensors plus a gps. The data are sent by bluetooth. The other device, that has a LCD5110, snif the incomming data from the bluetooth, split the data and show them in the LCD.

Everything workd perfect, except the split of the data. I tried a simple code (Serialcomm.ino i attach here). It works perfect. Read the data from the bluetooth, print them in the serial port, split, and print in the serial port in a independant line. The result is something like this:

D;0;304444;INVALID;07/01/2016;13:22:22;INVALID;INVALID;INVALID;23.21;19.73;-127.00;119
D
0
304444
INVALID
07/01/2016
13:22:22
INVALID
INVALID
INVALID
23.21
19.73
-127.00
119
D;0;304444;INVALID;07/01/2016;13:22:23;INVALID;INVALID;INVALID;23.21;19.67;-127.00;273
D
0
304444
INVALID
07/01/2016
13:22:23
INVALID
INVALID
INVALID
23.21
19.67
-127.00
273

I copied this test code into my main sketch (SPPS-control_01.ino i also attach here), and now it does not work properly, because it reads the data from the bluetooth, and print it in the serial port. But, it does not print the individual parts of the data, but empty lines (Lines264 to 276 in the main sketch). It is like if the getValues process was not working properly... What i have in the serial port looks like this:

D;0;304444;INVALID;07/01/2016;13:20:10;INVALID;INVALID;INVALID;23.19;19.71;-127.00;116

D;0;304444;INVALID;07/01/2016;13:20:11;INVALID;INVALID;INVALID;23.19;19.71;-127.00;192

Then, if everything is the same, why it does not work? Where could be the problem?

SPPS_Control_01.ino (11.9 KB)

Serialcomm.ino (2.12 KB)

The other device has a LCD5110 that shoud read the incomming data

I've never seen an LCD that can read serial data...

void process_data (const char* data) {

Since the data is a character string,

String getValue(String data, char separator, int index) {

Why are you f**king with Strings?

strtok() can parse strings.

@madepablo, if this was my project I would read all the data first and only then try to parse it.

This makes managing the project much easier.

Have a look at the second example in Serial Input Basics. There is also a parse example.

...R

@PaulS, thanks so much. Sorry for my bad english. I tried to correct it to show that the LCD is not reading, but showing what the bluetooth receives.
About the strings issue, i was looking on this forum and also in other sites of internet and found this solution. I included the getValue() procedure into an example sketch, and it was working. So, i didn´t detected that i was doing something wrong with Strings. My problem was how the same code does not produce the same efects if everything is the same. In any case, now i see that my way was not correct.

In fact, i also readed about the strtok() command, but i didn´t like it because i am not able (i think) to access any part of the complete array in any moment. Now, i am showing the splitted datain the serial port, but the idea is to show different parts of the array in the LCD depending of which screen type is active in the LCD in each moment. But this was other thing to do, once i solved the first one.

In any case, you say very clearly that i was doing the things incorrectly, so, i will explore deeper the strtok() option. Thanks for point to me in this way.

@Robin2, thanks so much for you post.
AFAIK, what i am doing is exactly what you say. I read all the incomming data (until a \n is received), and then it is processes. Am i right? I am not an expert on arduino or C coding, so, may be i am compltely wrong...
Thank so much for your post lisk. I will study it in detail. Thanks!!

BTW, i obtained the getValue() procedure from here:

and the serial communication from here:

strtok() is going to make your code easier. This shows how you might use it. You'll need to eitehr process or save the results from strtok() as needed.

const unsigned int MAX_INPUT = 100;
char buff[MAX_INPUT];

void setup() {
  Serial.begin(9600);
}

void loop() {
  int charsRead;

  // test data:  D;0;304444;INVALID;07/01/2016;13:20:11;INVALID;INVALID;INVALID;23.19;19.71;-127.00;192
 if (Serial.available() > 0) {
    charsRead = Serial.readBytesUntil('\n', buff, MAX_INPUT - 1);

    buff[charsRead] = '\0';                                           // Now it's a string
    BreakData();
 }

}

void BreakData() 
{
  char *ptr;
  
  ptr = strtok(buff, ";");
  while (ptr) 
  {
    Serial.println(ptr);      // Do your processing on each item here, or save it somewhere
    ptr = strtok(NULL, ";");
  }
}

Thanks @econjack,
It works as it is (i mean, i still din´t include it into my main program), as well as it was working my "serialcomm.ino" example code.

Now, i need to move each token to an array in order to be able to display in the LCD the different parts. I tried to create an array,and assign each token to a position of the array, in this way:

const unsigned int MAX_INPUT = 100;
char buff[MAX_INPUT];
char* item;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int charsRead;

  // test data:  D;0;304444;INVALID;07/01/2016;13:20:11;INVALID;INVALID;INVALID;23.19;19.71;-127.00;192
 if (Serial.available() > 0) {
    charsRead = Serial.readBytesUntil('\n', buff, MAX_INPUT - 1);

    buff[charsRead] = '\0';                                           // Now it's a string
    BreakData();
 }

}

void BreakData()
{
  char *ptr;
  item = 0;
  byte Count = 0; //a byte is enough because the array will benever longer than 12-15 items.
  ptr = strtok(buff, ";");
  while (ptr)
  {
    //Serial.println(ptr);      // Do your processing on each item here, or save it somewhere
    item[Count] = ptr;
    Serial.println(&item[Count]);
    Count++;
    ptr = strtok(NULL, ";");
  }
}

But it is not the correct way, because it return thos error where i try to assign the token to an array position:

sketch_jan07b.ino: In function 'void BreakData()':
sketch_jan07b.ino:32:17: error: invalid conversion from 'char*' to 'char' [-fpermissive]

I changed your definition of item[] and the way it is used:

const unsigned int MAX_INPUT = 100;
char buff[MAX_INPUT];
char* item[20];            // An array of 20 pointers to char

void setup() {
  Serial.begin(9600);
}

void loop() {
  int charsRead;

  // test data:  D;0;304444;INVALID;07/01/2016;13:20:11;INVALID;INVALID;INVALID;23.19;19.71;-127.00;192
 if (Serial.available() > 0) {
    charsRead = Serial.readBytesUntil('\n', buff, MAX_INPUT - 1);

    buff[charsRead] = '\0';                                           // Now it's a string
    BreakData();
    charsRead = 0;
    while (item[charsRead]) {
      Serial.println(item[charsRead++]);
    }
      
 }

}

void BreakData() 
{
  char *ptr;
  int count = 0;
  
  ptr = strtok(buff, ";");
  while (ptr) 
  {
//    Serial.println(ptr);      // Do your processing on each item here, or save it somewhere
    item[count++] = ptr;   // Save for later...
    ptr = strtok(NULL, ";");
  }
}

@econjack,

Thanks so much! Again, it works nice! Thanks you.

I will try to adapt the main program to use your method, to see if the LCD shows the data alrady splitted.
In ay case, thanks so much for your efforts!

I will read more about strtok().

Thanks!!

Edited: I adapted the here discussed sketch to my original code, and now it works nicely! Thanks @econjack

madepablo:
@Robin2, thanks so much for you post.
AFAIK, what i am doing is exactly what you say. I read all the incomming data (until a \n is received), and then it is processes. Am i right?

Yes, now that I study your code more closely I can see that that is what is happening.

The parse example in Serial Input Basics could be applied to your array input_line[]

...R

Thanks @robins2!
i was inmersed in your first post, and i didn´t see the second one where you have the parseData() procedure.

I will try also with your code! Thanks so much!

Although my problem is solved thanks to all your nice help, i am still curious about why the same piece of code does not work in both sketches... i willl go back about this topic again in the future.

Thanks!