Побеждаем кольцевой буфер

Я понимаю что через одно место это всё, но когда ищу конец строки, нашла, проверила та ли эта команда, ответ на которую я жду, если та, проверяю ОК и далее…вроде всё просто.

нет, любой из этот методов будет медленнее чем тупо поиск strstr и им подобным!

мне в свое время пришлось этим заморочиться, поскольку функционал скетча настолько разросся, что тупо не стало хватать памяти, оставался один вариант → уменьшать входной буфер, соответственно ответы модема стали тупо не влазить. Ну и понеслось…куча экспериментов, поиск оптимального алгоритма и прочее…

1 лайк

его не надо искать - каждый пришедший байт из модема и есть конец строки.

вы передаете в функцию два символа, а не символ и массив как задумывали

Если честно, я не понял для чего нужен еще один буфер при приеме строки через сериал, но может это Вам както поможет https://arduino.ru/forum/programmirovanie/poisk-nuzhnoi-stroki-pri-rabote-s-com-portom#comment-635310

памяти в МК мало, длинные ответы из модема иногда не влазят в буфер, а обработать хочется.
типа так:

07919702926033F1640B919702369149F6000022909161808021A0050003390201986FF71954749FD9E9391A346D4E41EE72990CA287E165503BED4EB7EB6D50CC06038DD161F91C7446A3CF665B8D263F83D075FA195DB7D9E86734089D3FD7F3799BCD763E83D0E873DE56AB99CFC6F3198D06D5CF67BAF98CCEA3D1209B8D7E3EA3D168F4F97C46A35DA0E3F99CB7D96A35FA198D06A1EBF433BA5E4783D2681CEE76B3E5CF

А как передать массив символов?

    const char *s[] = "+CCALR: 1";
    if (sim800.substring_search(text[counter], s)) Serial.println("Network_found");
    counter++;

передали вы правильно массив символов, функцию описали неправильно, и компилятор честно об этом сказал.

const char *s[] = "+CCALR: 1";
    if (sim800.substring_search(text[counter], s)) Serial.println("Network_found");
    counter++;

передала массив, а читаю символ?

На скорости 9600 бод надо 64 мс сопли жевать чтоб приемный буфер переполнился. Вместо того чтоб обрабатывать приходящую строку, мы еще 50 байт выделим под буфер, потомучто у нас памяти мало. Нихрена не понял.

э…че то мне кажется что вы не совсем понимаете то, что хотите реализовать :frowning:

хочу вернуться к вчерашнему комментарию:
Выкиньте весь свой код, напишите минимальную программу, которая отсылает в модем AT\r и после каждой отправки ищет/ждеи в кольцевом буфере длиной 6 байт ответ OK\r\n и только потом шлет следующую команду. Потом уже будете усложнять.

P.S. И не понимаю - почему не хотите разобтраться с готовыми примерами выше? и сделать по аналогии или вообще copy/paste а потом улучшать по своим хотелкам.

Вот и я читаю и не понимаю, зачем это все нужно.
Если хочется обрабатывать строки длиннее, чем объем оперативной памяти, так для этого нужен не кольцевой буфер, а конечный автомат.
А что касается кольцевого буфера, то он уже есть у UART и другого - дополнительного - не нужно.

Хочу передать в функцию массив символов для их поиска в буфере.

Так сейчас и сделаю, хочу полностью понять алгоритм работы кольцевого буфера.

не правильно рассуждаете, прилетает данных например 600 байт, если их принять от модема скопом, то нужен и буфер соответствующего размера, то нафиг не нужен кольцевой буфер - дождемся \r\n и спокойно обработаем.
Но как только мы кроме работы с модемом должны еще что то делать online, то упираемся или в память или в быстродействие .

Кольцевой буфер для этого не предназначен. У него вообще нет таких методов, чтобы в нем что-то искать.
Если у Вас вдруг получилось, что хочется что-то искать в кольцевом буфере, значит, Вы неправильно спроектировали задачу.

1 лайк

Вы имеете ввиду нужно сравнивать каждый пришедший символ с искомой строкой? Как я делала выше, а не записывать байты в новый буфер?

“Фило” - это название шикки у Анчифы Мелифаро в “Эхо” Макса Фрая. А стек называется LIFO.

Да, да. Как то извращённо я подумал. Совсем мозги уже набекрень.)

Собственно конечный автомат так и должен делать: сравнивать очередной пришедший байт, только не со строкой, а с очередным символом в строке (т.е. сравнивать не один байт с массивом, а один байт с одним байтом). Если сравнение успешно - идем дальше, пока не достигнем конца строки. Достигли - строка найдена. Если очередной байт не совпал - сбрасываем индекс очередного байта внутри строки.

1 лайк

Есть такой алгоритм. Нужно очень хорошо знать теорию конечных автоматов и заранее строить таблицу переходов - на сколько символов можно сместиться после неудачного сравнения пришедших с началом строки. Это очень быстрый алгоритм поиска слова в потоке, но трудный для реализации.
Проще так:

  1. принимаем символы. пока их последовательность совпадает с началом строки. Перемещаем маркер по образцу (искомой строке) по мере прихода символов.
  2. как только принятый кусок не соответствует началу строки, двигаем маркер назад по образцу, пока начало образца до маркера не совпадет с “хвостом” принятых символов.
  3. едем дальше.
    помнить не нужно НИЧЕГО, кроме последнего символа так как “хвост” до него совпадал с началом образца.

Прошу прощения, что несколько занудно. Конечно можно алгоритмически проще написать, но я привел “эталонный” алгоритм поиска. Только таблицу “переходов назад” обычно считают до начала поиска. В таблице пишут положения маркера и входной символ. Если не считать её заранее - то так, как я написал.