именно
Можно конечно реализовать полноценный FIFO буфер, искать строку с начальной позиции данных (размер) до конечной, но для вашей задачи и этого достаточно.
именно
Можно конечно реализовать полноценный FIFO буфер, искать строку с начальной позиции данных (размер) до конечной, но для вашей задачи и этого достаточно.
так так так, кодом не делитесь, дама сама сейчас будет думать XDDDD
Скоро скину код)
начните с попроще, выкиньте весь код работы с SIM800L, сделайте отправку команды АТ\r подряд пару тройку раз, буфер размером максимум 6 байт (для чистоты эксперимента, чтоб только OK\r\n влазило), и после каждой отправки ищите ответ.
Ну а потом уже по накатанной все легко пойдет, будет уже неважно сколько команд и какие ответы ожидаете, можно будет анализировать все (в пределах мощности МК конечно).
дык выше все есть, и велосипед не надо изобретать.
Не нужно это.
Если голова равна хвосту, значит, буфер пуст.
Где написано? В Википедии))))
Откуда вы можете знать где там у меня на ноль проверяется что либо?
И вообще логику программы? Или вы пару тыщь строк разобрали по кусочкам за вечер)))
Что у тебя лично проверяется, не имею ни малейшего понятия.
Я лишь утверждаю, что для кольцевого буфера это не нужно. От слова совсем.
Да, только фраза про очистку буфера была конкретно про логику работы с модемом, а там не полноценный 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++;
}
}
Два выхода: писать поверху или не сохранять принимаемые данные. Что важнее - каждый решает для себя сам .
Если позиция символа 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.
А теперь представьте лишнее усложнение логики, да и быстродействие МК не безграничное. Получив байт, найти в списке/массиве из десятка строк подходящее совпадение, за ним найти команду, по этой команде понять что произошло и это отработать
Это сейчас вы ищите OK\r\n , потом аппетиты возрастут.
Проще иметь например список enum текущей отправленной команды/режима и от него уже логику работы плясать, впрочем дело вкуса.
P.S. А вы заморочились кольцевым буфером из любопытства? или есть реальная сложная задача?
//Modem.h
#pragma once
#include <Arduino.h>
class Modem {
public:
bool substring_search(char temp);
private:
};
//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;
}
Как вы говорите это правильное решение моей задачи, и работает быстрее чем поиск конца строки, и еще несколько участников говорит что кольцевой буфер круто, из любопытства.