How to use TinyGPS++ or NeoGPS or NMEA library with A7 Module?

Hello guys :slight_smile:
I have seen many links that suggests to use library for NMEA data parsing, but I could not find any specific solution that could help me :frowning: , so I am posting here.

I am working with Ai-thinker A7 GSM+GPRS+GPS module with Arduino Uno. All my commands work fine and I also get the GPS data in NMEA format. I want to send the data in thingspeak cloud (only latitude and longitude).

[u]This[/u] is the module I am using. The module is powered by using external source and I have connected pins as below:

A7 PWR = A7 5V
A7 GND = Arduino GND
A7 UTXD = Arduino 8
A7 URXD = Arduino 9
#include <AltSoftSerial.h>
AltSoftSerial A7board;

int8_t answer;
String response;

void setup() {
  Serial.begin(19200);
  A7board.begin(19200);

  Serial.println("Start");

  A7board.println("AT");
  delay(2000);
  print_result();

  A7board.println("AT+CREG=0");
  delay(2000);
  print_result();
  
  A7board.println("AT+CIPMUX=0");
  delay(2000);
  print_result();
  
  A7board.println("AT+CGATT=1");
  delay(4000);
  print_result();
  
  A7board.println("AT+CSTT=""internet"",""0000"",""0000""");
  delay(2000);
  print_result();
  
  A7board.println("AT+CIICR");
  delay(5000);
  print_result();
  
  A7board.println("AT+CIFSR");
  delay(3000);
  print_result();

  A7board.println("AT+GPS=1");
  delay(2000);
  print_result();
}

void loop() {
  A7board.println("AT+GPSRD");
  delay(3000);
  print_result();

  A7board.println("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80");
  delay(5000);
  print_result();
  
  A7board.println("AT+CIPSEND=44");
  delay(3000);
  print_result();
 
  A7board.println("GET /update?api_key=***********&field1=*latitude*&field2=*longitude*");
  delay(5000);
  print_result();
}

void print_result() {
  while ( A7board.available() != 0)
    Serial.write( A7board.read());
  Serial.println();
}

All my commands work fine

So, what is the problem?

and I also get the GPS data in NMEA format.

You do NOT. You get some data that you do NOTHING with except print it out. For all you know, the data you got was a list of stock prices when the Bombay stock market closed.

You MUST know which AT command is asking for GPS data AND you must save the data for parsing later, or pass the GPS data to an instance of one of the GPS parsing classes.

Well, you haven’t told us anything else, so I’ll have to give you an incomplete answer to an unknown question. :-/

First, make sure you are using a HardwareSerial port, not AltSoftSerial. I think the A7 module only runs at 115200, so it will have to be connected to Serial pins 0 & 1:

#define A7board Serial   // baud is 115200, so you have to use Serial

This means you will have to disconnect pin 0 to upload a new sketch. If you are using wires to connect the A7 board to your UNO, put a switch in the wire from the A7 TX to the UNO RX pin 0.

You can try printing debug info to Serial. It will go to the Serial Monitor window and the A7board. This is probably ok, because all commands have to start with “AT”. The A7 should ignore your debug prints. Don’t echo the A7 response characters in print_result, because some of the response look like a new command.

If this doesn’t work (or you don’t like it), you can use AltSoftSerial to print debug information. Then you will need to connect a TTL Serial-to-USB adapter to pins 8 & 9, and the USB to your PC. Configure your Serial Monitor window to that COM port, and change your debug prints to use that variable. Perhaps:

AltSoftSerial debugPort; // pins 8 & 9

  ...

  A7board.begin( 115200 ); // this *is* Serial and the Serial Monitor window
  debugPort.begin( 9600 );

  debugPort.print( "Started." );

If you don’t have a Serial/USB adapater, you can use an extra Arduino with a simple echo sketch.

As far as parsing the NMEA data, just let NeoGPS read the A7board to get the NMEA characters for parsing. Check gps.available to know when a complete fix structure is ready. All GPS fields that were parsed will be available in that structure.

BUT: You should only do this when you know the A7 is in that “mode”. That would be after you send the “AT+GPSRD=1”. After you cancel the GPS mode with “AT+GPSRD=0”, you can send other AT commands and read the command responses.

A major problem is that you use delay. If you delay any longer than 64ms, you will lose GPS characters, and you will not get all (or any) complete NMEA sentences.

With NeoGPS, you would do something like this:

void setup() {
  Serial.begin(19200);
  A7board.begin(19200);

  Serial.println("Start");

  A7board.println("AT");
  delay(2000);

     ...

  //  Start the GPS "mode".  Raw NMEA characters will become available on the serial port A7Board.
  A7board.println("AT+GPS=1");

  gps_fix fix;
  int     fixCount;
  unsigned long startTime = millis();  // Take a timestamp

  //  Try to read NMEA data for up to 5 seconds or the 2nd fix.  NO DELAY!
  while ((millis() - startTime < 5000) && (fixCount < 2)) {

    //  Let NeoGPS read the characters and parse them into a fix structure.
    if (gps.available( A7board )) {

      //  Save the fix structure for later.
      fix = gps.read();
      fixCount++;
    }
  }
  Serial.print( fixCount );
  Serial.println( " fixes received" );

  //    cancel the GPS mode and start doing other A7 commands
  A7board.println("AT+GPS=0");

  //  The first fix might be partial, so make sure at least 2 were received.
  if (fixCount >= 2) {

    Serial.print( "location = " );
    if (fix.valid.location) {
      Serial.print  ( fix.latitude(), 6 );
      Serial.print  ( ',' );
      Serial.println( fix.latitude(), 6 );
    } else {
      Serial.println( '?' );
    }

    // Update thingspeak

    A7board.println("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80");
    delay(5000);
    print_result();

    A7board.println("AT+CIPSEND=44");
    delay(3000);
    print_result();
 
    A7board.print("GET /update?api_key=***********&field1=");
    if (fix.valid.location)
      A7board.print( fix.latitude(), 6 );
    A7board.print("&field2=");
    if (fix.valid.location)
      A7board.print( fix.longitude(), 6 );
    A7board.println();
    delay(5000);
    print_result();
  }
}

As I said before, using a delay of more than 64ms will truncate the response printed by print_result. Instead of delay, pass the timeout value into the print_result routine. Perhaps something like this:

void print_result( unsigned long waitMS )
{
  unsigned long startMS = millis();
  while (millis() - startMS < waitMS) {
    if ( A7board.available() ) {
      Serial.write( A7board.read() );
    }
  }
  Serial.println(); 
}

This routine would have to be different if you connect A7 TX to the UNO RX pin 0.

Also, Don’t Use String™.