Сравнение строк при использовании последовательного порта

Я пытаюсь обнаружить команды, данные пользователем в 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);
}

, 👍0

Обсуждение

Вы уверены, что входная строка **точно** является одной из «команд»... т.е. отправляется ли, например, символ конца строки?, @Jaromanda X

Мы не используем Serial.readString, поскольку он иногда ожидает данных, хотя у него есть тайм-аут. Serial.flush нельзя использовать для очистки входного буфера: https://www.arduino.cc/en/Serial/Flush. На данный момент лучше всего написать собственный код для чтения данных из последовательного порта., @Jot

вы можете использовать readBytesUntil для чтения текста из последовательного порта в массив символов, @Juraj

@JaromandaX Я отправляю «command_1» в качестве входных данных и не получаю совпадений, @Guy . D

Гай Д., мы знаем, что вы отправили эту команду, и знаем, что скетч не работает. Монитор последовательного порта может добавлять дополнительные символы после «command_1», символа перевода строки или возврата каретки. Даже если вы это исправите, проблема с синхронизацией все равно остается: скетч не знает начала и конца символов команды., @Jot


2 ответа


1

В цикле 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


-1

Вы пытаетесь сравнить последовательный вход

command_1\r\n

с

команда_1

и эти двое не равны.

,

Можете ли вы уточнить, чтобы это был правильный ответ, а не комментарий?, @MichaelT

Спасибо, Михаил, я учту это в следующий раз., @Martin Dittrich