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);
}
asked Dec 29, 2018 at 6:34
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');
 }
 }
}
answered Dec 29, 2018 at 14:11
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.

leoc7
6034 silver badges12 bronze badges
answered Dec 29, 2018 at 16:04
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

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.