1
votes

I have Arduino UNO and a Sim800L module and I know the way to read the serial, it is something like this question, but when I perform this function :

    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;
    }

The output is :

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

This AT command (AT+CNETSCAN) should scan all nearby antenna and print some information in multiple lines(according to datasheet), when I execute this command manually on this devices(SIM800L) ,I get multiple line such :

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

But I don't know what happen when I do it programmatically, It is messed up, I tried to change baud rate and change receiving method and read char by char and I did put delaying between receives and I tried to do if or for instead of while but no luck.

I guess there is a delay between receiving each line and it breaks the serial availability but I don't know what to do ! any help would be appreciated.

By the way, my setup function:

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: The whole thing(Arduino+Sim800L) works perfectly fine with no error and the Simcard is unlocked and it can send an receive SMS and Calls ,etc.

3
So you are complaining about the response that seems corrupted in the "LAC" field of the first line?Roberto Caboni
@RobertoCaboni Yes, it seems, something bad happens near LAC field and the rest of the lines ,are not printing or saving in the variable.malloc
Does the 'X' in Operator:"XXXX",MCC:XXX,MNC:XX,Rxlev:XX,Cellid:XX,Arfcn:XX,Lac:... substitute 1vs1 the actual chars? What is the first unexpected character in the response? Is that message printed by the Serial.print(c); or by another external call printing buffer2?Roberto Caboni
What I noticed is that the output is strange after about 64 characters. PS:serial.read() returns an int type variable (and -1 on error, so you shoud check its return value)Roberto Caboni
@RobertoCaboni the output is like ::Operator:"405803",MCC:405,MNC:803,Rxlev:62,Cellid:51A5,Arfcn:702 and serial print nothing.malloc

3 Answers

0
votes

Two tips:

  • Get rid of the ALL delay()s in your receive function it stops processing for 10 millis each character which might sum up to a serial buffer overflow on the long run
  • Get rid of String class, read into a char buffer large enough to take the largest expected message. Examples may be found here on stackexchange.

The serial.available() is handy if you do two way com, but you need to do your own checking for end terminators or other external signals.

0
votes

By spending hours of thinking the whole process through, I came up with an idea:

Be at Serial port for 10 second and get what ever it spit out! NO Serial port breaking out NO while (SIM800L.available() != 0)

The elapsedMillis is the library and this is the code:

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);
      }
}

Although there are some highlights in this process :

1- The main reason for NOT getting the whole output by the old loop is , the SIM800L.available() became Zero during multiple line receiving!

2- The String data type or SIM800L.read(); Do NOT do anything wrong and they, theoretically have no limitation of reading device output(Like 64 byte ) characters , They read it all

3- Some times electronic devices act strangely special Sim800L which is old and cheap!

4- If you will to send this data(Network Antenna Scan) via SMS, be aware of SMS max character limit and consider that Service Providers will charge you for about every 150 char that send! and remove \r\n chars from response, and run AT+CSMP=17,167,0,0 before sending SMS on SIM800L otherwise it will send a blank SMS!

5- Sim800L Datasheet said it work best on port 115200 BUT it is too fast for this device! set its baud rate on 9600.

0
votes

According to OP's answer, the problem resides on serial.available() returning 0 and making the loop end too early.

That probably happens because the delay between two consecutive serial.read() calls is too low, and it is not enough to wait for some side scenarios such as an AT response presented in more lines.

Increasing that delay would be wrong, because response is read character by character, and that change would affect the total time. What can be done is exiting the loop after a total inter-character delay . It the following example the value of 200ms is used:

#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;
}

Changes:

  • intercharTime is checked to exit the loop. It is increased each time serial.available() returned 0. Resetted each time a character is received. In this way we exit the loop after MAX_DELAY_MS milliseconds.
  • read() returns an integer, so I placed it on an integer variable, casting it to char whenever required. Furthermore it returns -1 on failure. It is always better to check return values before manipulating data that might be invalid.
  • I also substituted 10ms delay with a define. In this way it will be easy to play with several couples of LOOP_DELAY_MS and MAX_DELAY_MS in order to find the best fit.