极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13938|回复: 2

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

[复制链接]
发表于 2016-6-15 10:30:52 | 显示全部楼层 |阅读模式
最近用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=[0,1]
        index0 = recvString.indexOf("IOOF") + 4;
        recvdata = recvString.substring(index0, index0 + 8);
        digitalWrite(4, recvdata[0] - '0');
        digitalWrite(5, recvdata[1] - '0');
        digitalWrite(6, recvdata[2] - '0');
        digitalWrite(7, recvdata[3] - '0');
        digitalWrite(8, recvdata[4] - '0');
        digitalWrite(9, recvdata[5] - '0');
        digitalWrite(10, recvdata[6] - '0');
        digitalWrite(11, recvdata[7] - '0');
      }
      if (recvString.indexOf("IOOP") > -1) {                         //IOOPX,Y   X=[0,7] Y=[1,9]
        index0 = recvString.indexOf("IOOP") + 4;
        recvdata = recvString.substring(index0, index0 + 3);
        digitalWrite(recvdata[0] - '0' + 4, HIGH);
        delay((recvdata[2] - '0') * 1000);
        digitalWrite(recvdata[0] - '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;
  }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2016-6-16 22:01:23 | 显示全部楼层
求助~~有没有大神帮忙看下?
回复 支持 反对

使用道具 举报

发表于 2016-8-15 17:44:59 | 显示全部楼层
kaiserydl 发表于 2016-6-16 22:01
求助~~有没有大神帮忙看下?

用合方圆GU620直接GPRS+GPS二合一的测试秒杀
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 00:59 , Processed in 0.037067 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表