Увеличение буфера UART более 128 байт.

Volumetr
Offline
Зарегистрирован: 09.01.2012

Arduino UNO. Связь через UART (пинRX(0), пинTX(1)) с модемом Siemens MC35i.

Столкнулся с проблемой приёма данных по UART (RX, TX) больше чем размер буфера в 128 байт. Я думаю что упираюсь именно в ёмкость буфера, так как в стрковую переменную данные записываются не полностью. Во всей строчке около 70-75 букв, в я получаю что-то около 65 :(

Уже второй день бъюсь головой об стол - ничего не помогает. Ну не принимает зараза больше и всё!

Serial.println("AT+CMGL=?"); // Отправляем апрос модему

// Читаем ответ от модема

while (Serial.available() > 0) {
char inChar = Serial.read();
txtMsg += inChar;
}

// Обработка принятых данных, проверка, действие.

txtMsg = ""; // обнуляем строку
//в начало цикла loop

 Подскажите, как можно обойти это ограничение и принимать всё что нужно до конца?

step962
Offline
Зарегистрирован: 23.05.2011

 Есть подозрение, что проблема прямо противоположная - вы читаете быстрее, чем модем успевает присылать информацию. В какой-то момент условие Serial.available()>0 перестает выполняться, хотя модем готов слать еще и еще (программа выбрала/обработала последний успевший поступить в буфер символ, снова пришла на проверку условия и прочитала там 0 - очередной байт еще только поступает, принято, например, 6-7 битов, но не целый байт). 

Попробуйте либо в уже в имеющийся цикл впихнуть задержку в миллисекунду (на 9600 общаетесь?) или меньше (при более высокой скорости), либо сдублировать цикл (в смысле copy&paste) и вставить между первым и вторым циклами задержку в 10-20 мсек.

 

 

Volumetr
Offline
Зарегистрирован: 09.01.2012

Задержки ставил и по правде сказать мне это самое первое что пришло в голову, и скажу Вам не работает - и в цикл внутрь вставлял и снаружи и разные задержки от 50мсек и до 2 сек, но вот по поводу сдублировать цикл приёма это нужно попробовать, спасибо. Завтра с утра обязательно попробую и отпишусь.

whoim
Offline
Зарегистрирован: 03.11.2011

 Отпишитесь, ибо у меня та же проблема похоже

step962
Offline
Зарегистрирован: 23.05.2011

И дайте посмотреть, что отправляется и что принимается - т.е. хочется взглянуть что и где теряется.

Опять же - интересно узнать параметры связи, прежде всего скорость. Вы проверяли - с обоих сторон настройки одинаковые?

carduino.ru
Offline
Зарегистрирован: 06.12.2011

step962 прав, проблема в коде отправителя, я отправляю пакетом по 800 байт и никаких переполнений нет

Может я и не прав, у меня Carduino Nano Duo, у него USB мост на FTDI

whoim
Offline
Зарегистрирован: 03.11.2011

у меня тоже на ftdi. Код дома, вечером точно выложу. Но суть:

событие SerialEvent

цикл while serial.avariable

чтение в переменную byte

присвоение массиву глобальному

увеличение счетчиков для индексов массива (двухмерный)

если \n то флуш

если переполнение счетчиков то флуш

Надо отправлять 16*48 байт /8бит = 96 байт

доходит 10*48 / 8 = 60 байт, далее потеря serial.avariable видимо
попробую задержку..

 

whoim
Offline
Зарегистрирован: 03.11.2011

да, скорость пробовал 9600, 56700,115200

whoim
Offline
Зарегистрирован: 03.11.2011

 

//событие: данные в порт Serial
void serialEvent() {
  if(testmode) testmode = false; //сбросим тестовый режим если есть данные
  int x = 0; //переменные для
  int y = 0; //сопоставления с массивом данных
  while (Serial.available()) {
    byte _in = (byte)Serial.read();
    for (int j=0; j<8; j++) {
      data[x][y]= bitRead(_in, j); //формируем массив данных
      //Serial.println(data[x][y], DEC);
      y++;
      if(y == _COLUMNS) {
        y = 0;
        x++;
        if (x == _ROWS) {
          Serial.flush();
          Serial.println("overflow on ROWS (many bytes)");
        }
      } //if max columns
    } //bits cycle
   
  if (_in == '\n') {
    Serial.flush();
    Serial.println("cancel by end of data");
  }
  } //while serial active
  Serial.println("ok");
}

 

whoim
Offline
Зарегистрирован: 03.11.2011

Кстати, почему не работает 

  if (_in == '\n') {
23
    Serial.flush();
24
    Serial.println("cancel by end of data");
25
  }

никогда?

step962
Offline
Зарегистрирован: 23.05.2011

 А сивол новой строки точно передается? Может быть, только возврат каретки ('\r')? 

whoim
Offline
Зарегистрирован: 03.11.2011

 да черт его знает.. ))

http://my.jetscreenshot.com/1474/20120125-q5bs-116kb

carduino.ru
Offline
Зарегистрирован: 06.12.2011
whoim
Offline
Зарегистрирован: 03.11.2011

 спасибо, попробую

Volumetr
Offline
Зарегистрирован: 09.01.2012

Ребят, очень сорри что потерялся - работы просто вагон и маленькая тележка.

Под рукой проекта нет, он на работе остался - завтра думаю займусь в плотную, но пока объясню - да, пробовал разные скорости и пока остановился на 9600 для надёжности и USB мост на FTDI.

Отправляю в модем команду AT+CMGL=?

Ответ должен быть такой:

+CMGL : ("REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL")

OK

----------------------------------------------------------------------------------------------

Только вот приходит : +CMGL : ("REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL

Как видно в строчке теряются кавычки, скобка, возврат каретки, перенос строки и ОК.

String txtMsg = "";                             
String inputString = "";
boolean stringComplete = false;
void setup() {
  Serial.begin(9600);
}
void loop(){

  Serial.println("AT+CMGL=?");
  if (stringComplete) {
    Serial.print("2: " + inputString); 
    Serial.println();
    inputString = "";
    stringComplete = false;
  }
 delay(5000);
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    inputString += inChar;
     if (inChar == '\n') {
      stringComplete = true;
    } 
  }
}

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

step962
Offline
Зарегистрирован: 23.05.2011

 Скетч вот в таком виде:

String txtMsg = "";                             
String inputString = "";
boolean stringComplete = false;
void setup() {
  Serial.begin(9600);
}
void loop(){

  Serial.println("AT+CMGL=?");

// прием строки прямо в теле главного цикла  == НАЧАЛО
  while (Serial.available()) {
    char inChar = (char)Serial.read(); 
    inputString += inChar;
     if (inChar == '\n') {
      stringComplete = true;
    } 
  }
// прием строки прямо в теле главного цикла  == КОНЕЦ

if (stringComplete) { Serial.print("2: " + inputString); Serial.println(); inputString = ""; stringComplete = false; } delay(5000); }

 возвращает всю строку +CMGL : ("REC UNREAD", "REC READ", "STO UNSENT", "STO SENT", "ALL"). Чему я, собс-но, не удивляюсь, ибо всегда без проблем слушаю порт подобным образом. Установка delay(1) в цикле чтения не изменила поведения программы.

А в том виде, что у вас (с обработчиком serialEvent) вообще ничего не выдает (Arduino IDE ver 0022).

Строка подавалась через Serial monitor с установленным терминатором строки "new line" (выпадающий список внизу справа - левее списка выбора скорости передачи)

Volumetr
Offline
Зарегистрирован: 09.01.2012

Спасибо, завтра попробую и отпишусь по пунктам что куда отсылается и как принимается!

Volumetr
Offline
Зарегистрирован: 09.01.2012

Итак, отписываюсь - всё по прежнему! Строка принимается не полностью, но в ходе моих попыток, я заметил, что если подавать через сериал монитор по примеру step962, то всё принимается замечательно любой длинны, а вот с модема никак и меня осенило - когда модем даёт ответы, то сигнатура его обычно сводится к определённой очерёдности, а именно:

