Arduino +ESP8266 发送 POST 一次但每隔一次就失败

Arduino +ESP8266 sending POST once but fails every other time

我将 esp8266 与我的 arduino Mega 一起使用,并使用 AT 命令通过串行控制它(我知道这不是使用 ESP 的最佳方式,但我不知道如何使用其他方式)。 ..所以我的问题是我制定了我的 POST 请求并发送到我的网页....第一次尝试时它工作正常,但之后,在每次循环尝试中,它都失败了......请可以有人检查我的代码,看看您是否能找到可能导致此问题的错误?

这是我发送数据的函数:

void SendData(){



cmd = "AT+CIPSTART=\"TCP\",\"";
cmd+= server;
cmd+="\",80";
Serial1.println(cmd);
Serial.println(cmd);
delay(1000);
 if(Serial1.find("OK"))
  {
    Serial.println("\r\nReady to send data!");
  }



String retazec="cz="+cas_zaznamu; ////DATA from sensors etc.
retazec=retazec+"&tep="+t;
retazec=retazec+"&vlhv="+vv;
retazec=retazec+"&vlhp="+vp;
retazec=retazec+"&zav="+za;
retazec=retazec+"&kur="+ku;
retazec=retazec+"&vet="+ve;
retazec=retazec+"&pz="+datum_zavlaha;

int retazec_len=retazec.length();
retazec.toCharArray(retaz,70);

cmd = "POST /arduino.php"; ////POST request 
cmd+=" HTTP/1.1\r\n";
cmd+="Host: myhost.com\r\n";
cmd+="Content-Type: application/x-www-form-urlencoded\r\n";
cmd+="Connection:Close\r\n";
cmd+="Content-Length: ";
cmd+=retazec_len;
cmd+="\r\n\r\n";

int size=cmd.length()+retazec_len+2;

Serial1.print("AT+CIPSEND=");
Serial1.println(size);
Serial.print("AT+CIPSEND=");
Serial.println(size);
delay(2000);
if (Serial1.find(">")){
  Serial.println("Sending data...");
} else {
  Serial1.println("AT+CIPCLOSE");
  Serial.println("COnnection closed");
  return;
}
Serial.print(cmd);
Serial1.print(cmd);
for(int i=0;i<=retazec_len;i++){
    Serial.print(retaz[i]);
    Serial1.print(retaz[i]);
  }
 Serial1.print("\r\n");

if(Serial1.find("OK"))
    {
      Serial.println("Succesfuly send!");
    }


ReadString(); /// emptying the buffer by reading serial1
delay(5000); 
Serial.println("-----end");

}

此外,我对 GET 请求有不同的功能,与上面的非常相似,并且连续多次工作(不想说每次 bcs 它只 运行 几分钟) .

如有任何建议,我们将不胜感激。 :)

我受过教育的 guess:The String class 结合 at 命令
尝试在基于 web 的场景中摆脱 String class。原因:您想长期拥有一个稳定的环境运行。 String class 使用堆内存来动态构建和销毁它所需的底层结构,例如追加字符串(... = .. + .. + ..)。由于没有所谓的垃圾收集(并且无论如何都没有足够的内存),相对较小的内存被切成小单元,其中(在一定长度上)字符串不再适合 -> 崩溃,重置 => 丢失 POST 或 GET 请求。
使用固定的全局字符数组来构建您的消息,这些消息被编译到闪存中并停止 "memory bleeding"。
附上示例 (虽然我不明白 - 从你的语言 - 变量的名称或内容并且没有给出我不得不猜测的类型)

char retazec[256] = {'[=10=]'}; /* Defined globally - Used for retazec functions max 255 chars */
char cmd[512] = {'[=10=]'}; /* Defined globally - Used for POST/GET functions max 511 chars */
char numBuffer[16] = {'[=10=]'}; /* Defined globally - Used for uint32_t or smaller number conversions to char */
unsigned long timeStamp = 0;
unsigned long delayTime = 2000;

setup(){...}

//The parts you gave "translated"into char manuipulation
const char* cmdStart[] = "POST /arduino.php HTTP/1.1\r\n Host: myhost.com\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection:Close\r\nContent-Length: ";
const char* cmdEnd[] = "\r\n\r\n";  


strcpy (retazec, "cz=");
itoa(cas_zaznamu, numBuffer, 10); // convert int DATA from sensors etc.
// If its a float use this command
// dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
// dtostrf(cas_zaznamu, 3, 2, numBuffer); // -> xx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&tep=");
itoa(t, numBuffer, 10);
// or dtostrf(t, 4, 2, numBuffer); // -> xxx.xx
strcat(retazec, numBuffer);
strcat(retazec, "&vlhv=");
....
// ... till datum_zavlaha;

int retazec_len=strlen(retazec); // gives you the length
 // not needed we have a char array allready retazec.toCharArray(retaz,70);

strcpy(cmd, cmdStart);
iota (retazec_len, numBuffer);
strcat(cmd, numBuffer);
strcat(cmd, cmdEnd);

int size=strlen(cmd)+retazec_len+2;
if (millis() - timeStamp > delayTime) {
    Serial1.print("AT+CIPSEND=");
    Serial1.println(size);
    Serial.print("AT+CIPSEND=");
    Serial.println(size);
    timeStamp = millis();
}
// NO NEVER delay(2000);
if (Serial1.find(">")){
   Serial.println("Sending data...");
} else {
   Serial1.println("AT+CIPCLOSE");
   Serial.println("COnnection closed");
   return;
}

第二个问题是延迟(它停止处理死在它的轨道上)所以 cpu 在你的情况下等待 2 秒然后重新启动 - 在使用通信协议时不是一个聪明的主意。我实现了一个非阻塞延迟——如果你在其他地方需要它,正如我所说,你只提供了代码片段
编辑 OP 反馈后
在动态通信场景中应避免将字符串 class 作为一个整体,因此在程序的所有部分。
我是否应该使用一个大字符串(小 s = char 数组)来应对原始代码的作用但不是带有 char 数组的 String。
所以恕我直言,结构只需要适应 char 数组而无需大的更改(除了明确地将数字转换为 char)顺便说一句,当您将变量添加到 String

uint8_t aNumber = 12;
String myBigString = "A number is " + aNumber;

在字符串库内部与

相同
uint8_t aNumber = 12;
char numBuffer [16] = {'[=12=]'} ;
char myBigString [32] = {'[=12=]'} ;  
strcpy (myBigString, "A number is ");
iota (aNumber, numBuffer, 10);
strcat (myBigString, numBuffer);

不同之处在于 - 您编写代码行而不是懒洋洋地使用错误的库,但可以完全控制内存以及将其编译为闪存的优势,从而节省内存。 Const char 实际上是通过指针调用的——所以稍后有一些函数可以只获取数组的某些部分,以便从一个大数组中创建变量消息。
在对 github 进行代码分析后,有另一个大问题:阻塞延迟()的使用:

loop() {
   delay(1000);

   // lot of code

   delay(3000);
}

替换为非阻塞延迟 无符号长时间戳 = 0;

setup(){}

loop() {
  if (millis() - timeStamp > 4000) {

   // lot of code
   timeStamp = millis(); // reset the timer
   }
}

并如前所述删除所有字符串(例如)

///////////PREMENNE PRIJIMANÝCH ÚDAJOV///////
String mode;
String inzavlaha;
String inkurenie;
String invetranie;
String invlhkost_p;
String invlhkost_v;
String incas;
String intrvanie;
String inopakovanie;
String inteplota;

最后 tio.If 如果您需要全球范围的帮助,请开始用英语编写您的所有程序(变量和注释),这样更容易获得帮助。