0

I try to detect commands given by user in Serial Monitor, but strcmp fails to flag as identical.

What do I do wrong ?

Is there a better way not reading as String and convert to char for comparison ?

Guy

char* additional_callbacks [] = {"command_1", "command_2", "command_3"};

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

void loop() {
  if (Serial.available() > 0) {
    char tmpchar[50];

    Serial.print("entered_text:");
    String str = Serial.readString();
    str.toCharArray(tmpchar, 50);
    Serial.println(tmpchar);

    for (int i = 0; i < sizeof(additional_callbacks) / sizeof(char*); i++) {
      if (strcmp(tmpchar, additional_callbacks[i]) == 0) {
        Serial.println("match");
      }
    }
    Serial.flush();
  }
  delay(50);
}
5
  • 1
    are you sure the input string is exactly one of the "command"s ... i.e. is there a end-of-line character being sent for example Commented Dec 29, 2018 at 8:33
  • We don't use the Serial.readString because it sometimes waits for data, although it has a timeout. The Serial.flush can not be used to clear the input buffer: arduino.cc/en/Serial/Flush At this moment it is best to write your own code to read data from the serial port. Commented Dec 29, 2018 at 9:00
  • 1
    you can use readBytesUntil to read text from Serial to char array Commented Dec 29, 2018 at 10:02
  • @JaromandaX I send ‘command_1’ as input and get no match Commented Dec 29, 2018 at 10:07
  • Guy D. we know that you send that command and we know that the sketch does not work. The serial monitor might add extra charaters after the 'command_1', a line feed or carriage return character. Even if you fix that, there is still a synchronization problem, the sketch does not know the start or the end of the characters of a command. Commented Dec 29, 2018 at 13:10

2 Answers 2

1

In your for() loop, use Serial.println() to display both strings before the compare. You'll be able to see why the compare is failing.

Update:

it seemed identical.

Something has to be different for the test to fail. If the strings look identical then there must be some non-printing characters that differ: \r, \n, , , missing \0 ), etc.

Try printing your buffers byte-by-byte in hex for a few more bytes than the string length, to be sure there is an where it should be.

Or print the buffers with this hexdump function which lists a specified memory range in both ASCII and hex:

/***

Name:       hexdump

Function:   Dump memory contents to terminal

Description:Dump a specified range of memory in hex and ASCII

Parameters: byte *mem       - starting address
            uint16_t len    - # of bytes

Returns:    void

Notes:      Based on: http://grapsus.net/blog/post/Hexadecimal-dump-in-C
            Formats with sprintf(); outputs with Serial.print().
            Modified to print ...0 - ...F of each hex-block containing
            any of the requested memory range. Data not in the range are
            not shown.

***/



void hexdump(byte *mem, uint16_t len)
{
   byte *p, *pfirst, *plast;    // -> curr byte, first & last hex-blocks to print from
   char buf[10+1];              // sprintf o/p buffer


   // Print entire hex-blocks that contain the requested mem range,
   // except only show data within the range.
   pfirst = (byte *)((uint16_t)mem & 0xFFF0);           // beg of 1st  hex-block
   plast = (byte *)((uint16_t)(mem + len) | 0xF);       // end of last hex-block

   for( p = pfirst;  p <= plast;  ++p ){

      /* Print block addr */
      if( ((byte *)((uint16_t)p & 0xF)) == 0 ){
         sprintf_P(buf, PSTR("%06X: "), (unsigned int)p);
         Serial.print(buf);
      }

      // Print hex data, or if outside mem range, print spaces
      if( mem <= p && p < (mem + len) ){
         sprintf_P(buf, PSTR("%02hhX "), *p);
         Serial.print(buf);
      }
      else
         Serial.print("   ");                   // outside requested range - just spaces

      // Maybe print gutters and/or ASCII data
      if( ((uint16_t)p & 0xF) == 0x7 )
         Serial.print(" ");                     // narrow gutter after 8 bytes
      // If at end of hex block, print a gutter & re-print the block as ASCII
      if( ((uint16_t)p & 0xF) == 0xF ){
         Serial.print("  ");                    // wide gutter after 16 bytes

         // Print as ASCII.
         // Note: In this loop, we re-use the outer loop's index, 'p', to rescan
         // the hex block. We must leave 'p' as we found it!
         for( p = (byte *)((uint16_t)p & 0xFFF0);  ; ++p ){
            if( !(mem <= p && p < mem+len) )
               Serial.print(' ');               // not in requested mem range
            else if( !isprint(*p) )
               Serial.print('.');               // not printable
            else
               Serial.print(*(char *)p);        // print as ASCII

            if( ((uint16_t)p & 0xF) == 0xF ){
               break;                           // end of hex-block
            }
         }
         Serial.print('\n');
      }
   }
}
1
  • Already test, and it seemed identical. Perhaps what Martin say has something to do with it ( will try it later ) Commented Dec 29, 2018 at 16:21
-1

You try to compare Serial input

command_1\r\n

with

command_1

and these two are not equal.

2
  • Can you elaborate, to make this a proper answer rather than a comment? Commented Dec 29, 2018 at 19:02
  • Thanks Michael, i will regard this next time. Commented Dec 30, 2018 at 3:06

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.