kaiserydl 发表于 2016-6-15 10:30:52

Arduino UNO+QUECTEL M26基于GPRS进行远程控制,程序不稳定,跪求帮助!

最近用ArduinoUNO和QUECTEL M26做了个GPRS远程控制模块,现在模块跟服务器建立TCP连接,每隔5秒上报一次I/O口状态给服务器,并且可以根据服务器给他的指令对I/O口进行操作,M26模块的指令集都上传在附件里。现在的问题是,差不多跑一个礼拜,程序就挂了,不再上传数据到服务器,服务器也无法控制模块了,TCP连接就断开了,是不是我重启的代码写的不对?搞不明白,请大神帮我看一下代码,谢谢~
下面是代码:

//程序检测4~19脚数据并上传服务器   上传格式为id+时间+IO口状态

String inputString = "";         // a string to hold incoming data
String recvdata;
String rtime;
String orderID="";
unsigned long recvTime = 0;
unsigned long sendTime = 0;
unsigned long delayTime = 0;
int index = -1;
int index0 = -1;
int index1=-1;
int index2=-1;
int GPRSStep = 0;                                           //初始化GPRS模块步骤
int TCPStep = 0;                                          //TCP连接步骤
int SENDStep = 0;                                           //发送数据步骤
int timestep = 0;                                           //获取时间
bool response=false;

void connGPRS()                                             //初始化GPRS模块的函数
{
if (GPRSStep == 0)                                          //测试AT指令
{
    index = inputString.indexOf("AT\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT\r\n");
    }
}
else if (GPRSStep == 1)                                                   //第二步,重置模块,确保复位等操作可以正常运行
{
    index = inputString.indexOf("AT+QPOWD=1\r\r\nNORMAL POWER DOWN \r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+QPOWD=1\r\n");
    }
}
else if (GPRSStep == 2)                                                    //重置之后,再确认AT指令可以运行
{
    index = inputString.indexOf("AT\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT\r\n");
    }
}
else if (GPRSStep == 3)                                                         //查询网络注册状态,确保GPRS可用
{
    index = inputString.indexOf("AT+CGREG?\r\r\n+CGREG: 0,1\r\n\r\nOK\r\n");      //0,1代表本地网
    if (index == -1)
    {
      index = inputString.indexOf("AT+CGREG?\r\r\n+CGREG: 0,5\r\n\r\nOK\r\n");    //0,5代表漫游
    }
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+CGREG?\r\n");
    }
}
else if (GPRSStep == 4)                                                   //同步RTC时间
{
    index = inputString.indexOf("AT+CTZU=3\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+CTZU=3\r\n");
    }
}
else if (GPRSStep == 5)                                                   //同步网络时间并上报
{
    index = inputString.indexOf("AT+QNITZ=1\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+QNITZ=1\r\n");
    }
}
else if (GPRSStep == 6)                                                       //接收数据时显示IP头
{
    index = inputString.indexOf("AT+QIHEAD=1\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+QIHEAD=1\r\n");
    }
}
else if (GPRSStep == 7)                                             //AT+QISEND时不允许数据回显
{
    index = inputString.indexOf("AT+QISDE=0\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+QISDE=0\r\n");
    }
}
else if (GPRSStep == 8)                                             //设置上传到域名服务器
{
    index = inputString.indexOf("AT+QIDNSIP=1\r\r\nOK\r\n");
    if (index > -1)
    {
      GPRSStep++;
    }
    else
    {
      inputString = "";
      Serial.print("AT+QIDNSIP=1\r\n");
    }
}
}

void connTCP(String ip, String port)                            //连接TCP服务器的函数
{
if (TCPStep == 0)
{
    String tstr = "AT+QIOPEN=\"TCP\",\"";                           //AT+QIOPEN="TCP","
    String tstr2 = "\",";                                             //",
    String tstr3 = "\r\n";
    String t = tstr + ip + tstr2 + port + tstr3;

    inputString = "";
    Serial.print(t);
    TCPStep++;
    delayTime = millis();                                             //系统运行时间,单位毫秒
}
else if (TCPStep == 1)
{
    if (millis() - delayTime >= 10000)                                  //设置连接超时时间,超时了就重新连接
    {
      TCPStep = 0;
    }
    else
    {
      index = inputString.indexOf("CONNECT OK\r\n");         //TCP连接成功
      if (index > -1)
      {
      TCPStep++;
      }
    }
}
}

