Offline
Newbie
Karma: 0
Posts: 28
|
 |
« on: March 07, 2012, 11:37:13 pm » |
Hello  , 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: 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
Tesla Member
Karma: 71
Posts: 6824
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #1 on: March 08, 2012, 04:11:48 am » |
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'. char_in[i++] = Serial.read(); char_in[i] = '\0'; _____ Rob
|
|
|
|
« Last Edit: March 08, 2012, 05:47:42 am by Graynomad »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #2 on: March 08, 2012, 05:16:47 am » |
Hello Graynomad, thanks for your help  I have changed my program as you suggested. I have included a null terminator and used strcmp but still the output is same  Do you see any logical error in my 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
Tesla Member
Karma: 71
Posts: 6824
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #3 on: March 08, 2012, 05:38:30 am » |
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
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #4 on: March 08, 2012, 06:13:51 am » |
Now I think we are getting close, but I see something strange happening When I added the line 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. 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
Tesla Member
Karma: 71
Posts: 6824
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #5 on: March 08, 2012, 07:00:01 am » |
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 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
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #6 on: March 08, 2012, 07:28:04 am » |
Thank you! Thank you! Thank you! I removed the Serial.println and added a delay. It is working perfect!!! 
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6824
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #7 on: March 08, 2012, 07:35:49 am » |
I removed the Serial.println and added a delay. Dodgy but you're not the first  I wouldn't do it on code for the Mars rover though. ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #8 on: March 08, 2012, 07:39:27 am » |
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  ). So, I think I will just cross my fingers and pray that it will work. After all, that'ss what programmers do 
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 313
Posts: 35506
Seattle, WA USA
|
 |
« Reply #9 on: March 08, 2012, 12:31:51 pm » |
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
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #10 on: March 08, 2012, 12:52:31 pm » |
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. 
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 313
Posts: 35506
Seattle, WA USA
|
 |
« Reply #11 on: March 08, 2012, 02:47:06 pm » |
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
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #12 on: March 08, 2012, 03:05:12 pm » |
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
Tesla Member
Karma: 71
Posts: 6824
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #13 on: March 08, 2012, 04:44:18 pm » |
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
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 28
|
 |
« Reply #14 on: March 08, 2012, 10:52:32 pm » |
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
|
|
|
|
|
|