Hello everyone It's been a while since the last time I coded in Arduino and this is my first post in this forum.
I have a problem with serial communication and strings that might be too easy to solve but I don't see the answer without making many complex "useless" steps.
My code is fair simple I am using serial communication to send information to my Arduino in the form of "xyyy" where x is a letter ,yyy can be numbers from 0 to 360.
When I started coding this project realized I could use an if statement like this if(Serial.read()=='y') followed by the function Serial.parseInt(). I could know what letter is y and also get the integer number inside the code. However today I found out that this method only works the first time an if case structure is read by the code.
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available()>0)
{
if(Serial.read()=='a')
{
int data = Serial.parseInt();
Serial.print(data);
Serial.print('\t');
}
else if(Serial.read()=='b'){
int data = Serial.parseInt();
Serial.print(data);
Serial.print('\t');
}
}
}
If you run the code as I mentioned it will detect x and yyy if the input starts with a, it will never enter in the if structure if the input starts with b. if swapped around it will only detect inputs starting with b and so on.
After doing some research I think the problem is that after failing the first if every next if when using Serial.read() will try to read the Serial port and hence clearing the original input.
It would make sense saving that information into a variable like a String: if that was the case then I wouldn't be able to use the technique I mentioned before the code. And then I would have to create a char string to get y and then convert the rest of the array to form xxx multiply the units to form a number of max 3 digits. Which in my opinion is too much of a hassle when I already found a workaround.
So is there a way to simplify what I am trying to do or I should stick with the overkill code just to split a string that contains numbers and letters?
The serial input basics tutorial may be of interest. It shows how to read and parse serial data without blocking functions (parseInt) or the problematic String class.
Thanks I saw that post before but wasn't sure if my serial communication would be compatible with those examples, for now I solved my problem saving my input into a String variable and using Serial.readString() and learned that these functions are implemented into Arduino programming language: .startsWith(), .substring() and .toInt()
I agree @Delta_G's solution is the best choice, but another way could be to use Serial.peek(). Serial.peek() is like Serial.read() except is does not remove the character from the buffer.
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available()>0)
{
if(Serial.peek()=='a')
{
Serial.read(); //discard the 'a'
int data = Serial.parseInt();
Serial.print(data);
Serial.print('\t');
}
else if(Serial.peek()=='b'){
Serial.read(); //discard the 'b'
int data = Serial.parseInt();
Serial.print(data);
Serial.print('\t');
}
}
}
You should also understand that Serial.parseInt() can be tricky to use in some situations:
When you call Serial.parseInt(), it will wait for characters to arrive, and if they are digits, read them and wait for more digits, until a non-digit character arrives (which it does not remove from the buffer, it probably uses .peek() internally) or it times out while waiting.
If, while waiting for that first digit, it times out, it will return 0 and your code won't be able to tell if it actually read a 0 or timed out!
Similarly, it might read some digits, for example '2' followed by '7' and then time out while waiting for more digits. In this situation it will return 27, but your code won't be able to tell if '7' was actually the final digit or it timed out.
So Serial.parseInt() must be used with care and understanding of it's operation. In some situations, where it is vital to know if you got a number, the entire number, and timeouts are likely to happen, it may not be the best function to use.
if (Serial.read() == 'a' | 'b') has apparently worked for me (I did not check the response with c123) in respect of my following flawed reasoning:
"==" is not an assignment operator, So, the value returned by Serial.read() will be compared with 'a' for equality; else, it will be compared with 'b' for equality.
I want to thank everyone for taking their time replying and sharing information in this post I really learned new things from everyone.
Later this week I will try the different methods and write a conclusion by comparing them.