Serialred()->strtok()

good morning everyone. For some time I try to display data received with the com port.The data looks like this:

  • Attente arret 1;0011;1;1;zst; Kesseltemp.;0110;2;2;°C; Abgastem2Einschub Ist;0000;12;1;%; O2 Regler Pell ;0035;13;1;%; Füllstand: ;17844;14;207;%; Ansauggeschw.;0454;15;100;m/s; Strom Austrags;1010;16;1000;A; Fühler 1;0123;17;2;°C; Kesselsoll ;0080;18;2;°C; Pufferoben ;0000;20;2;°C; Pufferunten ;0000;21;2;°C; Pufferpumpe ;8192;22;1;%; Boiler 1;0121;23;2;°C; Vorlauf 1;0071;24;2;°C; Vorlauf 2;0031;25;2;°C; HK Pumpe 1;0001;26;1; ; HK Pumpe 2;0000;27;1; ; Aussentemp;0026;28;2;°C; Kollektortemp;0000;29;2;°C; Betriebsstunden;1195;30;1;h; Fehler;Kein Fehler ;99;1; ;

First I find a blog that uses a skecth strtok (), it works well.

/*

In your program, you would read stuff into a char array. For purposes of testing strtok, I'll just set it up a "string" in an initialized array.

*/

char arr[30] = { "Kesseltemp.;0126;2;2;°C;" };

void setup() { Serial.begin(9600); Serial.println("Index;Valeur"); }

void loop() { char str[30]; int val, ind, div; int errors = 0;

strcpy(str, arr);

// First is throwaway unless you want to do strcmp with "!ANG" or some such thing char chpt = strtok(str, ";"); if (chpt == NULL) { **Serial*.println("First strok returns NULL"); ++errors; }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Second strok returns NULL"); ++errors; } else { val = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Third strok returns NULL"); ++errors; } else { ind = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ",\r\n"); if (chpt == NULL) { Serial.println("Fourth strok returns NULL"); ++errors; // This is an input error: do something to handle it. } div = atof(chpt); } if (errors == 0) {

Serial.print(ind); Serial.print(";"); Serial.print((val)/(div)); Serial.println(); }

delay(1000); }

the résulte is 2;63 very good juste i want . you can see the "input" is a char array.

Second on this forum I found a sketch that reads data on com port and that the "put" in an array.

char inData[30]; byte index = 0;

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

void loop() { while(Serial.available() > 0) { char aChar = Serial.read(); if(aChar == '\r'|| index==30) { // End of record detected. Time to parse

index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated }

Serial.println(inData); }

}

in the consol if i send Vorlauf 2;0031;25;2;

the response is :

þV Vo Vor Vorl Vorla Vorlau Vorlauf Vorlauf Vorlauf 2 Vorlauf 2; Vorlauf 2;0 Vorlauf 2;00 Vorlauf 2;003 Vorlauf 2;0038 Vorlauf 2;0038; Vorlauf 2;0038;2 Vorlauf 2;0038;25 Vorlauf 2;0038;25; Vorlauf 2;0038;25;2 Vorlauf 2;0038;25;2; Vorlauf 2;0038;25;2;° Vorlauf 2;0038;25;2;°C Vorlauf 2;0038;25;2;°C;

I am a beginner and I do not really understand why. after i tested .

/*

In your program, you would read stuff into a char array. For purposes of testing strtok, I'll just set it up a "string" in an initialized array.

*/

char inData[30]; byte index = 0;

void setup() { Serial.begin(57600); Serial.println("Index;Valeur"); }

void loop() { char str[30]; int val, ind, div; int errors = 0;

while(Serial.available() > 0) { char aChar = Serial.read(); if(aChar == '\n') { // End of record detected. Time to parse

index = 0; inData[index] = NULL; } else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated } } Serial.setTimeout(1250); strcpy(str, inData); // First is throwaway unless you want to do strcmp with "!ANG" or some such thing

char chpt = strtok(str, ";"); if (chpt == NULL) { **Serial*.println("First strok returns NULL"); ++errors; }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Second strok returns NULL"); ++errors; } else { val = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Third strok returns NULL"); ++errors; } else { ind = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ";\r\n"); if (chpt == NULL) { Serial.println("Fourth strok returns NULL"); ++errors; // This is an input error: do something to handle it. } div = atof(chpt); } if (errors == 0) {

Serial.print(ind); Serial.print(";"); Serial.print((val)/(div)); Serial.println(); }

}

but the résult is:

have any tips or ideas? thank you

See the comment that says:

      // End of record detected. Time to parse

Is that where you do your parsing. No, it isn't. Why not?

if I receive the \ r is the end of the data the data like this : Vorlauf 2;0038;25;2;°C; "no printable \r"

sorry, but hard to understand is that you say (i am french)

Each character that you receive that is not a \n is added to an array. As soon as you receive a \n, you reset the index to the array, and put a NULL in the first position, thereby erasing all the data that was in the array.

Then, you copy the now-empty array to the end of str, wherever that might be. Then, you try to parse that copy of nothing.

First, str is a local variable. That means that it does not get initialized to anything. Whatever was in that memory is still there.

When strcat() tries to append to it, if searches the str array for the first NULL, which could be anywhere between the 0th element of the array and somewhere far beyond the end of the array.

You need to EXPLICITLY initialize str, and you need to copy inData to str BEFORE you reinitialize inData and index.

Finally, you should parse str ONLY if you copied data to it.

thank you!

I will try to understand how to do it and correct my mistake.

thanks you !!

i receive the data : Kesseltemp.;0126;2;2;°C and Serial.print = 2;63

char inData[35]; // to store incoming data byte index = 0; char str[35]; // string to copy inData int val, ind, divi; int errors = 0;

void setup() { Serial.begin(57600); // star serial at 57600 Serial.println("index;valeur"); // juste one time for test .CSV } void **loop*()

{

while(Serial.available() > 0) { char aChar = Serial.read(); if(aChar == '\r') // cariage return is the end of data { // End of record detected. Time to parse

strcpy(str,inData); // copy inData into str

/* Serial.print("str="); // for debug Serial.println(str); Serial.print("inData="); Serial.println(inData); Serial.println(); / // First is throwaway unless you want to do strcmp with "!ANG" or some such thing char *chpt = strtok(str, ";"); if (chpt == NULL) { **Serial*.println("First strok returns NULL"); ++errors; }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Second strok returns NULL"); ++errors; } else { val = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ";"); if (chpt == NULL) { Serial.println("Third strok returns NULL"); ++errors; } else { ind = atof(chpt); } }

if (errors == 0) { chpt = strtok(NULL, ";\r\n"); if (chpt == NULL) { Serial.println("Fourth strok returns NULL"); ++errors; // This is an input error: do something to handle it. } divi = atof(chpt); } if (errors == 0) {

Serial.print(ind); Serial.print(";"); Serial.print((val)/(divi)); Serial.println(); }

index = 0; inData[index] = NULL;

} else { inData[index] = aChar; index++; inData[index] = '\0'; // Keep the string NULL terminated

} } }