Как прочитать ответ GSM AT команды на последовательный порт Arduino для длительного ответа? - PullRequest
1 голос
/ 08 апреля 2020

У меня есть Arduino UNO и модуль Sim800L, и я знаю способ чтения сериала, это что-то вроде этот вопрос , но когда я выполняю эту функцию:

    String GetRegData()
    {
      Serial.println("Get nearby antenna info ...");
      SIM800L.print("AT+CNETSCAN=1\r");
      delay(1000);

      SIM800L.print("AT+CNETSCAN\r"); 
      delay(1000);

      String buffer2;

      while (SIM800L.available())
       {
          char c = SIM800L.read();
          Serial.print(c);
          buffer2.concat(c);
          delay(10);
       }
       //Serial.println();
       return buffer2;
    }

Выходные данные:

AT+CMGF=1

OK
AT+CNMI=2,2,0,0,0

OK
AT+CNETSCAN=1

OK
AT+CNETSCAN

Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:q5er32xlAair32xlAacrseifcca,Nvdc00

Эта команда AT ( AT + CNETSCAN ) должна сканировать всю близлежащую антенну и печатать некоторую информацию в несколько строк (в соответствии с таблицей данных), когда я выполняю эту команду вручную на этих устройствах (SIM800L), я получаю несколько строк, таких:

Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:XX,Bsic:XX
OK

Но я не знаю, что происходит, когда я делаю это программно, Это испортилось, я пытался изменить скорость передачи и изменить метод получения и чтение символа по символу, и я сделал задержку между получениями, и я попытался сделать if или for вместо while, но не повезло.

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

Кстати, моя функция установки:

void setup() {
  SIM800L.begin(9600);
  Serial.begin(9600); 
  delay(3000);

  SIM800L.print("AT+CMGF=1\r"); 
  delay(100);

  SIM800L.print("AT+CNMI=2,2,0,0,0\r");
  delay(100);
  GetRegData();

  delay(1000);
}

Ps : Все это (Arduino + Sim800L) работает отлично без каких-либо ошибка и сим-карта разблокирована, и он может отправлять получать SMS и звонки, и т. д. c.

Ответы [ 3 ]

0 голосов
/ 09 апреля 2020

Потратив часы на обдумывание всего процесса, я пришел к мысли:

Будь на последовательном порту в течение 10 секунд и получи то, что когда-либо выплюнуло! НЕТ Последующий последовательный порт НЕТ while (SIM800L.available() != 0)

elapsedMillis - это библиотека, и это код:

String buffer2;

elapsedMillis timeElapsed;
unsigned int interval = 10000; 

while(timeElapsed < interval){
    if (SIM800L.available() != 0){ // for ignoring the NULLs
        char c = SIM800L.read();
        Serial.print(c);
        buffer2.concat(c);
      }
}

Хотя в этом есть некоторые основные моменты процесс:

1- Основная причина НЕ получить весь вывод старого l oop состоит в том, что SIM800L.available() стал нулевым при получении нескольких строк!

2- Тип данных String или SIM800L.read(); НЕ ДЕЛАЙТЕ ничего плохого, и они, теоретически, не имеют ограничений по чтению символов устройства вывода (например, 64 байта). Они читают все это

3 - Иногда электроны c устройства работают странно, особенный Sim800L, который является старым и дешевым!

4- Если вы хотите отправить эти данные (сканирование сетевой антенны) с помощью SMS, помните о максимальном количестве символов в SMS и учтите, что поставщики услуг будут взимать с вас плату примерно на каждые 150 символов, которые отправляют! и удалите \r\n символов из ответа и выполните AT+CSMP=17,167,0,0 перед отправкой SMS на SIM800L, в противном случае он отправит пустое SMS!

5- Sim800L В данных сказано, что он лучше всего работает на порту 115200 НО это слишком быстро для этого устройства! установите скорость передачи в 9600 .

0 голосов
/ 09 апреля 2020

Согласно ответу OP, проблема заключается в том, что serial.available() возвращает 0 и слишком рано завершает l oop.

Это, вероятно, происходит потому, что задержка между двумя последовательными вызовами serial.read() слишком мала и этого недостаточно для ожидания какого-либо побочного сценария ios, такого как ответ AT, представленный в нескольких строках.

Увеличение этой задержки было бы неправильным, поскольку ответ читается символ за символом, и это изменение будет влияет на общее время. Что можно сделать, это выйти из l oop после общей межсимвольной задержки . В следующем примере используется значение 200ms:

#define MAX_DELAY_MS  200
#define LOOP_DELAY_MS 10

String GetRegData()
{
  int intercharTime = 0;

  Serial.println("Get nearby antenna info ...");
  SIM800L.print("AT+CNETSCAN=1\r");
  delay(1000);

  SIM800L.print("AT+CNETSCAN\r"); 
  delay(1000);

  String buffer2;

  while (  intercharTime < MAX_DELAY_MS  )
   {
      if( SIM800L.available() )
      {
          int c = SIM800L.read();

          /* read() return -1 on fail. Make sure it read something before using c */
          if( c != -1 )
          {
              Serial.print( (char)c );
              buffer2.concat( (char)c );

              /* Something received: reset intercharTime */
              intercharTime = 0;
          }
      }
      else
      {
          intercharTime += LOOP_DELAY_MS;
      }

      delay(LOOP_DELAY_MS);
   }

   //Serial.println();
   return buffer2;
}

Изменения:

  • intercharTime проверяется для выхода из l oop. Значение увеличивается каждый раз, когда serial.available() возвращает 0. Сбрасывается при каждом получении символа. Таким образом мы выходим из l oop через MAX_DELAY_MS миллисекунд.
  • read() возвращает целое число, поэтому я поместил его в целочисленную переменную, приведя его к char всякий раз, когда потребуется. Кроме того, он возвращает -1 при неудаче. Всегда лучше проверять возвращаемые значения, прежде чем манипулировать данными, которые могут быть недействительными.
  • Я также заменил задержку 10ms на определение. Таким образом, вам будет легко играть с несколькими парами LOOP_DELAY_MS и MAX_DELAY_MS, чтобы найти лучшее соответствие.
0 голосов
/ 08 апреля 2020

Два совета:

  • Избавьтесь от ВСЕХ задержек () в вашей функции приема, она останавливает обработку на 10 миллис каждого символа, что может привести к переполнению последовательного буфера в долгосрочной перспективе
  • Избавьтесь от класса String, прочитайте в буфер символов, достаточно большой, чтобы принять наибольшее ожидаемое сообщение. Примеры можно найти здесь на stackexchange.

Функция serial.available () удобна, если вы используете двухстороннюю связь, но вам необходимо выполнить собственную проверку на наличие терминаторов конца или других внешних сигналов.

...