Go Down

Topic: GPS vs Ai Thinker A7 module (Read 16286 times) previous topic - next topic

PieterE

Hello Arduino-fans!

I bought the A7 Ai Thinker module for handling GPS and GPRS. I spend hours on figuring out how to get the GPS working, without any result.  :(

The A7 module, which I use, can send SMS messages, make phone calls and can connect through TCP/IP. The module seems to work properly.

Is someone familiar with the A7 module and can help me out how to connect the A7 module to an Arduino (UNO)? Can you also please help me out on some basic code, so I can get GPS data?

Thank you in advance for your help!

With kind regards,

Pieter E.

PaulS

Quote
The module seems to work properly.
But you don't know how to connect it to the Arduino? By what measure is it working properly, then?

Why would you buy a board from a retailer that provides NO useful information about the product?
The art of getting good answers lies in asking good questions.

PieterE

But you don't know how to connect it to the Arduino? By what measure is it working properly, then?
Like I said, "The A7 module, which I use, can send SMS messages, make phone calls and can connect through TCP/IP." Sending SMS messages, making phone calls and connect through TCP/IP is done by using an Arduino UNO. Coding the module works as expected. The only part I cannot figure out is how to use the GPS part.

Why would you buy a board from a retailer that provides NO useful information about the product?
I'm not sure what you are trying to say. Do you have a better alternative? A lot of sensors and modules aren't (well) documented. Which sensors and modules do you use?


PaulS

Quote
Which sensors and modules do you use?
Those for which I can get at least a moderate amount of documentation for.

Perhaps you should try to find the manufacturer's site, not a useless reseller site.
The art of getting good answers lies in asking good questions.

PieterE

Thank you for your response. I'll contact Ai Thinker for more detailed information.

Still I don't have an answer to my question. ;)

Is there someone who also uses the A7 module?

-dev

After a quick look, I see that you can turn the GPS device on with "AT+GPS=1".  After that, the A7 starts sending NMEA data on the AT command port.  You should give that data to a GPS parser, like my NeoGPS library:

Code: [Select]
#include <NMEAGPS.h>

// Best would be to connect to the Serial pins 0 & 1
#define A7 Serial
//AltSoftSerial A7; Next best, but you must use pins 8 & 9!  This is very efficient.
//NeoSWSerial A7( 4, 5 ); 2nd best on whatever two pins you want.  Almost as efficient.
//  do not use SoftwareSerial!

NMEAGPS gps;
gps_fix   fix;

enum state_t { WAITING, READING_GPS, GPS_OFF_WAIT, ... {;
state_t state = WAITING;
uint32_t stateTime;

   ...

void setup()
{
  A7.begin( 9600 );
}

void loop()
{
  switch (state) {
    case WAITING:
      if (time to check location) {
        // Turn GPS data on
        A7.println( F("AT+GPS=1") );
        state = READING_GPS;
      }
      break;

    case READING_GPS:
      while (gps.available( A7 )) { // parse the NMEA data
        fix = gps.read(); // this structure now contains all the GPS fields

        if (fix.valid.location) {
          // Now that we have a fix, turn GPS mode off
          A7.println(  F("AT+GPS=0") );
          stateTime = millis();
          state = GPS_OFF_WAIT;
        }
      }
      break;

    case GPS_OFF_WAIT:
      serialEmpty();

      // Wait for the GPS data to stop
      if (millis() - stateTime >= 1000) {

        // Stopped, now send SMS with location values:
          ... set up the SMS ...
        A7.print( F("lat=") );
        A7.print( fix.latitude(), 6 ); // use the latitude field of the fix structure
          ...
        stateTime = millis();
        state = SENDING_SMS; // WAITING?
      }
      break;

    ... other states ...
  }
}

Cheers,
/dev

PaulS

Quote
After a quick look
Where? That information might be useful to OP.
The art of getting good answers lies in asking good questions.

PieterE

The A7 datasheet can be found here: PDF document A6/A7/A6C

The Elecrow shield contains an A7 module: Wiki page about A7 GPRS+GSM+GPS


mistery

I have A7 module, and it is working, but it gives me wrong GPS data so I needed to use offset to get it on track.
for init you need to
power module up
Print AT wait some time for OK response
wait for 10 sec while reading serial to check if it is all ok
If all ok
send "AT+GPS=1" to module

and then data on GPS TX will start showing up

PieterE

Thank you for your answer. I'm glad to find someone who uses this module. :)

I tried writing some code to read the GPS data. Still there is no data. Can you please inform me what to do?

My wiring:
A7 GRN => ARDUINO GRN
A7 UTXD => ARDUINO RX
A7 URXD => ARDUINO TX
A7 GPS => ??
UNO 5V => ARDUINO PWR
The arduino and A7 module are power by USB.

My code:
Code: [Select]
#include <SoftwareSerial.h>

byte RX = 10; // This is your RX-Pin on Arduino UNO
byte TX = 11; // This is your TX-Pin on Arduino UNO
SoftwareSerial *A7board = new SoftwareSerial(RX, TX);

void print_result()
{
  Serial.print("A7 board info: ");
  while( A7board->available() != 0)
    Serial.write( A7board->read());
  Serial.println();  
}
//--------------------------------------------------------------------

void setup() {
  Serial.begin(115200);
  A7board->begin(115200);
  delay(200);

  Serial.println("Send AT command");  
  A7board->println("AT");
  delay(15000);
  print_result();
  
  Serial.println("AT+GPS turn on");  
  A7board->println("AT+GPS=1");  
  delay(5000);
  print_result();
}
//--------------------------------------------------------------------

void loop() {
  print_result();
  delay(2000);
}
//--------------------------------------------------------------------


Thank you in advance for your help! :)

-dev

#10
Jan 12, 2017, 12:29 am Last Edit: Jan 12, 2017, 12:30 am by /dev
Quote
My code:

#include <SoftwareSerial.h>
Don't use SoftwareSerial unless you can't use pins 8 & 9 (with AltSoftSerial) and the baud rate is not 9600, 19200 or 38400 (with NeoSWSerial).

Quote
My wiring:
A7 GRN => ARDUINO GRN
A7 UTXD => ARDUINO RX
A7 URXD => ARDUINO TX
A7 GPS => ??
UNO 5V => ARDUINO PWR
"ARDUINO RX" is pin 10, right?
"ARDUINO TX" is pin 11, right?

According to your code,

    byte RX = 10; // This is your RX-Pin on Arduino UNO
    byte TX = 11; // This is your TX-Pin on Arduino UNO

... it must be connected to those pin numbers.

And you don't need to use "new":

    SoftwareSerial *A7board = new SoftwareSerial(RX, TX);

Just declare it like this:

    NeoSWSerial A7board( RX, TX );

Then you will use a "." instead of "->"

    void setup() {
      Serial.begin(115200);
      A7board.begin(9600);  // The spec says the default rate is 9600.

Also, I looked at the spec again, and there is a GPS example at the very end.  It shows that you need to send another command, AT+GPSRD=1.

Here is a NeoGPS/NeoSWSerial version that gets a GPS location about once every 10 seconds:

Code: [Select]
#include <NMEAGPS.h>

//#define A7board Serial  // Best would be to connect to the Serial pins 0 & 1
//      or
//#include <AltSoftSerial.h>
//AltSoftSerial A7board; Next best, but you must use pins 8 & 9!  This is very efficient.
//      or
#include <NeoSWSerial.h>
NeoSWSerial A7board( 10, 11 ); // 2nd best on whatever two pins you want.  Almost as efficient.
// DO NOT USE SoftwareSerial!

NMEAGPS gps;
gps_fix fix;

enum state_t { WAITING, READING_GPS, GPS_ON_WAIT, GPS_READING, GPS_READING_WAIT, GPS_OFF_WAIT, SENDING_SMS }; // other states?
state_t state = WAITING;
uint32_t stateTime;
const uint32_t CHECK_LOCATION_TIME = 5000; // ms

void echoA7chars()
{
  while (A7board.available())
    Serial.write( A7board.read() ); // just echo what we are receiving
}

void ignoreA7chars()
{
  while (A7board.available())
    A7board.read(); // ignore what we are receiving
}

void setup()
{
  Serial.begin( 115200 );
  A7board.begin( 9600 );
}

void loop()
{
  switch (state) {

    case WAITING:
      echoA7chars();

      if (millis() - stateTime >= CHECK_LOCATION_TIME) {

        // Turn GPS data on
        A7board.println( F("AT+GPS=1") );

        stateTime = millis();
        state     = GPS_ON_WAIT;
      }
      break;

    case GPS_ON_WAIT:
      echoA7chars();

      // Wait for the GPS to turn on and acquire a fix
      if (millis() - stateTime >= 5000) { // 5 seconds

        //  Request GPS data
        A7board.println( F("AT+GPSRD=1") );
        Serial.print( F("Waiting for GPS fix...") );

        stateTime = millis();
        state     = GPS_READING;
      }
      break;

    case GPS_READING:
      while (gps.available( A7board )) { // parse the NMEA data
        fix = gps.read(); // this structure now contains all the GPS fields

        if (fix.valid.location) {
          Serial.println();

          // Now that we have a fix, turn GPS mode off
          A7board.println(  F("AT+GPSRD=0") );

          stateTime = millis();
          state     = GPS_READING_WAIT;
        }
      }

      if (millis() - stateTime > 1000) {
        Serial.print( '.' ); // if still waiting for fix, print a dot.
        stateTime = millis();
      }
      break;

    case GPS_READING_WAIT:
      ignoreA7chars();

      // Wait for the GPS data to stop
      if (millis() - stateTime >= 1000) {

        // Turn GPS power off
        A7board.println(  F("AT+GPS=0") );

        stateTime = millis();
        state     = GPS_OFF_WAIT;
      }
      break;


    case GPS_OFF_WAIT:
      echoA7chars();

      // Wait for the GPS to power off
      if (millis() - stateTime >= 1000) {

        // Show the location we will send via SMS
        Serial.print( F("loc: ") );
        Serial.print( fix.latitude(), 6 ); // use the latitude field of the fix structure
        Serial.print( F(", ") );
        Serial.println( fix.longitude(), 6 ); // use the longitude field of the fix structure

        // Send SMS with location values ?
        //A7board.print( SMS commands? );
        //A7board.print( F("lat=") );
        //A7board.print( fix.latitude(), 6 ); // use the latitude field of the fix structure
        //  ...

        stateTime = millis();
        state     = SENDING_SMS;
      }
      break;
      
    case SENDING_SMS:
      echoA7chars();

      if (millis() - stateTime >= 2000) {
        stateTime = millis();
        state     = WAITING; // start over
      }
      break;

    //  ... other states ...
  }
}

It just "pretends" to send an SMS, because you haven't said what you're going to do with the location after you get it.

Notice how this sketch never uses delay.  It uses a "state" variable to wait for some time to go by, and then do something.  When it is in the GPS_READING state, it always reads the GPS characters.  When it finally gets a location from the GPS characters, it goes into the SENDING_SMS state (or whatever you need to do).

You can get NeoSWSerial here, and you can get NeoGPS from the link above (reply #5), or from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.

Cheers,
/dev

omkar_guhilot

Are you able to setup the A7 Module with Arduino Uno or Nano, i tried setting it with both but i am unable to get it working. I am not getting the GPS co-ordinates nor am i able to send SMS. i tried the above code for fetching GPS values but even that is not working.

I have connected the arduino uno pin 12 and pin 13 to A7 UART_TXD and UART_RXD respectively. And connected the GND of arduino uno to A7 and VCC of arduino uno to A7 module.

Here is the code i tried for sending SMS

Code: [Select]

#include <String.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12, 13);

void setup()
{
  mySerial.begin(115200);               // the GPRS baud rate   
  delay(500);
}
 
void loop()
{

 SendTextMessage();
 delay(10000);

}
 

void SendTextMessage()
{
   mySerial.print("AT+CMGF=1\r");    //Because we want to send the SMS in text mode
  delay(100);
   mySerial.println("AT+CMGS=\"+(YOUR_NUMBER_WITH_COUNTY_CODE)\"");
  delay(100);
   mySerial.println("GSM test message! Omkar");//the content of the message
  delay(100);
   mySerial.println((char)26);//the ASCII code of the ctrl+z is 26
  delay(100);
   mySerial.println();
}


Thanks.

sliekas_satanistas

hello, guys,

I would like to share my own experience with A7 (GPRS and GPS) and Arduino Nano. All this weekend I spend to understand and manage A7 board. So, maybe for someone, will be useful this post…
The main task, what I was trying to do, to make "application" which will periodicaly upload GPS (NMEA) data to the web.

My setup:
• Ai Thinker A7 (for GPS I bought another antenna, because antenna shipped with board is not compatible for GPS signal).
• Arduino Nano
• Level shifter (It is needed because Arduino is using 5V for high signal and A7 is using 3.3V)

My mistakes and solutions:
A7 has separate pin for GPS data. After turning on GPS (with command AT+GPS=1) board start transfering GPS NMEA data to this pin. So to get these data through GPS pin, it is needed to support two serials (one for board management - AT commands and second for GPS data). I tried to do it with library SoftwareSerial, got some positive results, but there was more problems than success ;)
Then I found out, that A7 board has command "AT+GPSRD", which as response provide one packet of GPS NMEA data through AT serial. So using this command it is enough to have one Serial. But while I was using library SoftwareSerial, I had some problems in communication. Then I decided to use library AltSoftSerial and vuolia - everything started to work as I wanted ;)
Note: AltSoftSerial require to use pins D8 and D9 for serial.

There is my code:
p.s. I'm not professional programmer, so sorry for some mess in code, but it works ;)
You need to find thease lines and modify according your situation:
sendCommand("at+cipstart=\"TCP\",\"46.251.52.32\",118","CONNECT OK",5000,1000,cont);
A6board.print("GET /gps.php?msg=");
A6board.print("HOST: 46.251.52.32");

The  46.251.52.32 is my own web, which is created only for testing.
The same with "/gps.php?msg=". So you need to use own web.

sendCommand("AT+CGDCONT=1,""IP"",""omnitel""","OK",2000,0,cont);
sendCommand("AT+CSTT=""omnitel"",""omni"",""omni""","OK",2000,0,cont);

This is my APN setup. You need setup according your mobile network provider.

Code: [Select]

#include <AltSoftSerial.h>

AltSoftSerial A6board;

char buffer[100];
char end_c[2];
int i;
int8_t answer;
/************************************************************************************************/
int8_t sendATcommand(String ATcommand, String expected_answer, unsigned int timeout, String &content){
    uint8_t answer=0;
    unsigned long previous;
 
    delay(100); // Delay to be sure no passed commands interfere
    while( A6board.available() > 0) A6board.read();    // Wait for clean input buffer
    A6board.println(ATcommand);    // Send the AT command
    previous = millis();
    content = "";
    // this loop waits for the answer
    do{
        // if there are data in the UART input buffer, reads it and checks for the asnwer
        if(A6board.available() != 0){
            String part = String(char(A6board.read()));
           
            content += part;
 
            // check if the desired answer is in the response of the module
            if (content.indexOf(expected_answer)>0){
                answer = 1;
            }
        }
    // Waits for the answer with time out
    } while((answer == 0) && ((millis() - previous) < timeout));   
    return answer;
}

/************************************************************************************************/
boolean sendCommand(String cmd, String expAnsw, unsigned int timeout, unsigned int freez, String &cont){
  //String cont;
  cont = "";
  boolean stat = false;
  if (sendATcommand(cmd,expAnsw,timeout, cont)==1) {
     Serial.print("OK: "); Serial.print(cmd); Serial.print("(Wait for: "); Serial.print(replace4VIEW(expAnsw)); Serial.println(")");
     stat = true;
  } else {
     Serial.print("ERROR: "); Serial.print(cmd); Serial.print("(Wait for: "); Serial.print(replace4VIEW(expAnsw)); Serial.println(")");
     stat = false;
  }
  Serial.println("*********** Content Begin *************");
  Serial.println(replace4VIEW(cont));
  Serial.println("*********** Content End *************");
  Serial.println();
  delay(freez);
  return stat;
}
String replace4URL(String txt){
  txt.replace("\r","%0D");
  txt.replace("\n","%0A");
  return(txt);
}
String replace4VIEW(String txt){
  txt.replace("\r","\\r");
  txt.replace("\n","\\n");
  return(txt);
}
/************************************************************************************************/
void uploanGPS(){
  String answ;
  int i;
  if (sendCommand("AT+GPSRD","OK",10000,0,answ)) { 
     String cont;
     sendCommand("at+cipstart=\"TCP\",\"46.251.52.32\",118","CONNECT OK",5000,1000,cont);
     sendCommand("AT+CIPSTATUS","OK",5000,1000,cont); 
     sendCommand("AT+CIPSEND",">",2000,500,cont);
     //A6board.print("GET /gps.php?msg=AT+GPSRD%0D%0A+GPSRD:$GPGGA,215549.000,,,,,0,00,,,M,,M,,0000*76%0D%0A$GPRMC,215549.00V,0,%0DVTNN%0A%0D HTTP/1.1");
     A6board.print("GET /gps.php?msg=");
     for (i=1; i<=answ.length(); i++) {
        char simb = answ.charAt(i);
        if (simb == 0x0D) {
          A6board.print("%0D");
        } else if (simb == 0x0A) {
          A6board.print("%0A");
        } else {
          A6board.print(char(simb));
        }
     }
     A6board.print(" HTTP/1.1");
     A6board.print("\r\n");
     A6board.print("HOST: 46.251.52.32");
     A6board.print("\r\n");
     A6board.print("\r\n");
     sendCommand(end_c,"OK",30000,0,cont);
     sendCommand("AT+CIPSTATUS","OK",5000,1000,cont);
     sendCommand("AT+CIPCLOSE","OK",15000,0,cont);
  }
}
/************************************************************************************************/
void setup() {
  String cont;
  Serial.begin(19200);
  A6board.begin(19200);
 
  Serial.println("Start");
  end_c[0] = 0x1a;
  end_c[1] = '\0';
 
  A6board.listen();
 
  Serial.print("Swiching to 19200 baudrait -> ");
  while(answer == 0){     // Send AT every two seconds and wait for the answer
    answer = sendATcommand("AT", "OK", 2000, cont);
    Serial.print("*");   
  }
  Serial.println("");

  sendCommand("AT+GPS=1","OK",2000,0,cont);
  sendCommand("AT+CREG=0","OK",2000,1000,cont);
  sendCommand("ATE0","OK",2000,1000,cont);   
  sendCommand("AT+CMEE=2","OK",2000,1000,cont);
  sendCommand("AT+CGATT=1","OK",5000,1000,cont);
  sendCommand("AT+CGDCONT=1,""IP"",""omnitel""","OK",2000,0,cont);
  sendCommand("AT+CSTT=""omnitel"",""omni"",""omni""","OK",2000,0,cont);
  sendCommand("AT+CGACT=1,1","OK",2000,0,cont);
////////////
 sendCommand("AT","OK",5000,0,cont);
 sendCommand("AT+GPSRD","OK",1000,0,cont);
 sendCommand("AT+GPSRD","\r\n\r\n",1000,0,cont);
 sendCommand("AT","OK",5000,0,cont);
}
/************************************************************************************************/
void loop() {
  String hh;
  String cont;
  if (Serial.available()) {
    hh = Serial.readStringUntil('\n');
    hh.toCharArray(buffer, hh.length() + 1);
    if (hh.indexOf("show_gps") == 0) {
         sendCommand("AT+GPSRD","OK",10000,0,cont);
         Serial.println(replace4VIEW(cont));
    } else if (hh.indexOf("upload_gps") == 0) {
       uploanGPS();       
    }else{
      A6board.write(buffer);
      A6board.write('\n');
    }
  }     
 
  if (A6board.available()) {
      hh = A6board.readStringUntil('\n');
      Serial.println("gprs: "+hh);
  }
  uploanGPS();
}


Currently I know few problems, which is not solved:
1. Time to time, A7 give to big package of GPS NMEA data, so there is it needed to parse these data.
2. As I noticed, currently A7 board don't wait until he will receive answer from WEB. It put data to the web and close communication. Any way web receive these data, but it would be good always get response from the web and parse it to find out if web got and saved these data.
3. Some SMS or Call to A7 board will rise errors to the commands, which was executed at that time. So it is needed to find out how to manage incoming commands, when A7 board is executing something else.

Alemorenao

#13
Mar 07, 2017, 03:27 pm Last Edit: Mar 07, 2017, 03:34 pm by Alemorenao Reason: I put my comment inside the quote.
• Ai Thinker A7 (for GPS I bought another antenna, because antenna shipped with board is not compatible for GPS signal).
Could you please tell me specifically what kind or model of GPS antenna did you buy??

farjad_shah

Hi guys. Your discussion is helping us a lot. Thanks to all of you. Well, so far we are good with the connections between A7 module and Arduino Uno. How about that GPS pin in module? How we connect this? So that we might be  able to get a GPS access from the module Or we may start GPS communication between arduino and A7 module..

Thanks in advance.  :smiley:

Go Up