0

I wrote an Arduino code to get the latitude,longitude,speed,date and time using the GPS SKG 13BL at every 5 secs and sent it to the database with the help of a php code using GSM 900A.The code is as follows :

#include <NeoSWSerial.h>

#include <AltSoftSerial.h>
#include <NMEAGPS.h>

NeoSWSerial GSM(2, 3); // RX, TX: Connect TXD to RX & RXD to TX

static const int RXPin = 8, TXPin = 9;
AltSoftSerial gpsPort(RXPin, TXPin);
static const uint32_t GPSBaud = 9600;

NMEAGPS gps;
gps_fix fix;
uint8_t fixCount = 0;
char dt[15],tm[15],lati[10],longi[10];


enum _parseState {
  PS_DETECT_MSG_TYPE,

  PS_IGNORING_COMMAND_ECHO,

  PS_HTTPPARA_RESPONSE,

  PS_HTTPACTION_TYPE,
  PS_HTTPACTION_RESULT,
  PS_HTTPACTION_LENGTH,

  PS_HTTPREAD_LENGTH,
  PS_HTTPREAD_CONTENT
};

enum _actionState {
  AS_IDLE,
  AS_WAITING_FOR_RESPONSE
};

byte actionState = AS_IDLE;
unsigned long lastActionTime = 0;

int s;

byte parseState = PS_DETECT_MSG_TYPE;
char buffer[160],url[160];
byte pos = 0;

int contentLength = 0;

void resetBuffer() {
  memset(buffer, 0, sizeof(buffer));
  pos = 0;
}

void sendGSM(const char* msg, int waitMs = 500) {
  GSM.println(msg);
  while(GSM.available()) {
    parseATText(GSM.read());
  }
  //delay(waitMs);
}

void setup()
{
  GSM.begin(9600);
  Serial.begin(9600);
  gpsPort.begin(GPSBaud);

  Serial.println(F("Hinder LOADING....."));
  Serial.println(F("obtain gps and store data to database"));
  Serial.println(F("Testing by : "));
  Serial.println(F("Nikhil,Muthumani and Mathews"));
  Serial.println();

  sendGSM("AT+SAPBR=3,1,\"APN\",\"vodafone\"");  
  delay(500);
  sendGSM("AT+SAPBR=1,1",3000);
  delay(500);
  sendGSM("AT+HTTPINIT"); 
  delay(500); 
  sendGSM("AT+HTTPPARA=\"CID\",1");
  delay(500);
}

void loop()
{ 
  unsigned long now = millis();
  while (gps.available( gpsPort )) {
    fix = gps.read();
     //Serial.println(F("b"));
    // Once every 5 seconds...    
    if (++fixCount >= 5) {
       //Serial.println(F("a"));
      displayInfo();

      //send the next report if previous one is finished
      if ( actionState == AS_IDLE ) {
      sprintf(url, "AT+HTTPPARA=\"URL\",\"http://********.com/***er.php?lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",lati,longi,s,dt,tm );
      sendGSM(url);
     // lastActionTime = now;
      parseState = PS_HTTPPARA_RESPONSE; // a new state
      actionState = AS_WAITING_FOR_RESPONSE;
      fixCount = 0;
    }

    }
  }

/*  if ((gps.statistics.chars < 10) && (millis() > 5000)) {
     Serial.println( F("No GPS detected: check wiring.") );
     while(true);
     block=1;
    }*/

  while(GSM.available()) {
    //lastActionTime = now;
    parseATText(GSM.read());
  }
 }


