Hallo there, for our projects based on several types of arduino I want make standard serial interface.
Since this must also work on older versions I want to avoid the String functions since they are slow.
For now I just read the serial interface byte by byte and store this in a char array.
After I have all the characters I want to compare them with some other char arrays
So for example I send ID? via the serial bus and it gives me the ID number back
However the comparison always fails
some how the char arrays are not equal.
here is my code
char inputbuf[32];
char Test[]="ID?";
char Test2[]="Test";
int counter;
void setup() {
Serial.begin(9600);
inputbuf[0]='\0';
counter=0;
}
void loop() {
while (Serial.available()>0)
{
inputbuf[counter] = Serial.read();
counter++;
}
if (counter>0)
{
inputbuf[counter]='\0'; // also without this line the comparison fails
Serial.println(inputbuf); // this shows ID?
if (strcmp(inputbuf,Test)==0)
{
Serial.println(inputbuf); // this is never reached
}
inputbuf[0]='\0';
counter=0;
}
}
Not exactly, but it depends on your "serial protocol". Are all the commands the same size in terms of characters ora can be variable lengths? Do you use a "line terminator" character?
Based on your description, the answer is "no, the commands are variable and use line terminating characters \r\n sent from the Serial monitor input".
To make things easier, my advise is to use single-character commands, for example just "I" (followed by "\r\n" automatically added) for Info request, or "T" for test.
But if you want to keep your syntax, your sample code to receive a command and compare with some fixed command strings could be something like this one:
#define MAXBUF 32
char inputbuf[MAXBUF];
int counter = 0;
bool cmdReceived = false;
// Fixed commands list (note
#define CMD_ID "ID?"
#define CMD_TEST "TEST"
void setup() {
Serial.begin(9600);
}
void bufReset() {
inputbuf[0]='\0';
counter=0;
cmdReceived = false;
}
void bufAdd(char c) {
// Ignore '\r' and '\n' and avoid buffer overflow
if (c != '\r' && c != '\n' && counter+1 < MAXBUF) {
// Convert to uppercase if needed
if (c >= 'a' && < <= 'z') c = c - 'a' + 'A';
inputBuf[counter++] = c;
inputBuf[counter] = '\0';
}
// If LF has been received, the command is complete
cmdReceived = (c == '\n');
}
void loop() {
if (Serial.available()>0) {
bufAdd(Serial.read());
}
if (cmdReceived) {
Serial.print("Received: ");Serial.println(inputbuf);
if (strcmp(inputbuf,CMD_ID)==0)
{
Serial.println("The ID is 1");
}
else if (strcmp(inputbuf,CMD_TEST)==0)
{
Serial.println("Test OK");
}
else
Serial.println("Unkown command");
// Reset buffer
bufReset();
}
}
Please note the changes I made, including "strcasecmp()" function to compare ignoring upper/lower case, and the usage of two useful functions for an easier handling of the buffer...
Well, strncmp() compares the strings given the number of chars to be compared, so it isn't wrong, but if you have a command like "Test1234-this and that" it will satisfy the condition because it compares just the first 4 characters: is it really what you want to get?
Post your entire (new) code, so I can get the whole context...
Ok, so the behavior of that piece of code is any command starting with the given string is accepted, including "?xyz" as "?", "TestJoe" as "Test" and so on. Is this what you really need?
And I still can't get why using just "strcmp()" (as per my code example, shich I can assure you it works correctly), why you said you needed to use "strncmp()"?
I am aware of the fact this code doesn't handle all the incoming data in a correct manner. But in this case we only use the devices for automating some measurment setup's.
For this we also make our own PC software so we can control the commands we are sending.
regarding the strcmp function I guess I have to take into account the '\n' or '\0' characters as well when comparing the two strings.
True, strcmp() is a string (lowercase s) function but it is not a String (uppercase S) function and thus using it is part of the strategy of avoiding using Strings