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

именно

Можно конечно реализовать полноценный FIFO буфер, искать строку с начальной позиции данных (размер) до конечной, но для вашей задачи и этого достаточно.

так так так, кодом не делитесь, дама сама сейчас будет думать XDDDD
Скоро скину код)

начните с попроще, выкиньте весь код работы с SIM800L, сделайте отправку команды АТ\r подряд пару тройку раз, буфер размером максимум 6 байт (для чистоты эксперимента, чтоб только OK\r\n влазило), и после каждой отправки ищите ответ.
Ну а потом уже по накатанной все легко пойдет, будет уже неважно сколько команд и какие ответы ожидаете, можно будет анализировать все (в пределах мощности МК конечно).

дык выше все есть, и велосипед не надо изобретать.

Не нужно это.
Если голова равна хвосту, значит, буфер пуст.

2 лайка

Где написано? В Википедии))))
Откуда вы можете знать где там у меня на ноль проверяется что либо?
И вообще логику программы? Или вы пару тыщь строк разобрали по кусочкам за вечер)))

Что у тебя лично проверяется, не имею ни малейшего понятия.
Я лишь утверждаю, что для кольцевого буфера это не нужно. От слова совсем.

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

Посмотрите пожалуйста.

Спойлер
#include <SoftwareSerial.h>
SoftwareSerial SIM800(9, 2);

#define MAX_BUF 50
char buffers[MAX_BUF];
uint8_t pos;

void setup() {
  Serial.begin(9600);
  SIM800.begin(9600);
  memset(buffers, 0, MAX_BUF);//Очистила буфер
}

void write_buffer(uint8_t temp) {
  if (temp) {
    if (pos >= MAX_BUF) pos = 0;
    buffers[pos] = temp;

    if (buffer_search(temp)) {
      Serial.println("String_found");
    }

    pos++;
  }
}

bool buffer_search(char temp) {
  const char inStr[] = "OKrn";
  uint8_t len_inStr  = sizeof(inStr) / sizeof(inStr[0]);

  if (temp == inStr[len_inStr - 2]) {//Если пришедший байт равен последнеу символу в искомой строке (сейчас \n)

    //Последний символ искомой строки = n
    Serial.print("Last_char = ");
    Serial.print(inStr[len_inStr - 2]);
    Serial.println("");

    //Позиция искомого символа в основном буфере = 6
    Serial.print("Pos_last_char_buf = ");
    Serial.print(pos);
    Serial.println("");


    for (byte i = 0; i < len_inStr - 2 ; i++) {
      if (buffers[pos - i - 1] != inStr[len_inStr - 3 - i])return false;

      //SИ - символ в буфере SS - символ в искомой строке
      Serial.print("SB №");
      Serial.print(pos - i - 1);
      Serial.print(" = ");
      Serial.print(buffers[pos - i - 1]);
      Serial.print(" --- ");

      Serial.print("SS №");
      Serial.print(len_inStr - 3 - i);
      Serial.print(" = ");
      Serial.print(inStr[len_inStr - 3 - i]);
      Serial.println("");

    }
    delay(3000);

  } else {
    return false;//Если пришедший байт не равен последнему символу искомой строки - выхожу
  }
  return true;//Если все символы искомой строки найдены в буфере
}



void loop() {
  static char text[] = "ATrnOKrn2AT";
  static uint8_t len_text = sizeof(text) / sizeof(text[0]);
  static uint32_t tmr;
  static uint8_t counter;

  if (millis() - tmr >= 200) {
    tmr = millis();
    if (counter >= len_text - 1)counter = 0;
    Serial.print(counter);
    Serial.print(".");
    Serial.print(text[counter]);
    Serial.println("");
    write_buffer(text[counter]);
    counter++;
  }

}

image

image

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

Два выхода: писать поверху или не сохранять принимаемые данные. Что важнее - каждый решает для себя сам .

Если позиция символа n = 0, проверяем последний символ буфера, потом предпоследний, то есть идём в обратную сторону, нет?
Или наверное не так, если позиция последнего символа меньше всей длины искомой строки, то проверяем в обратную сторону

в идеале наверное синхронно выбирать из буфера?

А если сразу же сверять каждый пришедший байт с искомой строкой?

Спойлер


void setup() {
  Serial.begin(9600);
}


