You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino Mega+ESP8266串口AT指令POST请求仅首次成功后续失败求助

Hey there! Let's dig into why your POST request works once but fails on subsequent attempts. I've gone through your SendData() function and spotted several potential issues that could be causing this behavior, especially compared to your working GET request.

1. Unclean TCP Connection Handling

Your code only closes the connection if it fails to get the > prompt when sending data, but it doesn't explicitly close the connection after a successful send. The Connection: Close header tells the server to close the connection, but the ESP8266 might still hold the connection open on its end until you send AT+CIPCLOSE. If you try to start a new TCP connection with AT+CIPSTART without closing the old one, the ESP will return an error (like ALREADY CONNECTED), which your code doesn't handle.

Fix: Add an explicit AT+CIPCLOSE at the start and end of your function to ensure no residual connections are left.

2. Incorrect Content-Length & Data Sending

Looking at your code:

  • You calculate size = cmd.length() + retazec_len + 2, then send that with AT+CIPSEND. But the +2 is for an extra \r\n you add at the end, which shouldn't be part of the POST payload. This creates a mismatch between the Content-Length header (set to retazec_len) and the actual data sent, which servers often reject.
  • When converting retazec to retaz with toCharArray(retaz,70), if your form data exceeds 69 characters (since toCharArray reserves space for a null terminator), it gets truncated. This again causes a Content-Length mismatch.

Fix:

  • Remove the extra Serial1.print("\r\n"); after sending form data — the POST request only needs \r\n\r\n to separate headers from data.
  • Use a buffer large enough for your form data: replace char retaz[70]; with a dynamic size like char retaz[retazec_len + 1]; (the +1 accounts for the null terminator).
  • Calculate size as cmd.length() + retazec_len (since cmd already includes the required \r\n\r\n after headers).

3. Reliance on Fixed Delays Instead of Timeout Checks

Using delay(1000) and delay(2000) is risky because network latency can make the ESP8266's response time vary. If the ESP takes longer than the delay to send OK or >, your Serial1.find() will fail, leading to incorrect error handling.

Fix: Use the timeout parameter for Serial1.find() (e.g., Serial1.find("OK", 5000) to wait up to 5 seconds) instead of fixed delays.

4. Incomplete Buffer Clearing

Your ReadString() function is supposed to empty the Serial1 buffer, but if it doesn't read all remaining bytes, leftover data from previous responses can interfere with subsequent find() checks. For example, leftover server responses might make Serial1.find("OK") pick up old data instead of the new connection's confirmation.

Fix: Replace ReadString() with explicit buffer clearing at the start of SendData():

while(Serial1.available()) {
  Serial1.read(); // Clear any leftover bytes from previous interactions
}

5. Missing Error Handling for AT+CIPSTART

Your code checks if Serial1.find("OK") after AT+CIPSTART, but if it fails, it still proceeds to build and send the POST request anyway. This means you're trying to send data over a failed connection, which will never work.

Fix: Add a return statement if AT+CIPSTART fails to exit the function early.

Modified SendData() Function Example

Here's how your function could look with all these fixes applied:

void SendData(){
  // Clear leftover bytes in Serial1 buffer first
  while(Serial1.available()) {
    Serial1.read();
  }

  // Close any existing connection before starting a new one
  Serial1.println("AT+CIPCLOSE");
  delay(500); // Short delay to let ESP process the command
  while(Serial1.available()) {
    Serial1.read(); // Clear response to CIPCLOSE
  }

  // Start TCP connection
  cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd+= server;
  cmd+="\",80";
  Serial1.println(cmd);
  Serial.println(cmd);

  // Wait for OK with 5-second timeout
  if(!Serial1.find("OK", 5000)) {
    Serial.println("\r\nFailed to connect to server!");
    return;
  }
  Serial.println("\r\nReady to send data!");

  // Build form data
  String retazec = "cz="+cas_zaznamu;
  retazec += "&tep="+t;
  retazec += "&vlhv="+vv;
  retazec += "&vlhp="+vp;
  retazec += "&zav="+za;
  retazec += "&kur="+ku;
  retazec += "&vet="+ve;
  retazec += "&pz="+datum_zavlaha;
  int retazec_len = retazec.length();

  // Use a buffer sized to fit the form data
  char retaz[retazec_len + 1];
  retazec.toCharArray(retaz, retazec_len + 1);

  // Build POST request headers
  cmd = "POST /arduino.php 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";

  // Calculate total bytes to send: headers + form data
  int size = cmd.length() + retazec_len;
  Serial1.print("AT+CIPSEND=");
  Serial1.println(size);
  Serial.print("AT+CIPSEND=");
  Serial.println(size);

  // Wait for > prompt with 5-second timeout
  if(!Serial1.find(">", 5000)) {
    Serial.println("Failed to get send prompt! Closing connection.");
    Serial1.println("AT+CIPCLOSE");
    return;
  }
  Serial.println("Sending data...");

  // Send the full request
  Serial.print(cmd);
  Serial1.print(cmd);
  Serial.print(retaz);
  Serial1.print(retaz);

  // Wait for OK response with timeout
  if(Serial1.find("OK", 5000)) {
    Serial.println("Successfully sent!");
  } else {
    Serial.println("Failed to send data!");
  }

  // Clear remaining response data
  while(Serial1.available()) {
    Serial1.read();
  }

  // Explicitly close the connection
  Serial1.println("AT+CIPCLOSE");
  Serial.println("Connection closed");
  delay(500);
  Serial.println("-----end");
}

Additional Troubleshooting Tips

  • Print every byte received from Serial1 to debug: instead of just checking for OK, add a loop to print all incoming data. This will show you exact errors from the ESP (like SEND FAIL or ALREADY CONNECTED) that are causing subsequent failures.
  • Test your POST request structure with a tool like Postman first to confirm it works with your server, then replicate that exact structure in your code.
  • Ensure your sensor variables (cas_zaznamu, t, etc.) don't contain unexpected characters (like newlines or spaces) that could break the form data format.

内容的提问来源于stack exchange,提问作者user7828716

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 06:53:16