Hi everyone, I really need your help. I'm receiving a chunk of data that comes like this xxx,yyy,zzz,aaa,bbb, and so on repetitive each represent different values.
Here's my code to split them up :
//sensorstring is the chunk of data coming in
int secondCommaIndex = sensorstring.indexOf(',', commaIndex+1);
String firstValue = sensorstring.substring(0, commaIndex);
String secondValue = sensorstring.substring(commaIndex+1, secondCommaIndex);
String thirdValue = sensorstring.substring(secondCommaIndex); // To the end of the string
int r = firstValue.toInt();
int g = secondValue.toInt();
int b = thirdValue.toInt();
Serial.println("r:");
Serial.print(r);
Serial.println("g:");
Serial.print(g);
Serial.println("b:");
Serial.print(b);
Serial.println("");
If I Serial print the sensorstring itself I can see the data on the serial monitor but if i serial print the 3 individual values ,it doens't appear......
I suggest you save the string as a c-string (null terminated char array) and then use strtok() to separate it into sub strings at the commas.
If you're reading the string from an input stream (serial port, file, network socket etc), you could also consider parsing it character by character as it is received, recognising when you receive the separator char which indicates the end of the previous field, handling the field and then resuming reading the following one.
I suggest you avoid the String class. It doesn't do anything that you can't do using c-strings, usually just as easily, and its use of dynamic memory allocation introduces potential problems.
Thanks PeterH and Machinyon for replying. Oh okay , It took me a while to edit the code. I did it before using Strtok but it turn out to be a failure , so i move on to indexOf . I also believe it will create lots of mistake so here's my code on strtok.
//string to char
char carray[sensorstring.length() + 1]; //determine size of the array
sensorstring.toCharArray(carray, sizeof(carray)); //put readStringinto an array
Serial.print(" ");
Serial.print("string received:"); //The serial monitor(pc/mac/other) will output: string received:
Serial.println(sensorstring); //and the actual text string that the E.C. circuit has transnmited.
char* TV=strtok(carray, ","); //let's pars the string at each comma.
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
Serial.print("TV:"); //We now print each value we parsed sepratly.
Serial.println(TV); //this is the EC value.
delay(10);
Serial.print("LPM:"); //We now print each value we parsed sepratly.
Serial.println(LPM); //this is the TDS value.
delay(10);
Serial.print("LPH:"); //We now print each value we parsed sepratly.
Serial.println(LPH); //this is the salinity value.
delay(10);
int TV_int=atoi(TV);
int LPM_int=atoi(LPM);
int LPH_int=atoi(LPH);
delay(1000);
I suggest you put some quotes or other delimiters around the strings when you print them. At the moment it's hard to make out where the value of sensorstring starts and ends in that output and it is not clear whether sensorstring actually has any content at all.
Can you post a complete sketch which demonstrates the problem with this code? It will save anyone trying to help from having to write their own.
You were supposed to print the string extracted from the String. THAT is what you are parsing.
Print each pointed to string (after the call to strtok()) BEFORE calling strtok() again. strtok() returns a pointer (it's the SAME pointer every time). What it does is point to something different. You are making three copies of the pointer, not making a copy of what it points to. There are not three commas in your string, so after the third call the pointer points to nothing, which is what you are seeing when you print the value pointed to three times.
Use ONE pointer, and call atof() after getting each token, and after making sure that the pointer is actually valid.
The third call to strtok() needs a different delimiter set.
PaulS:
strtok() returns a pointer (it's the SAME pointer every time). What it does is point to something different.
No, that's not how strtok() works. Luckystar94 is using strtok() correctly. I think the problem is that the input string doesn't contain what is expected.
@PaulS Pardon me... It'll be better if you post a code example so I could test it out. I'm really sorry , it just that I don't quite get it....... But I know what you mean for the first few line where after strtok is used a token will be generated then after that I don't quite understand already.... Really sorry..
@PeterH As you recommended , I did the following amendment and here's the edited code and what I seen on the serial monitor:
//string to char
char carray[sensorstring.length() + 1]; //determine size of the array
sensorstring.toCharArray(carray, sizeof(carray)); //put readStringinto an array
Serial.print(" ");
Serial.print("string received:"); //The serial monitor(pc/mac/other) will output: string received:
Serial.println(sensorstring); //and the actual text string that the Flow meter circuit has transnmited.
char* TV=strtok(carray, ","); //let's pars the string at each comma.
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
int TV_int=atoi(TV);
int LPM_int=atoi(LPM);
int LPH_int=atoi(LPH);
Serial.print("TV:'"); //We now print each value we parsed sepratly.
Serial.print(TV); //this is the Total Volume value.
Serial.println("'");
delay(10);
Serial.print("LPM:'"); //We now print each value we parsed sepratly.
Serial.print(LPM); //this is the Liquid Per Min value.
Serial.println("'");
delay(10);
Serial.print("LPH:'"); //We now print each value we parsed sepratly.
Serial.print(LPH); //this is the Liquid per Hour value.
Serial.println("'");
delay(10);
char* TV=strtok(carray, ","); //let's pars the string at each comma.
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
int TV_int=atoi(TV);
int LPM_int=atoi(LPM);
int LPH_int=atoi(LPH);
Change that to:
char* TV=strtok(carray, ","); //let's pars the string at each comma.
int TV_int=atoi(TV);
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
int LPM_int=atoi(LPM);
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
int LPH_int=atoi(LPH);
and print TV_int, LPM_int, and LPH_int, and let us know the results.
You are still printing sensorstring, instead of carray. Why, I can't imagine, since you are not parsing sensorstring.
You still haven't put delimiters around the input string when you print it so we can't be sure what it contains, but from what you're printing it does look like an empty string. You have working code in front of you now so you should not be in any doubt about how to do it - your problem now is to see what's different between your implementation and the working one.
@PaulS oh ya I forgot to answer one of your queries on my Serial.print(sensorstring); This actually allow me to see there's a value change when I pour water through a motor. It helps me a lot when trouble shooting error.
Oh my...... I suspect this is the problem....
is it because after I print string it clear automatically? even the data comes in consistently?
if (sensor_stringcomplete){ //if a string from the Atlas Scientific product has been received in its entirety
//use the hardware serial port to send that data to the PC
Serial.print(" ");
Serial.print("string received:"); //The serial monitor(pc/mac/other) will output: string received:
Serial.println(sensorstring); //and the actual text string that the Flow meter circuit has transnmited.
sensorstring = ""; //clear the string:
sensor_stringcomplete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
}
//string to char
char carray[sensorstring.length() + 1]; //determine size of the array
sensorstring.toCharArray(carray, sizeof(carray)); //put readStringinto an array
char* TV=strtok(carray, ","); //let's pars the string at each comma.
int TV_int=atoi(TV);
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
int LPM_int=atoi(LPM);
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
int LPH_int=atoi(LPH);
Serial.print("TV:'"); //We now print each value we parsed sepratly.
Serial.print(TV_int); //this is the Total Volume value.
Serial.println("'");
delay(10);
Serial.print("LPM:'"); //We now print each value we parsed sepratly.
Serial.print(LPM_int); //this is the Liquid Per Min value.
Serial.println("'");
delay(10);
Serial.print("LPH:'"); //We now print each value we parsed sepratly.
Serial.print(LPH_int); //this is the Liquid per Hour value.
Serial.println("'");
delay(10);
// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h> //add the soft serial libray
#define rxpin 2 //set the RX pin to pin 2
#define txpin 3 //set the TX pin to pin 3
SoftwareSerial myserial(rxpin, txpin); //enable the soft serial port
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
String inputstring = ""; //a string to hold incoming data from the PC
String sensorstring = ""; //a string to hold the data from the Atlas Scientific product
boolean input_stringcomplete = false; //have we received all the data from the PC
boolean sensor_stringcomplete = false; //have we received all the data from the Atlas Scientific product
void setup() {
Serial.begin(38400); //set baud rate for the hardware serial port to 38400
myserial.begin(38400); //set baud rate for software serial port to 38400
inputstring.reserve(5); //set aside some bytes for receiving data from the PC
sensorstring.reserve(30); //set aside some bytes for receiving data from Atlas Scientific product
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.clear();
lcd.print("r:");
lcd.setCursor(8,0);
lcd.print("g:");
lcd.setCursor(0,1);
lcd.print("b:");
}
void serialEvent() { //if the hardware serial port receives a char
char inchar = (char)Serial.read(); //get the char we just received
inputstring += inchar; //add it to the inputString
if(inchar == '\r') {input_stringcomplete = true;} //if the incoming character is a <CR>, set the flag (Last letter of the sentence
}
void loop() {
if (input_stringcomplete){ //if a string from the PC has been recived in its entierty
myserial.print(inputstring); //send that string to the Atlas Scientific product
inputstring = ""; //clear the string:
input_stringcomplete = false; //reset the flage used to tell if we have recived a completed string from the PC
}
while (myserial.available()) { //while a char is holding in the serial buffer
char inchar = (char)myserial.read(); //get the new char
sensorstring += inchar; //add it to the sensorString
if (inchar == '\r') {sensor_stringcomplete = true;} //if the incoming character is a <CR>, set the flag
}
if (sensor_stringcomplete){ //if a string from the Atlas Scientific product has been received in its entirety
//Serial.print(sensorstring); //use the hardware serial port to send that data to the PC
Serial.print(" ");
Serial.print("string received:"); //The serial monitor(pc/mac/other) will output: string received:
Serial.println(sensorstring); //and the actual text string that the Flow meter circuit has transnmited.
sensorstring = ""; //clear the string:
sensor_stringcomplete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
}
//string to char
char carray[sensorstring.length() + 1]; //determine size of the array
sensorstring.toCharArray(carray, sizeof(carray)); //put readStringinto an array
char* TV=strtok(carray, ","); //let's pars the string at each comma.
int TV_int=atoi(TV);
char* LPM=strtok(NULL, ","); //let's pars the string at each comma.
int LPM_int=atoi(LPM);
char* LPH=strtok(NULL, ","); //let's pars the string at each comma.
int LPH_int=atoi(LPH);
Serial.print("TV:'"); //We now print each value we parsed sepratly.
Serial.print(TV_int); //this is the Total Volume value.
Serial.println("'");
delay(10);
Serial.print("LPM:'"); //We now print each value we parsed sepratly.
Serial.print(LPM_int); //this is the Liquid Per Min value.
Serial.println("'");
delay(10);
Serial.print("LPH:'"); //We now print each value we parsed sepratly.
Serial.print(LPH_int); //this is the Liquid per Hour value.
Serial.println("'");
delay(10);
}
if (sensor_stringcomplete){ //if a string from the Atlas Scientific product has been received in its entirety
//use the hardware serial port to send that data to the PC
Serial.print(" ");
Serial.print("string received:"); //The serial monitor(pc/mac/other) will output: string received:
Serial.println(sensorstring); //and the actual text string that the Flow meter circuit has transnmited.
sensorstring = ""; //clear the string:
sensor_stringcomplete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
}
//string to char
char carray[sensorstring.length() + 1]; //determine size of the array
sensorstring.toCharArray(carray, sizeof(carray)); //put readStringinto an array
If you clear the String before extracting the data from it for parsing, then when you extract the data for parsing, you aren't going to get much. The parsing code goes BEFORE the clear.
How hard is it to print out the string before you parse it, with delimiters to show where it starts and ends? I've lost track of how many times this has been advised and you have still not done it yet. I've literally given you the code to parse the string in the way you want to. All you need to do is apply it to the correct string.
I agree with PeterH. Why won't you print carray? That is what you are parsing (or trying to). If carray does not match sensorstring, you have one problem. If it does, you have another problem. So, which problem are we trying to solve?
Thanks everyone... especially PaulS and PeterH , after I digest for awhile I finally understood because I was too stress up with the computer program side as I'm very new to programming, you can say I started a few weeks ago.....
Okay the code is working already I know where I went already thanks for all the advices you have gave me I appreciate it a lot. I hope to learn more from you guys.
For those who is looking at this thread actually the answer was posted in the forum already... is just that I wasn't able to understand that's all....