bool write_buffer(uint8_t temp) {
  const char inStr[] = "+CCALR: 1";
  uint8_t len_inStr  = sizeof(inStr) / sizeof(inStr[0]);
  static uint8_t search_counter;

  if (temp) {

    if (temp == inStr[search_counter]) {
      search_counter++;

      if (search_counter == len_inStr - 1) {
        search_counter = 0;
        return true;
      } else {
        return false;
      }
    } else {
      search_counter = 0;
      return false;
    }//if (temp == inStr

  }//if (temp) {
}




void loop() {
  static char text[] = "12AT+CCALR: 2rnOKrnAT+CCALR: 1";
  static uint8_t len_text = sizeof(text) / sizeof(text[0]);
  static uint32_t tmr;
  static uint8_t counter;

  if (millis() - tmr >= 200) {
    tmr = millis();
    if (counter >= len_text - 1)counter = 0;
    Serial.print(counter);
    Serial.print(".");
    Serial.print(text[counter]);
    Serial.println("");

    if (write_buffer(text[counter])) {
      Serial.println("String_found");
    }
    counter++;
  }

}

А зачем в буфере отправляемая команда?

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

Эхо. Чтобы знать что ОК пришло именно на эту команду, при работе с поиском rn.

А теперь представьте лишнее усложнение логики, да и быстродействие МК не безграничное. Получив байт, найти в списке/массиве из десятка строк подходящее совпадение, за ним найти команду, по этой команде понять что произошло и это отработать :roll_eyes:
Это сейчас вы ищите OK\r\n , потом аппетиты возрастут.
Проще иметь например список enum текущей отправленной команды/режима и от него уже логику работы плясать, впрочем дело вкуса.
P.S. А вы заморочились кольцевым буфером из любопытства? или есть реальная сложная задача?

image
С этим пока не разобралась.

Спойлер

//Modem.h

//Modem.h
#pragma once
#include <Arduino.h>

class Modem {
  public:
    bool substring_search(char temp);
  private:
};

//Modem.cpp


//Modem.cpp
#include "Modem.h"

bool Modem::substring_search(char _temp) {
  const char _inStr[] = "+CCALR: 1";
  const uint8_t _len = 9;
  static uint8_t _search_counter;

  if (_temp == _inStr[_search_counter]) {
    _search_counter++;

    if (_search_counter == _len) {
      _search_counter = 0;
      return true;
    }

  } else {
    _search_counter = 0;

    if (_temp == _inStr[_search_counter]) {
      substring_search(_temp);
    }

  }

  return false;
}


Скетч

#include "Modem.h"
Modem sim800;

void setup() {
  Serial.begin(9600);
}


void loop() {
  static char text[] = "2rnATATE1OKrnAT++++++++CCALR: 1";
  static uint8_t len_text = sizeof(text) / sizeof(text[0]);
  static uint32_t tmr;
  static uint8_t counter;

  if (millis() - tmr >= 100) {
    tmr = millis();
    if (counter >= len_text - 1)counter = 0;
    Serial.print(counter);
    Serial.print(".");
    Serial.print(text[counter]);
    Serial.println("");
    if (sim800.substring_search(text[counter])) Serial.println("Network_found");
    counter++;
  }
}

У меня вот по такому коду есть вопросы.
К примеру я ищу строку ATE1
Если исходная строка равна 2rnATE1OKrnAT++++++++CCALR: 1 то всё работает
Если исходная строка равна 2rnATATE1OKrnAT++++++++CCALR: 1 то строка не ищется
Добавила обнуление счётчика и повторный вызов функции с тем же байтом

    if (_temp == _inStr[_search_counter]) {
      substring_search(_temp);
    }

Это верное решение?

И ещё вопрос,
Я хочу вызывать функцию с параметром для поиска
sim800.substring_search(text[counter], “OKrn”)

Соответственно, функция не работает
invalid types ‘char[int]’ for array subscript

bool Modem::substring_search(char _temp, char _inStr) {
  //const char _inStr[] = "+CCALR: 1";
  //const uint8_t _len = 9;
uint8_t _len = sizeof(_inStr) / sizeof(_inStr[0]);

  static uint8_t _search_counter;

  if (_temp == _inStr[_search_counter]) {
    _search_counter++;

    if (_search_counter == _len) {
      _search_counter = 0;
      return true;
    }

  } else {
    _search_counter = 0;

    if (_temp == _inStr[_search_counter]) {
      substring_search(_temp, _inStr);
    }

  }

  return false;
}

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