Сравнение строк при использовании последовательного порта
Я пытаюсь обнаружить команды, данные пользователем в Serial Monitor, но strcmp
не помечается как идентичный.
Что я делаю не так?
Есть ли лучший способ не читать как String
и конвертировать в char
для сравнения?
Парень
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);
}
@Guy . D, 👍0
Обсуждение2 ответа
В цикле for() используйте Serial.println() для отображения обеих строк перед сравнением. Вы сможете увидеть, почему сравнение не удалось.
Обновление:
Кажется одинаково.
Чтобы тест провалился, должно быть что-то другое. Если строки выглядят одинаково, то должны быть некоторые непечатаемые символы, которые различаются: \r, \n, , , отсутствует \0 ) и т. д.
Попробуйте распечатать буферы побайтово в шестнадцатеричном формате, чтобы на несколько байтов больше длины строки, чтобы убедиться, что это именно то место, где оно должно быть.
Или распечатайте буферы с помощью этой функции шестнадцатеричного дампа, которая выводит указанный диапазон памяти как в ASCII, так и в шестнадцатеричном формате:
/***
Название: шестнадцатеричный дамп
Функция: Дамп содержимого памяти на терминал.
Описание: Дамп указанного диапазона памяти в шестнадцатеричном формате и ASCII.
Параметры: byte *mem — начальный адрес
uint16_t len — количество байтов
Возврат: недействителен
Примечания: На основе: http://grapsus.net/blog/post/Hexadecimal-dump-in-C.
Форматирует с помощью sprintf(); выводит с помощью Serial.print().
Изменено для печати ...0 - ...F каждого шестнадцатеричного блока, содержащего
любой из запрошенного диапазона памяти. Данные за пределами диапазона
не показано.
***/
void hexdump(byte *mem, uint16_t len)
{
byte *p, *pfirst, *plast; // -> текущий байт, первый & последние шестнадцатеричные блоки для печати
char buf[10+1]; // буфер sprintf o/p
// Распечатываем целые шестнадцатеричные блоки, содержащие запрошенный диапазон памяти,
// кроме отображения только данных в пределах диапазона.
pfirst = (byte *)((uint16_t)mem & 0xFFF0); // начало 1-го шестнадцатеричного блока
plast = (byte *)((uint16_t)(mem + len) | 0xF); // конец последнего шестнадцатеричного блока
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);
}
// Печатаем шестнадцатеричные данные или, если они находятся вне диапазона памяти, печатаем пробелы
if( mem <= p && p < (mem + len) ){
sprintf_P(buf, PSTR("%02hhX "), *p);
Serial.print(buf);
}
else
Serial.print(" "); // вне запрошенного диапазона - только пробелы
// Возможно, распечатываем желоба и/или данные ASCII
if( ((uint16_t)p & 0xF) == 0x7 )
Serial.print(" "); // узкий интервал после 8 байт
// Если в конце шестнадцатеричного блока, выводим желоб & перепечатать блок как ASCII
if( ((uint16_t)p & 0xF) == 0xF ){
Serial.print(" "); // широкий интервал после 16 байт
// Печатаем как ASCII.
// Примечание. В этом цикле мы повторно используем индекс внешнего цикла «p» для повторного сканирования.
// шестнадцатеричный блок. Мы должны оставить «p» таким, каким мы его нашли!
for( p = (byte *)((uint16_t)p & 0xFFF0); ; ++p ){
if( !(mem <= p && p < mem+len) )
Serial.print(' '); // не в запрошенном диапазоне памяти
else if( !isprint(*p) )
Serial.print('.'); // не для печати
else
Serial.print(*(char *)p); // печатаем как ASCII
if( ((uint16_t)p & 0xF) == 0xF ){
break; // конец шестнадцатеричного блока
}
}
Serial.print('\n');
}
}
}
Уже тестировал, вроде идентично. Возможно, то, что сказал Мартин, имеет к этому какое-то отношение (попробую позже), @Guy . D
Вы пытаетесь сравнить последовательный вход
command_1\r\n
с
команда_1
и эти двое не равны.
Можете ли вы уточнить, чтобы это был правильный ответ, а не комментарий?, @MichaelT
Спасибо, Михаил, я учту это в следующий раз., @Martin Dittrich
- Как разделить входящую строку?
- Как вывести несколько переменных в строке?
- форматирование строк в Arduino для вывода
- Очень простая операция Arduino Uno Serial.readString()
- Arduino Преобразование std:string в String
- Как прочитать входящие ШЕСТНАДЦАТИРИЧНОЕ значение из serial метод read ()?
- Arduino Serial.ReadString() проблема
- Очистка строкового буфера с помощью memset после последовательного чтения
Вы уверены, что входная строка **точно** является одной из «команд»... т.е. отправляется ли, например, символ конца строки?, @Jaromanda X
Мы не используем Serial.readString, поскольку он иногда ожидает данных, хотя у него есть тайм-аут. Serial.flush нельзя использовать для очистки входного буфера: https://www.arduino.cc/en/Serial/Flush. На данный момент лучше всего написать собственный код для чтения данных из последовательного порта., @Jot
вы можете использовать readBytesUntil для чтения текста из последовательного порта в массив символов, @Juraj
@JaromandaX Я отправляю «command_1» в качестве входных данных и не получаю совпадений, @Guy . D
Гай Д., мы знаем, что вы отправили эту команду, и знаем, что скетч не работает. Монитор последовательного порта может добавлять дополнительные символы после «command_1», символа перевода строки или возврата каретки. Даже если вы это исправите, проблема с синхронизацией все равно остается: скетч не знает начала и конца символов команды., @Jot