Pages: [1] 2   Go Down
Author Topic: Receiving serial data as string and comparing them with other strings  (Read 1185 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello smiley ,

This is what I want to achieve:
I am sending some data serially (currently from the serial monitor). I want it such that when I receive some particular codes such as "on1",  "of1" the arduino should do some action. Otherwise it should print the data on the LCD.

This is how I am trying to achieve it right now (which is not correct in some way):
I am sending data from serial monitor. Receiving it in a character array. comparing it with the two command words I mentioned before by "==" ( Is it correct??) and then switching ON LED at pin 13 if the command is "on1", switching it off if its "of1" and printing on the serial terminal if it is neither.

This is the problem:
All the data that I am sending is being printed on the serial terminal including "on1", "of1" commands.

This is the code:
Code:
int ledPin = 13;           
const int maxLength=140;        //maximum length for textbox data
char char_in[maxLength];  //Create a buffer to input all incoming data
int i=0;
void setup() {

  pinMode(ledPin, OUTPUT);  //Configure pins as output

  Serial.begin(9600);      //begin serial communication

}


void loop() {

  if (Serial.available() > 0)     //Is any serial data available
  {


    for( i=0;i<maxLength && Serial.available();i++)
    {
      char_in[i] = Serial.read();
 
    }
 
    if (char_in=="on1")
    {
      digitalWrite(ledPin,HIGH);
    }
    else if(char_in == "of1")
    {
      digitalWrite(ledPin,LOW);
    }
    else
    {
      Serial.print(char_in);

    }

  }

}





I am a bit confused about how character arrays and strings are distinguished and I doubt the problem is because of that.

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8590
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A null-terminated char array is often called a string, a String is a C++ class.

== won't work with an array of char, use strcmp() or make char_in a String (not the preferred option on a small chip like the Arduino).

Also you have to terminate char_in with a '\0'.

 
Code:
    char_in[i++] = Serial.read();
      char_in[i] = '\0';

_____
Rob
« Last Edit: March 08, 2012, 05:47:42 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello Graynomad, thanks for your help smiley
I have changed my program as you suggested. I have included a null terminator and used strcmp but still the output is same smiley-sad
Do you see any logical error in my code?



Code:
int ledPin = 13;           
const int maxLength=140;        //maximum length for textbox data
char char_in[maxLength];  //Create a buffer to input all incoming data
int i=0;
void setup() {

  pinMode(ledPin, OUTPUT);  //Configure pins as output

  Serial.begin(9600);      //begin serial communication

}


void loop() {

  if (Serial.available() > 0)     //Is any serial data available
  {


    for( i=0;i<maxLength && Serial.available();i++)
    {
      char_in[i] = Serial.read();
   
    }
 
   char_in[i+1]='\0';
    if (!strcmp(char_in,"on1"))
    {
      digitalWrite(ledPin,HIGH);
    }
    else if(!strcmp(char_in,"of1"))
    {
      digitalWrite(ledPin,LOW);
    }
    else
    {
      Serial.print(char_in);

    }

  }
 


}

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8590
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

i<maxLength && Serial.available()

The first time Serial.available() fails the loop ends, that will be after the first character.

Hint, get used to printing things to see exactly what you have,  the results often point you to the error, in this case print char_in after the loop.

______
Rob

« Last Edit: March 08, 2012, 05:48:10 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now I think we are getting close, but I see something strange happening
When I added the line
Code:
Serial.println(char_in[i]);
, each character that was being stored in char_in got printed in a new line( like it should). But now the action that was to be performed is being done nicely (LEDs are turning on and off like they should). I cannot figure out why the program is running like it should after this line..

When I remove it the old behaviour starts.

The loop to give '0' values to each element is added to flush out the garbage values from previous serial input.





Code:
int ledPin = 13;           
const int maxLength=140;        //maximum length for textbox data
char char_in[maxLength];  //Create a buffer to input all incoming data
int i=0;
void setup() {

  pinMode(ledPin, OUTPUT);  //Configure pins as output

  Serial.begin(9600);      //begin serial communication

}


void loop() {

  if (Serial.available() > 0)     //Is any serial data available
  {
 for( i=0;i<maxLength;i++)
    {
      char_in[i] = 0;
    }

    for( i=0;i<maxLength && Serial.available();i++)
    {
      char_in[i] = Serial.read();

   Serial.println(char_in[i]);
    }
    //  Serial.print(char_in);
   char_in[i+1]='\0';
    if (!strcmp(char_in,"on1"))
    {
      digitalWrite(ledPin,HIGH);
    }
    else if(!strcmp(char_in,"of1"))
    {
      digitalWrite(ledPin,LOW);
    }
    else
    {
      Serial.print(char_in);

    }

  }
 


}

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8590
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I cannot figure out why the program is running like it should after this line..
The act of printing the char is effectively adding a delay, so when the loop iterates again enough time has passed for another character to be received by the serial port. Remove the printing and the loop runs so fast that it's finished before the next character has arrived.

Given that it seems you will always have 3 characters I think the simplest thing to do is

 
Code:
while (Serial.available() < 3); // wait for three characters
  for( i = 0 ; i < 3;) // stick them in the array, you could use memcpy() here
    {
      char_in[i++] = Serial.read();
    }
   char_in[i] = '\0';

(far from bullet proof but should work)

The for loop to clear the array is not necessary as the array will be overwritten anyway. However to be safe you can null the string by just placing a \0 in the first location.

______
Rob
« Last Edit: March 08, 2012, 07:06:05 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you! Thank you! Thank you!

I removed the Serial.println and added a delay. It is working perfect!!! smiley-grin

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8590
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I removed the Serial.println and added a delay.
Dodgy but you're not the first smiley

I wouldn't do it on code for the Mars rover though.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Its a part of small proof-of-concept sort of project for college. So nothing critical. Also I have to display messages that are not command words on LCD so I cannot use the 3 character method( or any method with fixed number of characters smiley ).

So, I think I will just cross my fingers and pray that it will work. After all, that'ss what programmers do smiley-grin
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So, I think I will just cross my fingers and pray that it will work. After all, that'ss what programmers do
Not good ones. Good ones address the underlying issue and write bullet-proof code. You, on the other hand, sound like a future Microsoft employee.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Any suggestions PaulS?

I am trying too hard to get a lot of things working. Maybe I will keep this in my mind and get back to this problem when my work is complete. smiley

Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 633
Posts: 50210
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you have control over the sender? If so, then you should add start and end of packet markers to the packets you send. This way, you can read and store all the serial data as it arrives, as fast as it arrives, and only do something with the data when the end of packet marker arrives.

"PaulS SOP EOP" in the search field will get you code I post regularly that reads properly packet-ed data.

If you don't have control over the data stream, then you must determine what is in the stream that bounds a packet. Hopefully, it is not just a matter of timing. If it is, you should wait until near the end of the time between packets before reading all the data, with no delays. You will, of course, miss a few packets learning about the timing, if it is only timing that delimits packets. Your initial post indicates that you do have control, though.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks PaulS and yes I have full control on the data which is being sent.

This seems like a great idea. I will try to get it working in my code.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 129
Posts: 8590
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The sort of thing we normally suggest is like this

<some data>

Your code waits for the '<' character then starts accumulating characters until it sees the '>' character. Then it parses the data.

This provides a couple of mechanisms that make the code more robust.

Note that this only works if < and > will never appear in your data. If they might then use different characters that don't. This also means that this technique cannot be used for binary data.

_____
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have had an arduino from a long time, but the real learning is starting now.
Thanks Graynomad, these characters are not going to be in my input so I will soon try what you and PaulS suggested.

Thanks again you too!
Logged

Pages: [1] 2   Go Up
Jump to: