0
votes

I started a project quite recently were I intend to combine the arduino uno and the sim808 module which has gps/gsm/gprs all together in one.

Using just the gps functionality works fine, just the gsm both receiving and sending messages also works good. but combining them for what i intend makes the entire system falls apart.

I intend to be able to have some coordinates registered let's say position A position B and position c, and the system i intend to design is put on a moving, let's say car, now anyone on either of the positions will send a message with the alphabet denoting the position to a number lets say "A TO +23*******98 , AND WOULD get a reply of the cars current time from that position.

With all parts combined the program would sometimes not even indicate receiving any message or even if it did the gps part won't even work.

Is there something I am doing wrong or is it not just feasible with what the components I am using pls help as I am very confused right now.

`#include <SoftwareSerial.h>
SoftwareSerial GPRS(7, 8); // RX, TX

  String BUSNUM="A";  // THIS SIM IS TO BE INSTALLED ON BUS A
  static String sendersnumber;
  char* key;
  char MESSAGE[280];
  String latitude;
  String longitude;

  String Speed;

enum _parseState 
{


    PS_DETECT_MSG_TYPE,
      PS_IGNORING_COMMAND_ECHO,

      PS_READ_CMTI_STORAGE_TYPE,
      PS_READ_CMTI_ID,
      PS_DETECT_MSG_TYPE2,
      PS_IGNORING_COMMAND_ECHO2,
      PS_READ_CMGR_STATUS2,
      PS_READ_CMGR_CONTENT2,
      PS_READ_CMGR_DATE2,

      PS_READ_CMGR_STATUS,
      PS_READ_CMGR_NUMBER2,
      PS_READ_CMGR_NUMBER,
      PS_READ_CMGR_SOMETHING,
      PS_READ_CMGR_DATE,
      PS_READ_CMGR_CONTENT,
      PS_READ_VIDEO_CONTENT,
      PS_READ_VIDEO2_CONTENT,
      PS_READ_CMGR_SOMETHING2,
      PS_READ_VIDEO_CONTENT2,
    };

    byte state = PS_DETECT_MSG_TYPE; // KEEP TRACK OF WHAT STATE WE ARE IN RIGHT NOW

    char buffer[100]; // WHAT WE ARE READING INTO

    byte pos = 0;  //WHAT POSITION WE ARE AT IN THAT BUFFER

    int lastReceivedSMSId = 0;  // LAST RECIEVED SMS ID
    boolean validSender = false; //SOO NOT JUST ANYONE HAS ACESS TO SEND A COMMAND


    void resetBuffer() 
    {
      memset(buffer, 0, sizeof(buffer));
      pos = 0;
    }//BASICALLY TO RESET THE BUFFER


    void setup()
    {

      GPRS.begin(9600);
      Serial.begin(9600);
      GPRS.println("AT+CGNSPWR=1");
      delay(290);
      GPRS.println("AT+CGNSURC=0");
      delay(300);
      GPRS.println("AT");
      delay(300);
      GPRS.println("AT+CMGF=1"); // INITIALIZE SMS
      delay(300);

      for (int i = 1; i <= 15; i++) 
      {
        GPRS.print("AT+CMGD=");
        GPRS.println(i);
        delay(300);
        // Not really necessary but prevents the serial monitor from dropping any input SINCE WE KNOW LIMIT TO STORE IS 15, THIS JUST DELETES IT CLEARS IT
        while(GPRS.available()) 
          Serial.write(GPRS.read());
      }   
        delay(2000);
       GPRS.println("AT+CGNSURC=1");     

    }

    void loop()
    {

     while(GPRS.available()) //ONLY WHEN THERE IS SOMETHING AVAILABLE,
      {


       GSM_NUM1(GPRS.read());  
       //delay(50);
       GPRS.println("AT+CGNSINF");
      // delay(40);    

        GPSAnalyzer(GPRS.read());

        sendSMS();

      }

    }
    // END OF VOID LOOP



    void GSM_NUM1(byte b)
    {

      buffer[pos++] = b;

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

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

              if ( strcmp(buffer, "+CMTI:") == 0 ) {
                Serial.println("Received CMTI");
                state = PS_READ_CMTI_STORAGE_TYPE;
              }
              else if ( strcmp(buffer, "+CMGR:") == 0 ) {
                Serial.println("Received CMGR");            
                state = PS_READ_CMGR_STATUS;
              }
              resetBuffer();
            }
          }
        }
        break;

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

      case PS_READ_CMTI_STORAGE_TYPE:
        {
          if ( b == ',' ) {
            Serial.print("SMS storage is ");
            Serial.println(buffer);
            state = PS_READ_CMTI_ID;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMTI_ID:
        {
          if ( b == '\n' ) {
            lastReceivedSMSId = atoi(buffer);
            Serial.print("SMS id is ");
            Serial.println(lastReceivedSMSId);

            GPRS.print("AT+CMGR=");
            GPRS.println(lastReceivedSMSId);
            //delay(500); don't do this!

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

      case PS_READ_CMGR_STATUS:
        {
          if ( b == ',' ) {
            Serial.print("CMGR status: ");
            Serial.println(buffer);
            state = PS_READ_CMGR_NUMBER;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_NUMBER:
        {
          if ( b == ',' ) {
            Serial.print("CMGR MSSG SENDERS Number: ");
           Serial.println(buffer);
           String sendersnumber=buffer;
            // Uncomment these two lines to check the sender's cell number
            //validSender = false;
            //if ( strcmp(buffer, "\"+0123456789\",") == 0 )
            validSender = true;

            state = PS_READ_CMGR_SOMETHING;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_SOMETHING:
        {
          if ( b == ',' ) {
            Serial.print("CMGR something A.K.A SENDER'S NAME: ");
            Serial.println(buffer);
            state = PS_READ_CMGR_DATE;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_DATE:
        {
          if ( b == '\n' ) {
            Serial.print("CMGR date: ");
            Serial.println(buffer);
            state = PS_READ_CMGR_CONTENT;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_CONTENT:
        {
          if ( b == '\n' ) {
            Serial.print("CMGR MESSAGE Content: ");
            Serial.print(buffer);
             String key=buffer;

           //  sendSMS();
           // GPSAnalyzer();

            GPRS.print("AT+CMGD=");
            GPRS.println(lastReceivedSMSId);

            //delay(500); don't do this!

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

    }



      void GPSAnalyzer(byte b) 
     {

       buffer[pos++] = b;

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

        switch (state) 
      {
      case PS_DETECT_MSG_TYPE2: 
        {
          if ( b == '\n' )
            resetBuffer();
          else {        

            if ( pos == 9 ) {
             // Serial.print("Checking message type: ");
             // Serial.println(buffer);

              if ( strcmp(buffer, "+UGNSINF:") == 0 ) {
                Serial.println("Received CGNSINF:");            
                state = PS_READ_CMGR_STATUS2;
              }
              resetBuffer();
            }
          }
        }
        break;

        //CHECK
        case PS_IGNORING_COMMAND_ECHO2:
        {
          if ( b == '\n' ) {
            //Serial.print("Ignoring echo: ");
            //Serial.println(buffer);
            state = PS_DETECT_MSG_TYPE2;
            resetBuffer();
          }
        }
        break;

    //THIS WOULD READ FROM +CGNSINF: (TO THE COMMA),
      case PS_READ_CMGR_STATUS2:
        {
          if ( b == ',' ) {
            Serial.print("RUN STATUS: ");
            Serial.println(buffer);
            String runstatus=buffer;


            state = PS_READ_CMGR_NUMBER2;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_NUMBER2:
        {
          if ( b == ',' ) {
            Serial.print("FIX STATUS : ");
           Serial.println(buffer);

           String fixstatus=buffer;
          fixstatus.replace(","," ");
            validSender = true;

            state = PS_READ_CMGR_SOMETHING2;
            resetBuffer();
          }
        }
        break;
    // this is DATE AND TIME i dont need this
      case PS_READ_CMGR_SOMETHING2:
        {
          if ( b == ',' ) {
            Serial.print("DATE AND TIME : ");
            Serial.println(buffer);
            String dateandtime=buffer;

            state = PS_READ_CMGR_DATE2;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_DATE2:
        {
          if ( b == ',' ) {
            Serial.print("LATITUDE: ");
            Serial.println(buffer);
              latitude=buffer;
              latitude.replace(","," ");

            state = PS_READ_CMGR_CONTENT2;
            resetBuffer();
          }
        }
        break;

      case PS_READ_CMGR_CONTENT2:
        {
          if ( b == ',' ) {
            Serial.print("LONGITUDE: ");
            Serial.println(buffer);
            longitude=buffer;
            longitude.replace(","," ");

            state = PS_READ_VIDEO_CONTENT2;
            resetBuffer();
            //delay(500); don't do this!

          }
        }
        break;

       case PS_READ_VIDEO_CONTENT2:
       {
          if ( b == ',' ) {
            Serial.print("ALTITUDE: ");
            Serial.println(buffer);
            String Altitude=buffer;

            state = PS_READ_VIDEO2_CONTENT;
            resetBuffer();
            //delay(500); don't do this!
         }
        }
        break;

        case PS_READ_VIDEO2_CONTENT:
        {
         if ( b == ',' ) {
            Serial.print("SPEED(KM/HR): ");
            Serial.println(buffer);
            String Speed=buffer;
            Speed.replace(","," ");

                   state =PS_DETECT_MSG_TYPE2;
            resetBuffer();

          }
        }
        break;
      //use goto to put it at sms begining
      }
     }  

     void sendSMS() 
      {
        if ( strcmp(key,"A") == 0 )
    {
     float lati=7.200970;
     float longi=5.181782;
     float Speed1 = atof(Speed.c_str());
     float latituded = atof(latitude.c_str());
     float longituded = atof(longitude.c_str());
     float Distance = HaverSine(lati,longi,latituded,longituded);
     float duration=Distance/Speed1; 
     const int StrLen = 10; 
     char * duration_new ;
     double Value = duration; 
     (void) dtostrf (Value, StrLen, 6, duration_new); 

     String MESSAGE="BUS A";
     MESSAGE+=duration_new ; 
     Serial.print("THE MESSAGE SENT IS ");
     Serial.println(MESSAGE);
    }

     else if ( strcmp(key,"B") == 0 )
    {
     float lati=7.290970;
     float longi=5.141782;
     float Speed1 = atof(Speed.c_str());
     float latituded = atof(latitude.c_str());
     float longituded = atof(longitude.c_str());
     float Distance = HaverSine(lati,longi,latituded,longituded);
     float duration=Distance/Speed1; 
     const int StrLen = 10; 
     char * duration_new ;
     double Value = duration; 
     (void) dtostrf (Value, StrLen, 6, duration_new); 

     String MESSAGE="BUS B";
     MESSAGE+=duration_new ; 
     Serial.print("THE MESSAGE SENT IS ");
     Serial.println(MESSAGE);
    }


      delay(300);
      GPRS.print("AT+CMGF=1\r\n");                                                       
      delay(100);
      GPRS.println("AT+CMGS=\""+sendersnumber+"\"\r\n");                                   
      delay(100);
      GPRS.println(MESSAGE);       
      delay(100);
      GPRS.println((char)26);                       
      delay(100);
      GPRS.println();
      delay(100);
    }



    float HaverSine(float lat1,float lon1,float lat2,float lon2)
    {
      String fixstatus;
     float ToRad = PI / 180.0;
     float R = 6371;   // radius earth in Km

     float dLat = (lat2-lat1) * ToRad;
     float dLon = (lon2-lon1) * ToRad;

     float a = sin(dLat/2) * sin(dLat/2) +
           cos(lat1 * ToRad) * cos(lat2 * ToRad) *
           sin(dLon/2) * sin(dLon/2);
           String o= fixstatus + "8";


     float c = 2 * atan2(sqrt(a), sqrt(1-a));

     float d = R * c;
     return d;
    }

EXPLANATION After all declarations and initializations the first active part of the entire code is the for loop that just deletes all former messages from the sim card memory.it runs 15 times

for (int i = 1; i <= 15; i++) { GPRS.print("AT+CMGD="); GPRS.println(i); delay(300); while(GPRS.available()) Serial.write(GPRS.read()); } Now, having functions GSM_NUM1(); GPSAnalyzer(); sendSMS(); Which are defined below in the code

GSM_NUM1(); GPSAnalyzer(); both work similarly they extract needed data which come in separated by commas. For the gps which comes in , in the form

+UGNSINF: ,,,,, ,,, ,,,,,,, ,,,,

lathitude, speed and any other important parameter is extracted.

For GSM_NUM1(); it gets the senders message and number into variable.

sendSMS(); this just does some calculation based on the message received and send a certain result to the number who requested it.

OBERVATIONS

When the program starts nothing happens which is good cause nothing is supposed to until something new comes in. Hence the void loop() { while(GPRS.available()) //ONLY WHEN THERE IS SOMETHING AVAILABLE, { GSM_NUM1(GPRS.read()); //delay(50); GPRS.println("AT+CGNSINF"); // delay(40); GPSAnalyzer(GPRS.read()); sendSMS(); } Now this is were things go bad, as the first function works good, it waits gets the message and extracts the senders number and message"key" into variables but immediately after that I wantjust one return of the gps info shown below that's why I used ("AT+CGNSINF"); instead of ("AT+CGNSURC=1"); as the later gives continuous gps data such as

+UGNSINF: ,,,,, ,,, ,,,,,,, ,,,,

BUT instead of one line of the gps data to be gotten from were lathitude and some other parameters are extracted into variables "THE PROGRAM HANGS/STOPS for some unknown reason.

SUSPICIONS

Since the SIM808 possess gps/gsm on the same module. It makes it kind of tricky to separate them in the sense that.

IF I WANT THE GPS TO BE ON BUT NOT READ IN ANY DATA UNTIL A VALID REQUEST COMES IN , IN FORM OF AN SMS THEN THE NECESSARY GPS INFORMATION IS PARSED AND SOME CALCULATIONS ARE DONE TO GET A PARAMETER THAT WOULD BE SENT TO THE SAME NUMBER THAT REQUESTED IT.

PERSONNALY, I FEEL THAT GETTING THE GPS AND GSM TO WORK HAND IN HAND WITHOUT CANCELLING EACH OTHER OUT IN SOME WAY,SUCESSFULLY WOULD BE THE END OF MY PROBLEM. AND I THINK IT COMES DOWN TO THE POSITION OF THE AT COMMAND

GPRS.println("AT+CGNSURC=1"); AND/OR GPRS.println("AT+CGNSINF"); AS the former spits out the gps data every GNSS FIX continuously when called once and LATER spits it out just once per one command.

the attached picture just shows the continous nature of the output of ("AT+CGNSURC=1"); , just as ("AT+CGNSINF"); spits out just one line with +CGNSINF: at the begining instead

2

2 Answers

0
votes

Please check that is not in overflow SRAM , that produces stranger things when you execute the program. This occur when you declare so much variables, you can use this library to check the use of sram.

0
votes

I ran into this similar issue with trying to get GPS data from a module over serial but figured it out after painstaking hours. Essentially you need to validate every response from every command and flush the serial port before every write.

Flushing the serial port buffer before you write any command will ensure that you don't accidentally read left over characters from a previous command when you are trying to get the output of the one you just ran. Most TAs (Terminal Adapters) use EOL characters like OK which translates into "\r\nOK\r\n". If you do not read them all, they can hang around and interfere with the next command you send/ read a response from. use GPRS.flush() to get rid of extra garbage characters in the serial buffer before sending commands.

Also, creating a generic command function to pass all AT commands and validate their output will save you a lot of sleep.

something like

int sendCommand(int fd, char* message, char* eol, char* response){
 int wlen, rlen;
 char buf[1024];

 tcflush(fd, TCIOFLUSH); //flush the serial port to remove anything left over

 wlen = write(fd, message, strlen(message)); //write command to terminal

   tcdrain(fd); //delay until 1st readable character is written by modem
   delay(100); //delay a little longer until all characters are written(hopefully)

   rdlen = read(fd, buf, sizeof(buf) - 1); //read from serial port

   if(rdlen > 0){ //if readable characters
     if(strstr(buf, eol) != NULL){ //if my end of line character is present then 
       int i = 0;                  //output from TA is complete
       while(buf[i] != '\0'){ //while buffer has more characters
        response[i] = buf[i]; //copy string into the string I passed, char by char
       }
       return 1; //return 1 (i.e.true aka success)
     }
   }
   return 0; //return 0 (i.e. false aka failure)
}

I wrote this for a communicating to a simcom5320 but I didnt use software serial so it'll be a little different for you. Use this function for all your at commands to ensure everything actually succeed like:

char commandReply[512];

if(sendCommand(myFileDescriptor, "AT+CGNSINF\r", "\r\nOK\r\n", commandReply)){
  //do something with commandReply or not

} else {
  //command failed
  //do something else
}

Hope this helps!