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 withAT+CIPSEND. But the+2is for an extra\r\nyou add at the end, which shouldn't be part of the POST payload. This creates a mismatch between theContent-Lengthheader (set toretazec_len) and the actual data sent, which servers often reject. - When converting
retazectoretazwithtoCharArray(retaz,70), if your form data exceeds 69 characters (sincetoCharArrayreserves space for a null terminator), it gets truncated. This again causes aContent-Lengthmismatch.
Fix:
- Remove the extra
Serial1.print("\r\n");after sending form data — the POST request only needs\r\n\r\nto separate headers from data. - Use a buffer large enough for your form data: replace
char retaz[70];with a dynamic size likechar retaz[retazec_len + 1];(the+1accounts for the null terminator). - Calculate
sizeascmd.length() + retazec_len(sincecmdalready includes the required\r\n\r\nafter 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 (likeSEND FAILorALREADY 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