void sendStr(String str, int len)                           //发送字符串的函数
{
String tmp1 = (String)len;                               //强制转换
if (SENDStep == 0)
{
    inputString = "";
    Serial.print("AT+QISEND=");
    Serial.print(tmp1);                                  //指定长度发送
    Serial.print("\r\n");
    SENDStep++;
}
else if (SENDStep == 1)
{
    index = inputString.indexOf("> ");
    if (index > -1)
    {
      inputString = "";
      Serial.print(str);                           //发送字符串str
      SENDStep++;
    }
}
else if (SENDStep == 2)
{
    index = inputString.indexOf("SEND OK");            //发送成功
    if (index > -1)
    {
      SENDStep++;
    }
}
}
String recv()                                       //读取输入数据的函数,返回值是String型
{
int index = -1, index2 = -1;
index = inputString.indexOf("IPD");                  //接收数据时,显示IP头,格式为"IPD(data length):XXXXXXX"
index2 = inputString.indexOf(":");
int len = 0;
String lenStr;
lenStr.reserve(5);                                    //设置为:lenStr的字符串容量至少是5
if (index > -1)
{
    if (index2 > index)
    {
      index += 3;                                                       //跳过了IPD这三个字符
      lenStr = inputString.substring(index, index2);                  //截取字符串,从IPD后一位到:(包含IPD后一位,不包含:),该字符串是输入字符串的长度
      len = lenStr.toInt();                                             //把刚获得的字符串转换成INT型!!就获得了输入字符串的长度,INT型
      if (inputString.length() >= index2 + len)
      {
      return inputString.substring(index2 + 1, index2 + len + 1);   //index2+1,是跳过了:,这样截取的就是正确的输入的字符串
      }
    }
}
return "";                        //否则返回空
}
String retime()                                       //读取实时时间的函数
{
if (timestep == 0) {
    index = inputString.indexOf("+CCLK:");
    if (index > -1)
    {
      timestep++;
      return inputString.substring(index + 8, index + 25);               //截取时间
    }
    else
    {
      inputString = "";
      Serial.print("AT+CCLK?\r\n");
      return"";
    }
}
}
void setup() {
for (int i = 4; i < 12; i++) {                               //4~11脚为输出脚,初始化是0
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
}
for (int i = 12; i < 20; i++) {                           //12~19脚为输入脚,内部上拉
    pinMode(i, INPUT_PULLUP);
}
inputString.reserve(200);                              //初始化inputstring的容量至少是200
Serial.begin(115200);                                 //波特率115200!
}

void loop() {
if (GPRSStep < 9)
{
    connGPRS();                      //初始化设置GPRS模块
    delay(200);
}
else if (TCPStep < 2)
{
    connTCP("test.glotrol.com", "23000");            //设置上传服务器
    SENDStep = 0;
    sendTime = 0;
    recvTime = 0;
    timestep = 0;
}
else
{
    String recvString = recv();
    if ( recvString.startsWith("$%%") && recvString.endsWith("#*")) {                //$%%IOOP2,5,-1233(32位指令ID)#*
      index1=recvString.indexOf(",-")+2;
      index2=recvString.indexOf("#*");
      orderID=recvString.substring(index1, index2);
      if (recvString.indexOf("IOOF") > -1) {                        //IOOFXXXXXXXX    X=
      index0 = recvString.indexOf("IOOF") + 4;
      recvdata = recvString.substring(index0, index0 + 8);
      digitalWrite(4, recvdata - '0');
      digitalWrite(5, recvdata - '0');
      digitalWrite(6, recvdata - '0');
      digitalWrite(7, recvdata - '0');
      digitalWrite(8, recvdata - '0');
      digitalWrite(9, recvdata - '0');
      digitalWrite(10, recvdata - '0');
      digitalWrite(11, recvdata - '0');
      }
      if (recvString.indexOf("IOOP") > -1) {                         //IOOPX,Y   X= Y=
      index0 = recvString.indexOf("IOOP") + 4;
      recvdata = recvString.substring(index0, index0 + 3);
      digitalWrite(recvdata - '0' + 4, HIGH);
      delay((recvdata - '0') * 1000);
      digitalWrite(recvdata - '0' + 4, LOW);
      }
      response=true;
      }   
    if (SENDStep < 3)
    {
      if(response==true)
      {
         if (SENDStep == 0)
      {
          sendTime = millis();
      }
      sendStr(orderID+"OK", 34);
         if (millis() - sendTime > 60000)            //发送数据超时,重发
      {
          GPRSStep=0;
          TCPStep = 0;
          SENDStep=0;
          timestep = 0;
      }
      }
      else if (timestep < 1) {
      rtime = retime();                                        //读取当前时间
      delay(200);
      }
      else {
      String sid = "$00000001";                                       //模块ID,独一无二
      String sbuf = "";                                             //存储IO口数据
      String uploaddata = "";
      if (SENDStep == 0)
      {
          sendTime = millis();
      }
      for (int i = 4; i < 20; i++)                                       //读取4~19脚的数据,并存入sbuf
      {
          if (digitalRead(i) == HIGH)
          {
            sbuf += "1";
          }
          else
          {
            sbuf += "0";
          }
      }
      uploaddata = sid + rtime + sbuf + "#";
      sendStr(uploaddata, 43);                        //发送数据给服务器,注意字符串长度!!(这步完成之后SENDStep=3)
      if (millis() - sendTime > 60000)            //发送数据超时,重发
      {
          GPRSStep=0;
          TCPStep = 0;
          SENDStep=0;
          timestep = 0;
      }
      }
    }
    else
    {
      if (millis() - sendTime > 5000)            //5秒之后再次发送
      {
      SENDStep = 0;
      timestep = 0;
      }
      if(response==true)
      {
      response=false;
      }
    }
}
}
void serialEvent() {
while (Serial.available()) {
    char inChar = (char)Serial.read();                  //每当串口缓存区有数据,就读取数据
    delay(2);
    inputString += inChar;
}
}

kaiserydl 发表于 2016-6-16 22:01:23

求助~~有没有大神帮忙看下?

shaobaov9 发表于 2016-8-15 17:44:59

kaiserydl 发表于 2016-6-16 22:01 static/image/common/back.gif
求助~~有没有大神帮忙看下?

用合方圆GU620直接GPRS+GPS二合一的测试秒杀
页: [1]
查看完整版本: Arduino UNO+QUECTEL M26基于GPRS进行远程控制,程序不稳定,跪求帮助!