AT+QENG in BG96 does not reply me like manual example

Hi everyone,
please I really need help. I’ve used a BG96 module for making a prototype that it measure different network parameters like RRSI, RSRQ, ECL, and Cell ID. All of these parameters are catched well except one, the Cell ID. The reason is because when I send the command AT+QENG=“servingcell”, the module does not respond me with all the fields of the answer, only shows me until third parameter. This is the response I received:

+QENG: "servingcell","NOCONN","CAT-NB",

After the last coma, I cannot read more, doesn’t appear. The answer I should receive is like this:

+QENG: "servingcell","NOCONN","CAT-NB","FDD",460,11,DDA1451,280,2506,5,0,0,69C9,-84,-17,-67,8,44

I don’t understand why happen this.
For more realization, I publish all the code, it is programmed on the Arduino IDE because the module is controlled by one Arduino UNO. Thanks for all.

#include <SoftwareSerial.h>
//#include <ATcommands.h>
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <MemoryFree.h>
#include <string.h>

#define UART_RX 10 // Serial PIN RX connection
#define UART_TX 11 // Serial PIN TX connection
#define WIDTH_DISPLAY 128 // ancho pantalla OLED
#define HEIGTH_DISPLAY 32 // alto pantalla OLED

SoftwareSerial mySerial(UART_RX, UART_TX);
Adafruit_SSD1306 screen(WIDTH_DISPLAY, HEIGTH_DISPLAY, &Wire);

#define NWSCANSEQ   F("AT+QCFG=\"NWSCANSEQ\",03,1")
#define NWSCANMODE  F("AT+QCFG=\"NWSCANMODE\",3,1")
#define IOTOPMODE   F("AT+QCFG=\"IOTOPMODE\",1,1")
#define BAND        F("AT+QCFG=\"BAND\",0,0,A0E189F,1")
#define QICSGP      F("AT+QICSGP=1,1,\"m2m.movistar.es\"")

//Declare some variables they will be needed after
int *SignalLevels;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
  screen.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  screen.clearDisplay();
  screen.setTextColor(SSD1306_WHITE);
  
  Serial.println(F("Welcome to use NB-IoT Shield QG96"));
  getNetRegistration();
  //getGNSSRegistration();
}

void ATresponse(String AT, int wait){
  // The function extract the AT command response and specified 
  // a delay between different commands 
  mySerial.println(AT+"\r\n");
  delay(wait);
  updateSerial();
}

// void openCoAPclient(){
//   ATresponse("AT+QCOAPCFG=\"pdpcid\",0,1 ", 500); //Set the PDP context ID as 1 for CoAP client 0
//   ATresponse("AT+QCOAPCFG=\"trans\",0,2,3", 500); //Configure retransmission settings for CoAP client 0.The ACK timeout is 2 seconds and the maximum retransmission count is 3
//   ATresponse("AT+QCOAPOPEN=0,\"220.180.239.212\",8028", 500); //Create a CoAP session and connect to the CoAP server (IP Adress/Port)
//   ATresponse("AT+QCOAPHEADER=0,1234,1", 500); //Set to CoAP client 0 the CoAP message ID to 1234 and generate token automatically
//   ATresponse("", 500);
//   ATresponse("", 500);
// }

void getNetRegistration(){
  //The AT command's sequence for getting a CatNB1 network attachment
  screen.clearDisplay();
  screen.setTextSize(1,1);
  screen.setCursor(0, 0);
  screen.println(F("Getting connection"));
  screen.display();
  screen.setTextSize(1,1);
  screen.setCursor(0, 16);
  screen.println(F("please wait..."));
  screen.display();

  //ATresponse("AT&F", 1000);
  ATresponse(F("AT+IPR=9600;&W"), 1000);
  ATresponse(F("AT+CFUN=0"), 1000);  
  ATresponse(F("AT+CEREG=2"), 1000);
  ATresponse(BAND, 1000);
  ATresponse(F("AT+QCFG=\"nb1/bandprior\", 14"), 1000);
  ATresponse(NWSCANMODE, 1000);
  ATresponse(NWSCANSEQ, 1000);
  ATresponse(IOTOPMODE, 1000);
  ATresponse(QICSGP, 1000);  
  ATresponse(F("AT+CFUN=1"), 1000);
  delay(15000);
}

void updateSerial(){
  while (mySerial.available()) {
    Serial.write(mySerial.read()); //Forward what Serial received to Software Serial Port
  }
  while (Serial.available()) {
    mySerial.write(Serial.read()); //Forward what Serial received to Software Serial Port   
  }  
}

double *Split(String s, String delimiter){
  static double Split[13];
  int pos = 0;
  int i = 0;
  String token;
  while((pos = s.indexOf(delimiter)) != -1){
    token = s.substring(0, pos);
    Split[i] = token.toDouble();
    //Serial.println(Split[i]); // To ensure all values are correctly separated and stored
    s.remove(0, pos+delimiter.length());
    i++;
  }
  i++;
  token = s.substring(0);
  Split[i] = token.toDouble();
  //Serial.println(Split[i]); // To ensure all values are correctly separated and stored
  return(Split);
}

void loop() {   
  //Serial.println(Serial.read()+"\r\n"); delay(4000);
  //updateSerial();
  ATdisplay(F("AT+QCFG=\"celevel\""), 10000, "ECL");
  ATdisplay(F("AT+QNWINFO"), 10000, "NetInfo");
  ATresponse(F("AT+QCSCON=1"), 500);
  ATdisplay(F("AT+QENG=\"servingcell\""), 10000, "EngMode");
  ATresponse(F("AT+QCSCON=0"), 500);  
  ATdisplay(F("AT+QCSQ"), 10000, "LevelSignal");
  ATdisplay(F("AT+QGPSLOC=2"), 10000, "GPSInfo");      
}