1. символ возврата каретки (ASCII 13, или '\r'), символ новой линии (ASCII 10, или '\n')

2. данные

3. символ возврата каретки (ASCII 13, или '\r'), символ новой линии (ASCII 10, или '\n')

4. OK

5. символ возврата каретки (ASCII 13, или '\r') и символ новой линии (ASCII 10, или '\n')

-----------------------------------

AT+CMGL=?

+CMGL: ("REC UNREAD","REC READ","STO UNSENT","STO SENT","ALL")

OK

_ <- Здесь мигает курсор

-----------------------------------

Я думаю, что из-за этого кода:

  if (inChar == '\n') {
      stringComplete = true;
    } 

выход из условия производится не корректно и нужно как-то ковырять строковую переменную  от модема игнорируя всё лишнее кроме последнего "ОК".

Может есть у кого какие мысли? Как быть?

whoim
Offline
Зарегистрирован: 03.11.2011

 Как быть? Ну вы все расписали)

Volumetr
Offline
Зарегистрирован: 09.01.2012

Это конечно, но как реализовать на практике, я не знаю.

Целый день пытался обработать строку с помощью .endsWith() и .indexOf(), но никак не получается....

Функция trim() почему-то не работает.

whoim
Offline
Зарегистрирован: 03.11.2011

 Я еще таким не занимался к сожалению, строки в МК вообще ненавижу...

alexxx86
Offline
Зарегистрирован: 15.01.2014

Всем добрый вечер!
Столкнулся с аналогичной проблемой не хватки размера буфера.
Не влазит часть строки от SIM900.
Возможно ли как то увеличить размер буфера?

ales2k
Offline
Зарегистрирован: 25.02.2013

HardwareSerial.cpp 

 #define SERIAL_BUFFER_SIZE

Но это изменит размер буфера для всех скетчей - можно помоему до килобайта

Александр597
Offline
Зарегистрирован: 30.01.2016

ales2k пишет:

HardwareSerial.cpp 

 #define SERIAL_BUFFER_SIZE

Но это изменит размер буфера для всех скетчей - можно помоему до килобайта

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

 
  #define SERIAL_BUFFER_SIZE 16
#else
  #define SERIAL_BUFFER_SIZE 64
 
LeXXkiev
Offline
Зарегистрирован: 20.03.2016

Вчера сам столкнулся с аналогичной проблемой при чтении USSD ответа от GSM модуля.

Этот код разбивает считываемую строку на несколько частей:

while (gsm.available()) {ch = gsm.read(); val += char(ch);}

А вот этот считывает полностью:

while (gsm.available()) {ch = gsm.read(); val += char(ch); delay(1);}

Тестовая строка - около 160 символов.

delay(1) замедляет чтение из буфера, предотвращая его опустошение. Справедливо для скорости 9600. Для более высоких надо задержку уменьшать чтоб не столкнуться с переполнением буфера длинной строкой.

 

Sts
Offline
Зарегистрирован: 22.06.2015

А если не думать и просто попробывать

 str = Serial.readString();

PS.

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

пока не кончится TimeOut  (Serial.setTimeout()...) но зато получаем целую строку,

со всякими chr(13), chr(10) внутри. А в ответе модемов и GSM, по моему, нет конца строки ...

wic
Offline
Зарегистрирован: 26.12.2016

Решили задачу?

Не могу вешить подубную, нужно считать с прибора 71 байт данных. Получается считать только 63.

Говорят можно в библиотеке поменять размер буфера, пока не получилось. Подскажите где именно.

Плата UNO R3

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

wic пишет:

Решили задачу?

Не могу вешить подубную, нужно считать с прибора 71 байт данных. Получается считать только 63.

Говорят можно в библиотеке поменять размер буфера, пока не получилось. Подскажите где именно.

Плата UNO R3

https://www.google.com/search?q=arduino+uard+buffer

wic
Offline
Зарегистрирован: 26.12.2016

Спасибо. Все получилось, УРА. Все заработало после установки новой версии IDE