@WladDrakula посмотри пож мой пример. Ссылка выше. Можно его рекомендовать или мне лучше заткнуться?
подозреваю, что этот алгоритм Иринке будет еще сложнее, чем просто поиск в буфере с последнего символа. И да, беда в том, что искать приходиться разные значения в потоке, в зависимости от текущей логики.
Например ответ на подписанный топик MQTT совмещенный с командой исполнительному устройству.
ты словами напиши вкратце, ОК? Там же от маркера начала ищешь, если не путаю? а это вообще другая задача, в 100500 раз проще, чем просто вхождение подстроки где-то.
Меня совсем запутали, что такое хорошо и что такое плохо
Пока - что разбираюсь с кодом andycat, массив из 6 байт, работаемс)
Это будет понятно только в реальной работе
Я не видел что Иринке нужно найти именно начало подстроки. У меня подстрока ищется.
любопытная реализация
надо будет взять на вооружение/попробовать.
Добавить/создать список ответов, совместить его с режимом работы, добавить маленький буфер если необходимо получение произвольных данных (типа имя оператора) для парсинга и получится очень даже быстродействующая вещь.
???
-
Я отвечал Андриано. Что нужно ТС - мне безразлично. В дамском угодничестве на форуме - участие не принимаю.
-
Что касается твоего алгоритма, то мне читать код сейчас некогда. Хочешь ответ? - Я попросил объяснить словами. Не хочешь - твое дело.
-
Таки оторвали меня от работы. Радуйтесь! Можно было сказать, что нужно искать код функции isMarker(). Для гиперпростых маркеров - это ровно то, что я написал. Слово “гиперпросто” если никакое его конец не является началом. Сложный откат назад по образцу нужен для НЕ гиперпростых слов.
Вот
Спойлер
#define MAX_BUF 6
char buffers[MAX_BUF];
bool send_flag;
uint32_t tmr;
uint8_t pos;
void setup() {
Serial.begin(9600);
}
void modem_reading(char temp) {
if (pos >= MAX_BUF) pos = 0;
buffers[pos] = temp;
if (substring_search(temp)) {
send_flag = false;
Serial.println("OK_found");
delay(1000);
}
pos++;
}
bool substring_search(char temp) {
const char string[] = "OKrn";
uint8_t len_string = strlen(string);//4
if (temp == string[len_string - 1]) {
for (uint8_t i = 0; i < len_string - 1 ; i++) {
if (buffers[pos - i - 1] != string[len_string - i - 2])return false;
}
} else {
return false;
}
return true;
}
void loop() {
//Отправляю АТ, получаю в ответ ОКrn
static char text[] = "OKrn";
if (!send_flag && millis() - tmr >= 1000) {
send_flag = true;
for (uint8_t i = 0; i < 4; i++) {
modem_reading(text[i]);
delay(200);
}
}
//Отправляю АТ, получаю в ответ ОКrn
}
Код с выводом сообщений
Спойлер
#define MAX_BUF 6
char buffers[MAX_BUF];
bool send_flag;
uint32_t tmr;
uint8_t pos;
void setup() {
Serial.begin(9600);
}
void modem_reading(char temp) {
if (pos >= MAX_BUF) pos = 0;
buffers[pos] = temp;
if (substring_search(temp)) {
send_flag = false;
Serial.println("OK_found");
delay(1000);
}
pos++;
}
bool substring_search(char temp) {
const char string[] = "OKrn";
uint8_t len_string = strlen(string);//4
if (temp == string[len_string - 1]) {
//Последний символ искомой строки = n
Serial.print("Last_char = ");
Serial.print(string[len_string - 1]);
Serial.println("");
//Позиция искомого символа в основном буфере = 6
Serial.print("Pos_last_char_buf = ");
Serial.print(pos);
Serial.println("");
for (uint8_t i = 0; i < len_string - 1 ; i++) {
if (buffers[pos - i - 1] != string[len_string - i - 2])return false;
//SB - символ в буфере 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_string - i - 2);
Serial.print(" = ");
Serial.print(string[len_string - i - 2]);
Serial.println("");
}
} else {
//Если пришедший символ НЕ равен последнему символу искомой строки
return false;
}
return true;
}
void loop() {
//Отправляю АТ, получаю в ответ ОКrn
static char text[] = "OKrn";
if (!send_flag && millis() - tmr >= 1000) {
send_flag = true;
for (uint8_t i = 0; i < 4; i++) {
modem_reading(text[i]);
delay(200);
}
}
//Отправляю АТ, получаю в ответ ОКrn
}
Соответственно первый раз срабатывает, второй раз нет
ужас
никаких delay
где весь код с serial.available() serial.read()? Модема
Модема нет сейчас под рукой.
Моделирую в протеус.
Паузы для меня только, смотрю код.
Как тут рядом в ветке ЕвгенийП правильно сказал: нет того лампового наслаждения прочуствовать работу в железе, как дымок из МК идет и т.д…
Тем более без модема.
я не знаю как объяснить мою мысль
Ира! Я наступаю на горло своей мизогинии…
в строке 44 по второму коду нужно вот так:
if (buffers[(MAX_BUF + pos - i - 1) % MAX_BUF] != string[len_string - i - 2])return false;
Это же КОЛЬЦЕВОЙ буфер! Значит нужно в кольце вычетов работать.
Поэтому выбирают степени 2 как размер, тогда вместо остатка можно просто битовое “и” использовать.
Например для буфера длиной 8 будет так:
if (buffers[(8 + pos - i - 1) & 0b111] != string[len_string - i - 2])return false;
Вот такой смысл?
Спойлер
bool substring_search(char temp) {
const char string[] = “OKrn”;
uint8_t len_string = strlen(string);//4
if (temp == string[len_string - 1]) {
//Последний символ искомой строки = n
Serial.print("Last_char = ");
Serial.print(string[len_string - 1]);
Serial.println("");
//Позиция искомого символа в основном буфере = 6
Serial.print("Pos_last_char_buf = ");
Serial.print(pos);
Serial.println("");
if (pos < len_string - 1) {
for (uint8_t i = 0; i < len_string - 1 ; i++) {
int8_t new_pos = pos - i - 1;
if (new_pos < 0) new_pos = MAX_BUF - i;
if (buffers[new_pos] != string[len_string - i - 2])return false;
}
} else {
for (uint8_t i = 0; i < len_string - 1 ; i++) {
if (buffers[pos - i - 1] != string[len_string - i - 2])return false;
}
}
} else {
return false;
}
return true;
}
теперь больше времени на малыша останется )))
не проверял, стенд занят, минимальный пример:
Спойлер
#include <SoftwareSerial.h>
#define GSM_RX (byte)3 // пин RX на модуле подключаем к указаному пину на Ардуино TX
#define GSM_TX (byte)2 // пин TX на модуле подключаем к указаному пину на Ардуино RX
SoftwareSerial gsm(GSM_TX, GSM_RX); // установка контактовGSM_TX->RX и GSM_RX->TX для программного порта
#define max_size_response_buf (byte)6 // размер буфера ответа от модема, должен быть чуть больше максимальной строки поиска, например SEND OK, ERROR, OK и т.д. для стандартных команд
char resp_buf[max_size_response_buf]; // буфер ответов от модема
byte pos_buf; // текущая позиция буфера ответов
void clearRespBuf() { // очистка приемного буфера
memset(resp_buf, 0, max_size_response_buf);
pos_buf = 0;
}
bool findOKfromBuf(const unsigned char inByte) { // поиск OK\r\n в циклическом буфере
const char inStr[] = "OK\r\n"; // искомая строка
byte slen = 4; // длина искомой строки
if (inByte == inStr[slen - 1]) { // если последний символ совпадает - продолжаем искать всю строку
byte abpos = pos_buf; // абсолютная позиция в буфере поиска-1 = последнему символу искомой строки
if (!abpos) abpos = max_size_response_buf - 1; else --abpos; // ищем с предпоследнего символа
for ( byte i = 0; i < (slen - 1); ++i) { // цикл по оставшимся символам
if (inStr[slen - 1 - i] != resp_buf[abpos]) return false; // если не сопадабт символы - выходим
if (!abpos) abpos = max_size_response_buf - 1; else --abpos; // уменьшаем счетчики
}
} else {
return false;
} return true;
}
void setup() {
Serial.begin(115200);
gsm.begin(9600);
// put your setup code here, to run once:
clearRespBuf();
gsm.print("AT\r");
}
bool waitOKrnFromModem() {
byte br = 0;
if (gsm.available()) br = gsm.read();
if (br) {
// запись байта в буфер
resp_buf[pos_buf] = br; // записали
++pos_buf; // увеличили счетчик
if (pos_buf >= max_size_response_buf) pos_buf = 0; // если дошло до максимума - обнуляем
Serial.write(br);
return findOKfromBuf(br);
}
return false;
}
void loop() {
// put your main code here, to run repeatedly:
if (waitOKrnFromModem()) {
delay(1000); // пауза для наблюдения результата
gsm.print("AT\r");
}
}
/*Скетч использует 3436 байт (11%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 318 байт (15%) динамической памяти, оставляя 1730 байт для локальных переменных. Максимум: 2048 байт.*/
Оххх, Вы, наверняка в силу возраста, не можете помнить драму Трофимова “Всё как у людей”, почитайте
Сие мне неведомо.
(Сцена из КФ Монах и бес, где их полицмейстер поймал и повёл к старшему, сказать что они почту ограбили)
Я бы рекомендовал задавать размер кольцевого буфера кратным 2 (2,4,8,16,32,64,128 или 256 байт)
#define UART_RX_BUFFER_SIZE 64 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#define UART_TX_BUFFER_SIZE 64 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif
static unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char Tx_Active_Flag;
Тогда проще с ним работать используя маску.
unsigned char DataInReceiveBuffer( void )
{
return ( UART_RxHead != UART_RxTail );
/* return 0 (FALSE) if the receive buffer is empty */
}
/* Read and write functions */
unsigned char ReceiveByte( void )
{
unsigned char tmptail;
unsigned char data;
if (DataInReceiveBuffer())
{
tmptail = ( UART_RxTail + 1 ) & UART_RX_BUFFER_MASK;/* calculate buffer index */
UART_RxTail = tmptail; /* store new index */
data = UART_RxBuf[tmptail];
return data; /* return data */
}
return 0;
}