void getGNSSRegistration(){
  //Initialize GNSS settings to obtain coordinates
  screen.clearDisplay();
  screen.setTextSize(1,1);
  screen.setCursor(0, 0);
  screen.println(F("Getting your locationcould spend more than 30s, please wait..."));
  screen.display();
  ATresponse(F("AT+QGPS=1,1"), 1000);
  ATresponse(F("AT+QGPSCFG=\"gnssconfig\",6"), 1000);     
  ATdisplay(F("AT+QGPSLOC=2"), 30000, "GPSInfo");
  // ATresponse("AT+QGPSEND", 1000); //More optimum not finishing everytime
}

void ATdisplay(String AT, int wait, const char* TypeOfMeasure){
  mySerial.println(AT+"\r\n");
  delay(wait);
  String values = "";
  while (mySerial.available()) {
    Serial.write(mySerial.read()); //Forward what Serial received to Software Serial Port
    //values = mySerial.readStringUntil("\n");
    values = mySerial.readString();
  }

  if(strcmp(TypeOfMeasure, "LevelSignal")==0){
    values = values.substring(26);
    //Serial.println(values);// Ensure which values are shown on the screen
    double *SignalLevels = Split(values, ",");
    screen.clearDisplay();
    screen.setTextSize(1,1);
    screen.setCursor(0, 0);
    screen.println("RSSI:"+String(SignalLevels[0], 0)+"  RSRP:"+String(SignalLevels[1], 0));
    screen.display();
    screen.setTextSize(1,1);
    screen.setCursor(0, 16);
    screen.println("SINR:"+String(SignalLevels[2], 0)+"  RSRQ:"+String(SignalLevels[4], 0));
    screen.display();

  }else if(strcmp(TypeOfMeasure, "ECL")==0){
    values = values.substring(26);
    screen.clearDisplay();
    screen.setTextSize(1,1);
    screen.setCursor(0, 0);
    screen.println("ECL:"+values.substring(10,11));
    screen.display();

  }else if(strcmp(TypeOfMeasure, "EngMode")==0){
    Serial.println(values);
    values = values.substring(35);
    //Serial.println(values);    
    screen.clearDisplay();
    screen.setTextSize(1,1);
    screen.setCursor(0, 0);
    screen.println("Cell ID:   "+values);
    screen.display();

  }else if(strcmp(TypeOfMeasure, "GPSInfo")==0){
    values = values.substring(30,52);
    //Serial.println(values); // Ensure which values are shown on the screen
    double *Coordinates = Split(values, ",");  
    int c = (int)Coordinates[1];
    switch(c){
      case NULL:
        screen.clearDisplay();
        screen.setTextSize(1,1);
        screen.setCursor(0, 0);
        screen.println(F("FAIL: Coordinates"));    
        screen.display();
        screen.setTextSize(1,1);
        screen.setCursor(0, 16);
        screen.println(F("do not fixed"));    
        screen.display();
        break;
        
      default:
        screen.clearDisplay();
        screen.setTextSize(1,1);
        screen.setCursor(0, 0);
        screen.println("Latitude:"+String(Coordinates[1], 5));    
        screen.display();
        screen.setTextSize(1,1);
        screen.setCursor(0, 16);
        screen.println("Longitude:"+String(Coordinates[2], 5));
        screen.display();
        break;
    }       
       
  }else if(strcmp(TypeOfMeasure, "NetInfo")==0){
    values = values.substring(22);
    screen.clearDisplay();
    screen.setTextSize(1,1);
    screen.setCursor(0, 0);
    screen.println(F("Type of Service:"));
    screen.display();

    if(values==NULL){
      screen.clearDisplay();
      screen.setTextSize(1,1);
      screen.setCursor(0, 16);
      screen.println(F("No Service Available"));
      screen.display();
      delay(3000);
      getNetRegistration();

    }else{
      screen.setTextSize(1,1);
      screen.setCursor(0, 16);
      screen.println(values);
      screen.display();
    }
  }
}

I think it is not necessary at all, but just in case.

Do you execute the AT command directly by the main serial port(TxD/RxD)? or by mcu?

AT+CFUN=0
AT+QCSCON=1
AT+CFUN=1
AT+QENG=“SERVINGCELL”
AT+COPS?
AT+QCFG=“IOTOPMODE”
AT+QCFG=“BAND”
AT+QCFG=“NWSCANMODE”
AT+QCFG=“NWSCANSEQ”

By mcu. I’ve used a similar sequence of AT commands at the beginning when I’m trying to attach the NB network, but the purpose is showing the Cell ID after showing RSSI, RSRQ parameters (these is when I use the comand AT+QCSQ).

@herbert.pan-Q Will I need change any command in the sequence I programmed ?

No, I suggest you disconnect the BG96 from the MCU and test it through the main serial port. I reasoned that it was probably due to insufficient cache space

1 Like

I tried to use an ESP32 (it has more RAM and cache than Arduino UNO), but it didn’t work because voltage of ESP32 GPIO output was different of my BG96 NB-IoT Shield.
How can I release more cache?

I created a code more simpler than the first and it works!

+QENG: "servingcell","NOCONN","CAT-NB","FDD",214,07,7059610,225,6354,20,0,0,B611,-110,-16,-94,8,10

I must change the mcu :sweat_smile:
Thank you @herbert.pan-Q , best regards