void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (fix.valid.location) {
    dtostrf( fix.latitude(),7,5,lati);
    //sprintf(lati,"%d",fix.latitude(),5);
    Serial.print(lati);
    Serial.print( ',' );
    dtostrf( fix.longitude(),8,5,longi);
    //sprintf(longi,"%d",fix.longitude(),5);
    Serial.print(longi);
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Speed: ")); 
  if (fix.valid.speed) {
    s=fix.speed_kph();
    Serial.print(s);
    Serial.print(F(" KMPH "));
  } else {
    Serial.print(F("INVALID"));
  }

  // Shift the date/time to local time
  NeoGPS::clock_t localSeconds;
  NeoGPS::time_t  localTime;
  if (fix.valid.date && fix.valid.time) {
    using namespace NeoGPS; // save a little typing below...

    localSeconds = (clock_t) fix.dateTime; // convert structure to a second count
    localSeconds += 5 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE; // shift timezone
    localTime = localSeconds;              // convert back to a structure
  }

  Serial.print(F("  Date : "));
  if (fix.valid.date) {
    sprintf(dt,"%02d/%02d/20%d",fix.dateTime.date,fix.dateTime.month,fix.dateTime.year);
    Serial.print(dt);
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Time : "));
  if (fix.valid.time) {
    if (localTime.hours>12)localTime.hours-=12;//To convert 24 hr format to 12 hr format
    sprintf(tm,"%02d:%02d:%02d",localTime.hours,localTime.minutes,localTime.seconds);
    Serial.print(tm);
    //block=1;
  } else {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}

void parseATText(byte b) {

  buffer[pos++] = b;

  if ( pos >= sizeof(buffer) )
    resetBuffer(); // just to be safe

  /*
   // Detailed debugging
   Serial.println();
   Serial.print("state = ");
   Serial.println(state);
   Serial.print("b = ");
   Serial.println(b);
   Serial.print("pos = ");
   Serial.println(pos);
   Serial.print("buffer = ");
   Serial.println(buffer);*/

  switch (parseState) {

  case PS_HTTPPARA_RESPONSE:
    {
      parseState = PS_DETECT_MSG_TYPE;
      sendGSM("AT+HTTPACTION=0");
     /*  while(GSM.available()) {
    //lastActionTime = now;
    parseATText(GSM.read());
  }*/

    }
    break;

  case PS_DETECT_MSG_TYPE: 
    {
      if ( b == '\n' )
        resetBuffer();
      else {        
        if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
          parseState = PS_IGNORING_COMMAND_ECHO;
        }
        else if ( b == ':' ) {
          //Serial.print("Checking message type: ");
          //Serial.println(buffer);

          if ( strcmp(buffer, "+HTTPACTION:") == 0 ) {
            Serial.println("Received HTTPACTION");
            parseState = PS_HTTPACTION_TYPE;
          }
          else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) {
            Serial.println("Received HTTPREAD");            
            parseState = PS_HTTPREAD_LENGTH;
          }
          resetBuffer();
        }
      }
    }
    break;

  case PS_IGNORING_COMMAND_ECHO:
    {
      if ( b == '\n' ) {
        Serial.print("Ignoring echo: ");
        Serial.println(buffer);
        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_TYPE:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION type is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_RESULT;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_RESULT:
    {
      if ( b == ',' ) {
        Serial.print("HTTPACTION result is ");
        Serial.println(buffer);
        parseState = PS_HTTPACTION_LENGTH;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPACTION_LENGTH:
    {
      if ( b == '\n' ) {
        Serial.print("HTTPACTION length is ");
        Serial.println(buffer);

        // now request content
        GSM.print("AT+HTTPREAD=0,");
        GSM.println(buffer);

        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_LENGTH:
    {
      if ( b == '\n' ) {
        contentLength = atoi(buffer);
        Serial.print("HTTPREAD length is ");
        Serial.println(contentLength);

        Serial.print("HTTPREAD content: ");

        parseState = PS_HTTPREAD_CONTENT;
        resetBuffer();
      }
    }
    break;

  case PS_HTTPREAD_CONTENT:
    {
      // for this demo I'm just showing the content bytes in the serial monitor
      Serial.write(b);

      contentLength--;

      if ( contentLength <= 0 ) {

        // all content bytes have now been read

        parseState = PS_DETECT_MSG_TYPE;
        resetBuffer();

        Serial.print("\n\n\n");

        actionState = AS_IDLE;
      }
    }
    break;
  }
}

When I test the code it shows the output as : enter image description here as you can see after Ignoring echo: AT+HTTPREAD=0,0 the GPS output is printed out at every sec (not at 5 sec interval) and also does not perform rest of the actions (i.e Sending to database is not performed). And I press reset button and the output is : enter image description hereEven though it prints the GPS output at every sec it inserted the values into database.And once again I press reset button then it works fine.So why do this error occurs and is there a way to solve this.And can I make the program run only when GPS data is available (because now if GPS data is not available it shows some error nature ).

1 Answer 1

0

:)

Why does this error occur, and is there a way to solve this?

Because the GSM operations take time, the GPS data has time to accumulate. Then the while (gps.available loop will execute multiple times without breaking. It calls displayInfo every time because fixCount >= 5. fixCount is 6, 7, 8, etc. in consecutive seconds.

To solve this problem, you need to be more restrictive about starting the sending process:

void loop()
{ 
  while (gps.available( gpsPort )) {
    fix = gps.read();
     //Serial.println(F("b"));

    //send a report once every 5 seconds if previous one is finished
    if ((++fixCount >= 5) && (actionState == AS_IDLE)) {

      //Serial.println(F("a"));
      displayInfo();

      sprintf(url, "AT+HTTPPARA=\"URL\",\"http://********.com/***er.php?lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",lati,longi,s,dt,tm );
      sendGSM(url);
      parseState  = PS_HTTPPARA_RESPONSE; // a new state
      actionState = AS_WAITING_FOR_RESPONSE;
      fixCount    = 0;
    }
  }

  while(GSM.available()) {
    parseATText(GSM.read());
  }
}

The combined if test displays GPS info only when the GSM process begins. Then it will continue to read fixes, keeping the queue emptied. When the state goes back to AS_IDLE, it can send another update. Notice how this loop structure will continue counting fixes while the GSM process is completing. If the GSM process takes 5 seconds or more, it will immediately send another update when the previous GSM send has completed.

If you want it to wait an additional 5 seconds between each GSM update, don't increment the fixCount until the GSM process has completed (AS_IDLE). Then the updates will be sent once every 5 + (GSM send time) seconds, perhaps once every 15 seconds.

can I make the program run only when GPS data is available (because now if GPS data is not available it shows some error nature ).

Yes, make the if test even more restrictive by testing the valid flags:

    //send a report once every 5 seconds if the data is valid
    //   and the previous one is finished
    if ((fix.valid.location && fix.valid.date && fix.valid.time) &&
        (++fixCount >= 5) &&
        (actionState == AS_IDLE)) {

This only counts valid fixes; the fixCount will not increment unless those 3 pieces are valid.

NOTE: You probably don't have to test fix.valid.speed, as it will be marked as invalid when you are stationary. Testing the valid flags could be removed from displayInfo():

void displayInfo()
{
  Serial.print(F("Location: ")); 
  dtostrf( fix.latitude(),7,5,lati);
  Serial.print(lati);
  Serial.print( ',' );
  dtostrf( fix.longitude(),8,5,longi);
  Serial.print(longi);

  Serial.print(F("  Speed: ")); 
  if (fix.valid.speed) {
    s=fix.speed_kph();
  } else {
    s=0;
  }
  Serial.print(s);
  Serial.print(F(" KMPH "));

  // Shift the date/time to local time
  NeoGPS::clock_t localSeconds;
  NeoGPS::time_t  localTime;
  {
    using namespace NeoGPS; // save a little typing below...

    localSeconds = (clock_t) fix.dateTime; // convert structure to a second count
    localSeconds += 5 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE; // shift timezone
    localTime = localSeconds;              // convert back to a structure
  }

  Serial.print(F("  Date : "));
  sprintf(dt,"%02d/%02d/20%d",fix.dateTime.date,fix.dateTime.month,fix.dateTime.year);
  Serial.print(dt);

  Serial.print(F("  Time : "));
  if (localTime.hours>12)localTime.hours-=12;//To convert 24 hr format to 12 hr format
  sprintf(tm,"%02d:%02d:%02d",localTime.hours,localTime.minutes,localTime.seconds);
  Serial.print(tm);
  //block=1;

  Serial.println();
}

displayInfo still checks fix.valid.speed and uses 0 when there is no speed (i.e., when you're stationary).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.