Reading text from serial and compare the input always fails

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; 
 } 
}

inputbuf[counter+1]='\0';

Try this

Thanks that helps.
After the last read the counter is already increased but apperantly the '\0' should be 1 position further

oops i replied to soon this also didn't work

If the Serial input is coming from the Serial monitor then what have you got the Line Ending set to ?

Have you tried printing the length of the string before comparing it ?

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...

I suspect that this is the most referred to tutorial: Serial Input Basics - updated.

You can study it to get ideas.

I found the issue.
It was indeed due to the length of the two char arrays.
I solved it by using the strncomp function

if (strncmp(command, "Test",4) == 0)

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...

This is the working code

# include "FlashAsEEPROM.h"

const int MAX_COMMAND_LENGTH = 32;
char command[MAX_COMMAND_LENGTH];
int commandIndex = 0;

const String IDNr = "ODDeviceName_";
const byte SerialNrAddress = 0;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  // Read incoming serial data
  while (Serial.available() >0) 
  {
    char inChar = Serial.read();
    
    if (commandIndex < MAX_COMMAND_LENGTH - 1) 
    {
      command[commandIndex] = inChar;
      commandIndex++;
    }
  }
  if (commandIndex>0) 
  {
    command[commandIndex] = '\0'; // Null-terminate the string
    processCommand();

    commandIndex = 0;
  }
}

void processCommand() 
{
  if (strncmp(command, "?",1) == 0) 
  {
    Serial.println("Data");
    return;
  }
  else if (strncmp(command, "Test",4) == 0) 
  {
    Serial.println("Test command received. System is operational.");
    return;
  }
  else if (strncmp(command, "ID?",3) == 0) 
  {
    byte SerieNr = EEPROM.read(SerialNrAddress);
    char buf[4];
    sprintf(buf,"%03d",SerieNr);
    Serial.println("ID="+IDNr + buf);    
    return;
  }
  else if (strncmp(command, "SN=", 3) == 0) 
  {
    byte serialNumber = atoi(command + 3);
    if (!EEPROM.isValid()) 
    {
     EEPROM.write(SerialNrAddress, serialNumber);
     return;     
    }
    EEPROM.commit(); 
    serialNumber = EEPROM.read(SerialNrAddress);
    char buf[4];
    sprintf(buf,"%03d",serialNumber);
    Serial.print("Serial number set to: ");
    Serial.println(buf);
    return;
  }
  else 
  {
    Serial.println("Unknown command");
    return;
  }
}

Maybe strstr makes life easier.

And as mentioned Robin's updated Serial Input Basics is always a good read.

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.

Sure, the strings to be compared must have the correct format, with the terminating '\0' characters.

but strcmp is a string function

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

You are right.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.