首页 文章

ARDUINO UNO SIM808(GPS / GSM)同步

提问于
浏览
0

我最近开始了一个项目,我打算将arduino uno和sim808模块结合在一起,它们将gps / gsm / gprs合二为一 .

使用gps功能工作正常,只需gsm接收和发送消息也很好 . 但是为了我想要的东西而将它们结合起来会使整个系统崩溃 .

我打算能够注册一些坐标,让我们说位置A位置B和位置c,我打算设计的系统放在一个移动的,比方说汽车,现在任何一个位置的任何人都会发送一个消息表示数字位置的字母表可以说“A to 23 ******* 98,并且可以从那个位置获得汽车当前时间的回复 .

由于所有部分组合在一起,程序有时甚至不会指示接收任何消息,即使它确实gps部分甚至不能工作 .

有什么我做错了或者它不仅仅是可行的我正在使用的组件帮助,因为我现在很困惑 .

`#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;
    }

说明在所有声明和初始化之后,整个代码的第一个活动部分是for循环,只删除来自sim卡存储器的所有以前的消息 . 它运行15次

for(int i = 1; i <= 15; i){GPRS.print(“AT CMGD =”); GPRS.println(ⅰ);延迟(300); while(GPRS.available())Serial.write(GPRS.read());现在,具有函数GSM_NUM1(); GPSAnalyzer();发送短信();这些在代码中定义如下

GSM_NUM1(); GPSAnalyzer();两者同样工作,他们提取所需的数据,这些数据以逗号分隔 . 对于进入的gps,在表单中

UGNSINF:,,,,, ,,,,,,,,,,,,,

提取了lathitude,speed和任何其他重要参数 .

对于GSM_NUM1();它将发件人的消息和号码变为变量 .

发送短信();这只是基于收到的消息进行一些计算,并将一定的结果发送给请求它的号码 .

OBERVATIONS

当程序启动时没有任何事情发生,这是好事,因为在新的东西进来之前什么都不应该 . 因此void loop(){while(GPRS.available())//只有当有可能时,{GSM_NUM1(GPRS.read) ()); //延迟(50); GPRS.println(“AT CGNSINF”); //延迟(40); GPSAnalyzer(GPRS.read());发送短信();现在这是事情变得糟糕,因为第一个功能运行良好,它等待获取消息并提取发件人号码和消息“密钥”变成变量但是之后我想要一次返回显示如下所示的gps信息这就是为什么我用过(“AT CGNSINF”);代替(“AT CGNSURC = 1”);因为后者给出了连续的gps数据,如

UGNSINF:,,,,, ,,,,,,,,,,,,,

但是,而不是从gps数据的一行得到的是lathitude和一些其他参数被提取到变量“程序悬挂/ STOPS由于某种未知的原因 .

猜疑

由于SIM808在同一模块上具有gps / gsm . 从某种意义上说,将它们分开是很棘手的 .

如果我想要GPS,但是没有读取任何数据,直到有效请求进入,以短信的形式存在必要的GPS信息,并且已经完成了一些计算以获得将被发送到同一号码的参数要求它 .

个人,我觉得让GPS和GSM在手上工作,而不是以某种方式取消其他方式,不可避免地会成为我的问题的终点 . 而且我认为它会降低到命令的位置

GPRS.println(“AT CGNSURC = 1”);和/或GPRS.println(“AT CGNSINF”);当前者在调用一次时连续吐出每个GNSS FIX的gps数据,而LATER每个命令只吐出一次 .

附图只显示了输出的连续性(“AT CGNSURC = 1”); ,就像(“AT CGNSINF”);用CGNSINF吐出一行:在开头而不是

2 回答

  • 0

    请检查是否存在溢出SRAM,这会在执行程序时产生异常情况 . 当您声明这么多变量时会发生这种情况,您可以使用此library来检查sram的使用 .

  • 0

    我遇到了类似的问题,试图通过串口从模块获取GPS数据,但经过艰苦的工作时间才发现它 . 基本上,您需要验证每个命令的每个响应,并在每次写入之前刷新串行端口 .

    在编写任何命令之前刷新串行端口缓冲区将确保在尝试获取刚刚运行的命令的输出时,不会意外地读取上一个命令中的剩余字符 . 大多数TA(终端适配器)使用像OK这样的EOL字符,转换为“\ r \ nOK \ r \ n” . 如果您不全部阅读它们,它们可能会徘徊并干扰您发送/读取响应的下一个命令 . 在发送命令之前,使用GPRS.flush()去除串行缓冲区中的额外垃圾字符 .

    此外,创建一个通用命令函数来传递所有AT命令并验证它们的输出将为您节省大量的睡眠 .

    就像是

    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)
    }
    

    我写这个是为了与a进行沟通simcom5320,但我没有使用软件序列,所以它会有点不同你 . 将此功能用于所有at命令,以确保所有实际成功如下:

    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
    }
    

    希望这可以帮助!

相关问题