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);
}
-
1are you sure the input string is exactly one of the "command"s ... i.e. is there a end-of-line character being sent for exampleJaromanda X– Jaromanda X2018年12月29日 08:33:09 +00:00Commented 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.Jot– Jot2018年12月29日 09:00:08 +00:00Commented Dec 29, 2018 at 9:00
-
1you can use readBytesUntil to read text from Serial to char arrayJuraj– Juraj ♦2018年12月29日 10:02:43 +00:00Commented Dec 29, 2018 at 10:02
-
@JaromandaX I send ‘command_1’ as input and get no matchguyd– guyd2018年12月29日 10:07:41 +00:00Commented 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.Jot– Jot2018年12月29日 13:10:06 +00:00Commented Dec 29, 2018 at 13:10
2 Answers 2
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');
}
}
}
-
Already test, and it seemed identical. Perhaps what Martin say has something to do with it ( will try it later )guyd– guyd2018年12月29日 16:21:31 +00:00Commented Dec 29, 2018 at 16:21
You try to compare Serial input
command_1\r\n
with
command_1
and these two are not equal.
-
Can you elaborate, to make this a proper answer rather than a comment?MichaelT– MichaelT2018年12月29日 19:02:15 +00:00Commented Dec 29, 2018 at 19:02
-
Thanks Michael, i will regard this next time.Martin Dittrich– Martin Dittrich2018年12月30日 03:06:29 +00:00Commented Dec 30, 2018 at 3:06