Incomplete response from AT command

Hello,

I’m working on project using Uno Rev3 and gprs shield SIM900. I’m using AT+CENG to obtain cell towers information.

At first, I’ve modified the code from an example which require a letter input and the results were printed correctly.

However, I need the board to process automatically so I came up with the code below

#include <SoftwareSerial.h>

SoftwareSerial mySerial(7,8);                 // define serial connection

void setup() {
    mySerial.begin(19200);                     // GPRS shield baud rate
    Serial.begin(19200);
    delay(500);
    Serial.println("Getting information...");
    activate();                                       // open engineering mode
    delay(500);
}

void loop() {
    if (Serial.available() == 0) {              // check if there is no serial data
        getInfo();                                    // send AT command to get cell tower information
        delay(5000);
    }
    Serial.println();                            
}

/*
 * Get cellular information including MMc, MNC, LAC, and CID
 * Using AT command AT+CENG
 */

void activate() {
    mySerial.print("AT+CENG=3\r");         // activate engineering mode
    delay(100);
    while (mySerial.available()) {
        Serial.write(mySerial.read());
    }
}

void getInfo() {
    mySerial.print("AT+CENG?\r");           // reading information  
    delay(100); 
    while (mySerial.available()) {
        Serial.write(mySerial.read());
    }
}

After calling AT+CENG? I get the result like this.

AT+CENG?

+CENG: 3,0

+CENG:0,520,18,36bb,1ec7,73,46
+CENG:
+CENG:2,520,18,36bb,1ec6,64,22
+CENG:3,520,18,36bb,17cd,22,19
+CENG:4,520,18,36bb,17cb,61,15
+CENG:5,520,18,36bb,21a1,23,14
+CENG:6,520,18,36bb,1ec5,12,13

OK

The information for cell1 is missing. Can anybody help me what I did wrong?

Thanks.

