Arduino Uno搭配SIM900、GPS向000webhost传数据AT+CIPSEND报错
SIM900执行AT+CIPSEND报错无法上传GPS数据到000webhost故障排查
问题描述
- 硬件方案:采用Arduino Uno作为主控,搭配SIM900 GSM模块、GPS模块实现GPS定位数据上传至000webhost服务器
- 运行状态:GSM模块初始化流程无报错,GPS模块可正常获取经纬度信息
- 故障现象:执行服务器数据发送操作时
AT+CIPSEND指令返回错误,数据无法成功上传
原故障代码
void setup() { Serial.begin(9600); SIM900.begin(9600); delay(100); Serial.println("Initializing..."); delay(1000); SIM900.println("AT"); updateSerial(); SIM900.println("AT+CPIN?"); updateSerial(); SIM900.println("AT+CREG?"); updateSerial(); SIM900.println("AT+COPS?"); updateSerial(); SIM900.println("AT+CGATT?"); updateSerial(); SIM900.println("AT+CIPSHUT"); updateSerial(); SIM900.println("AT+CIPMUX=0"); updateSerial(); SIM900.println("AT+CGATT?"); updateSerial(); SIM900.println("AT+CSTT=\"airtelgprs.com\""); updateSerial(); SIM900.println("AT+CIICR"); delay(2000); updateSerial(); SIM900.println("AT+CIFSR"); updateSerial(); SIM900.println("AT+CIPSPRT=0"); delay(3000); updateSerial(); SIM900.println("AT+CIPSTART=\"TCP\",\"xxxxx.000webhostapp.com\",\"80\""); delay(3000); updateSerial(); Serial.begin(9600); gpsSerial.begin(9600); } void updateSerial() { delay(500); while (Serial.available()) { SIM900.write(Serial.read()); } while(SIM900.available()) { Serial.write(SIM900.read()); } } void loop() { while(1) { while (gpsSerial.available() > 0) { gps.encode(gpsSerial.read()); } if (gps.location.isUpdated()) { latitude=gps.location.lat(); longitude=gps.location.lng(); break; } } Serial.println("LATITUDE=" + String(latitude,6)); Serial.println("LONGITUDE=" + String(longitude,6)); delay(1000); SIM900.println("AT+CIPSEND"); delay(10000); updateSerial(); String str="GET /coba.php?latitude=" + String(latitude) + "&longitude=" +String(longitude); Serial.println(str); SIM900.println(str); updateSerial(); SIM900.println(" HTTP/1.1\r\n"); delay(4000); updateSerial(); SIM900.println("Host: xxxx.000webhostapp.com"); updateSerial(); SIM900.println((char)26); delay(5000); SIM900.println(); updateSerial(); SIM900.println("AT+CIPSHUT"); delay(100); }
故障原因
- TCP连接状态无校验
代码发送AT+CIPSTART后仅固定延时3秒就进入发送流程,未判断模块是否返回CONNECT OK确认连接建立。如果出现域名解析失败、GPRS网络附着失败、TCP握手失败的情况,连接根本没建立,此时发送AT+CIPSEND必然返回错误。另外代码中硬编码的APN为airtelgprs.com,如果使用的不是Airtel运营商的SIM卡,APN配置错误会直接导致无法联网。 - AT指令时序逻辑错误
发送AT+CIPSEND后未等待模块返回>发送提示符,直接延时10秒就开始发数据;且将HTTP请求拆分为多段发送,中间穿插串口转发和不必要的延时,SIM900进入透传模式后会将所有收到的内容作为数据发送,中途插入的逻辑会直接打乱发送流程。 - HTTP请求格式不合法
代码将GET请求路径和HTTP版本拆分为两次发送,中间多了不必要的换行,且请求末尾缺少HTTP协议规定的空行,000webhost服务器无法识别这种畸形请求,会直接断开连接。 - 基础代码逻辑问题
setup()末尾重复调用Serial.begin(9600),可能打乱串口缓冲区状态;未补全gps、gpsSerial的对象定义;每次发送完数据直接执行AT+CIPSHUT关闭连接,下一次loop循环没有重新建立TCP连接的逻辑,第二次运行必然发送失败。 - 服务端限制问题
000webhost免费版默认拦截请求头不全、无合法User-Agent的请求,且目前多数节点默认强制HTTPS跳转,80端口的HTTP请求会被直接拦截,而SIM900本身不支持SSL/TLS,无法直接连接443端口的HTTPS服务。
修复方案
- 所有AT指令发送后必须等待返回结果,校验成功后再执行下一步,不要靠固定延时凑时序:
- 发送
AT+CIPSTART后必须等待返回CONNECT OK再执行后续操作,如果返回错误则重新走GPRS附着、TCP连接流程 - 发送
AT+CIPSEND后必须等待模块返回>提示符,再一次性发送所有请求数据,最后发送(char)26作为发送结束符
- 发送
- 替换APN为当前所用SIM卡对应的接入点,不要硬抄其他运营商的配置
- 提前拼接完整的合法HTTP请求,不要拆分发送,参考格式:
String httpReq = "GET /coba.php?latitude=" + String(latitude,6) + "&longitude=" + String(longitude,6) + " HTTP/1.1\r\n"; httpReq += "Host: xxxx.000webhostapp.com\r\n"; httpReq += "User-Agent: SIM900-GPS/1.0\r\n"; httpReq += "Connection: close\r\n\r\n";
- 删除setup()中重复的
Serial.begin(9600)代码,提前定义GPS相关对象和软串口引脚 - 登录000webhost后台关闭站点的强制HTTPS跳转,确保80端口可正常访问HTTP服务;如果无法关闭,更换支持SSL功能的GSM模块(如SIM800C SSL版本)
内容的提问来源于stack exchange,提问作者Nana
相关产品推荐
相关产品推荐