You might be emptying your input buffer too fast in getInfo() so you exit that function call with the Serial buffer empty but by the time you arrive back to the loop more data came in and then the loop does not empty the buffer and you end up stuck in the if (Serial.available() == 0) { that never gets executed

your

    while (mySerial.available()) {
        Serial.write(mySerial.read());
    }

should not be in getInfo() but in the main loop()

Can anybody help me what am I missing?

For one thing, when you send data to the Arduino, via the serial port, you never read it. So, that data will always be available().

Second, you do NOT have a mySerial attached to pins 7 and 8, so what’s with the dumb name?

Third, you are missing some description of what the problem is.

You send a command to the “mySerial” (whatever the hell that is) and expect a response 1/10 of a second later. That may, or may not, be a realistic assumption. Then, you read all the data that has arrived, assuming that the data that has arrived constitutes a complete packet - another unrealistic assumption. Then, you return, ans do the same thing over again. You assume that there is a problem - based on no criteria, no evidence, and no explanation. Why?

PaulS: Second, you do NOT have a mySerial attached to pins 7 and 8, so what's with the dumb name?

Paul, I've seen you make that comment a few times in the forum.

I think there is some merit to calling this mySerial because what you instantiate is a Serial Object and not the representation of a high level abstraction class of the GSM object for example. This names implies that this is not the board's Serial object, but one tailored for you, with pins you selected. hence mySerial makes some sense.

A better name for me could be GSMSerial to denote it's a Serial object, connected to the GSM, but in reality whatever device attached on the other side is irrelevant and you have no high level method in that instance (abstracting the Serial connection) to talk to a specific device ---> so I would disagree (if this is what you have in mind making that comment, probably not) to call this just GSM.

At least personal view.

So, if you get an instance of the Dog class, you'll call it myDog. If you get another one, you'll call it myDog2?

SoftwareSerial GSM((7,8);                 // define serial connection

The fact that Serial does not appear in the name is, in my opinion, irrelevant.

   if(GSM.available() > 0)
   {
      char c = GSM.read();

is more than enough information for me to see that GSM is some kind of serial class object. It is more than enough to know that the device that it is connected to is a GSM.

It is then very difficult to forget the my prefix, and read from the wrong serial buffer or write to the wrong serial buffer.

YMMV.

I put the code in main loop() and the result is cut off from +CENG:

The part of that statement after the and is complete devoid of content.

You posted no code, and showed no output.

You have also failed to answer all the questions that have been asked.

PaulS: So, if you get an instance of the Dog class, you'll call it myDog. If you get another one, you'll call it myDog2?

no - I would call them pluto and scoobydoo and would not use the word Dog at all if I know which dog it is. if I don't and I've only one, it would be aDog and if I've many, it would probably be an array pack[] (or meute[] in french) and something else in context if I need a couple like madDog and rogueDog

I'm not arguing about the "my", I agree this part is weak. as I said, I would prefer GSMSerial because that's what is at the end of the 2 pins: the Serial hardware of the GSM shield, not the GSM components.

if GSM is just the SoftwareSerial instance name, then what does it [u]conceptually[/u] mean to do GSM.flush()? what does this represent - is it like waiting until an SMS is sent? What does GSM.print() or GSM.isListening() actually mean when you read the code? I think this is highly confusing.

I would understand thisif (GSM.available()) {...} as "is the GSM device live and working" i.e. does it answer OK to an AT command prompt and any other AT command that confirms it is connected to the cellular network. I would not understand that as is there data to be read and interpreted?

See my point? I think not remembering this is [u]just[/u] a Serial Instance and thus that you are "bare metal" is relevant to read and understand the code.

if I had a GSM class providing a higher level abstraction of the connexion to a GSM device, hiding the AT command language for me, offering resilience etc, such as I could check if something high level has arrived like as a new SMS, making a call, etc and hiding the Serial connection for me then I would call that GSM and anyone would understand the if (GSM.smsAvailable()) {...}kind of construct.

Anyway, at the end of the day this is (almost) a free world - so everyone can enjoy it the way he wants.

ino_beginner:
I put the code in main loop() and the result is cut off from +CENG:

what does this do for you? (set your PC console at 115200 bauds)

#include <SoftwareSerial.h>

const unsigned long Period = 5000ul; // every 5 seconds

SoftwareSerial GSMSerial(7, 8); // instantiate serial object, connecting the the GSM Serial hardware

void setup() {
  GSMSerial.begin(19200); // GPRS shield baud rate
  Serial.begin(115200);
  delay(500);
  Serial.println("Getting information...");
  GSMSerial.println("AT+CENG=3"); // activate engineering mode
}


void loop() {
  static unsigned long tempo = millis();

  while(GSMSerial.available()) Serial.write(GSMSerial.read());

  if (millis() - tempo > Period) {
    GSMSerial.println("AT+CENG?"); // reading information
    tempo += Period;
  }

}

What does GSM.print() or GSM.isListening() actually mean when you read the code? I think this is highly confusing.

On that, I think we'll just have to agree to disagree.

The device that you want to print to, or to listen from, is clearly, in my mind, defined. That a serial port is involved is not important, in my opinion.

When the instance name is mySerial, it is not at all obvious what device you are talking to.

I dislike the fact that there is an instance of the HardwareSerial class named Serial created for you. And, I dislike that there are Serial1, Serial2, and Serial3 instances for the Mega. If I use a Mega, with an XBee and a GPS connected to it, I'd prefer to use XBee.print() and GPS.available(), instead of Serial1.print() and Serial2.available(). It's too easy for fat-fingered people like me to hit 2, instead of 1, and spend time puzzling over why no GPS data is coming in.

I don't know what printing to a GPS would conceptually mean, but Ok fair enough. Agree it's better than mySerial :)

J-M-L: I don't know what printing to a GPS would conceptually mean, but Ok fair enough. Agree it's better than mySerial :)

Some GPSs, including the one I have, allow you to send them commands to control what NMEA sentences they return. So, writing to a GPS is not unreasonable. Although I never actually mentioned writing to a GPS...

Yes you did not - but the serial API does support it

Anyway I think we agree that better variable names makes sense, then personal preference on what that needs to be is acceptable