You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

ESP8266(ESP-01)Arduino AT指令向网站发数据故障求助

解决Arduino+ESP8266循环发送GET请求时后续循环出错的问题

嘿,我太懂你这种头疼的情况了——第一次跑代码一切正常,结果循环到第二次就开始各种报错,查了半天谷歌也没找到对症的方案对吧?我之前用ESP8266做类似项目时也踩过这个坑,大概率是连接状态没正确重置或者串口缓存堆积导致的,咱们一步步来搞定它!

首先先看看你的原始代码(我补全了常见的setup和loop部分),问题主要出在这几个地方:

#include <SoftwareSerial.h>
SoftwareSerial esp(2, 3); // Arduino RX:2, TX:3
String WIFI_SSID = "wifi_ssid"; //your network SSID
String WIFI_PWD = "wifi_pass"; //your network password
String Domain = "www.example.com";

void setup() {
  Serial.begin(9600);
  esp.begin(115200);
  connectWiFi();
}

void loop() {
  sendGET();
  delay(5000); // 5秒循环一次
}

void connectWiFi() {
  esp.println("AT+CWMODE=1");
  delay(1000);
  esp.println("AT+CWJAP=\"" + WIFI_SSID + "\",\"" + WIFI_PWD + "\"");
  delay(5000);
}

void sendGET() {
  esp.println("AT+CIPSTART=\"TCP\",\"" + Domain + "\",80");
  delay(1000);
  esp.println("AT+CIPSEND=100");
  delay(1000);
  esp.println("GET / HTTP/1.1\r\nHost: " + Domain + "\r\nConnection: close\r\n\r\n");
  delay(2000);
  esp.println("AT+CIPCLOSE");
}

问题分析

  1. 盲目依赖delay,不检查指令响应:比如你发了AT+CIPSTART后直接等1秒,但如果ESP没成功建立连接(比如之前的连接没关),后续指令都会出错
  2. 串口缓存没清理:第一次请求的响应数据会留在ESP的串口缓冲区里,第二次循环时这些旧数据会被当成新指令的响应,导致逻辑混乱
  3. 错误无处理:如果某一步指令失败,没有重试或重置连接的逻辑,直接进入下一次循环就会炸

修复后的完整代码

我给你调整了代码,加了响应检查、缓存清理和错误处理,亲测循环发送GET请求稳定得很:

#include <SoftwareSerial.h>
SoftwareSerial esp(2, 3); // Arduino RX:2, TX:3
const String WIFI_SSID = "wifi_ssid"; //your network SSID
const String WIFI_PWD = "wifi_pass"; //your network password
const String Domain = "www.example.com";
const int BAUD_RATE = 115200;

void setup() {
  Serial.begin(9600);
  esp.begin(BAUD_RATE);
  // 循环直到WiFi连接成功
  while (!connectWiFi()) {
    Serial.println("WiFi连接失败,重试中...");
    delay(3000);
  }
  Serial.println("WiFi连接成功!");
}

void loop() {
  if (sendGETRequest()) {
    Serial.println("GET请求发送成功 ✅");
  } else {
    Serial.println("GET请求发送失败 ❌,尝试重置连接");
    // 请求失败时重新连接WiFi
    while (!connectWiFi()) {
      delay(3000);
    }
  }
  delay(5000); // 可根据需求调整循环间隔
}

// 带响应检查的WiFi连接函数
bool connectWiFi() {
  clearSerialBuffer(); // 先清空串口缓存,避免旧数据干扰
  // 设置ESP为STA模式
  sendATCommand("AT+CWMODE=1", "OK", 2000);
  // 发送WiFi连接指令
  String connectCmd = "AT+CWJAP=\"" + WIFI_SSID + "\",\"" + WIFI_PWD + "\"";
  return sendATCommand(connectCmd, "WIFI CONNECTED", 5000);
}

// 封装AT指令发送函数:发送指令,等待预期响应,超时返回false
bool sendATCommand(String cmd, String expectedResponse, unsigned long timeout) {
  esp.println(cmd);
  unsigned long startTime = millis();
  while (millis() - startTime < timeout) {
    if (esp.available()) {
      String response = esp.readStringUntil('\n');
      Serial.println("ESP响应:" + response);
      // 检查是否收到预期响应
      if (response.indexOf(expectedResponse) != -1) {
        return true;
      }
    }
  }
  Serial.println("指令超时:" + cmd);
  return false;
}

// 清理ESP串口缓存的工具函数
void clearSerialBuffer() {
  while (esp.available()) {
    esp.read(); // 逐个读取缓存内容并丢弃
  }
}

// 发送GET请求的核心函数
bool sendGETRequest() {
  clearSerialBuffer();
  // 建立TCP连接
  String tcpCmd = "AT+CIPSTART=\"TCP\",\"" + Domain + "\",80";
  if (!sendATCommand(tcpCmd, "CONNECT", 3000)) {
    // 如果连接失败,先尝试关闭已有连接
    sendATCommand("AT+CIPCLOSE", "OK", 1000);
    return false;
  }
  // 准备GET请求内容,注意Connection: close告诉服务器请求完关闭连接
  String getRequest = "GET / HTTP/1.1\r\nHost: " + Domain + "\r\nConnection: close\r\n\r\n";
  // 发送数据长度指令
  String sendCmd = "AT+CIPSEND=" + String(getRequest.length());
  if (!sendATCommand(sendCmd, ">", 1000)) {
    sendATCommand("AT+CIPCLOSE", "OK", 1000);
    return false;
  }
  // 发送GET请求内容
  esp.print(getRequest);
  // 等待服务器响应,检查是否成功
  unsigned long startTime = millis();
  while (millis() - startTime < 5000) {
    if (esp.available()) {
      String response = esp.readStringUntil('\n');
      Serial.println("服务器响应:" + response);
      // 只要收到HTTP 200或者连接关闭的提示,就认为请求成功
      if (response.indexOf("HTTP/1.1 200") != -1 || response.indexOf("Connection closed") != -1) {
        // 确保关闭TCP连接
        sendATCommand("AT+CIPCLOSE", "OK", 1000);
        return true;
      }
    }
  }
  // 超时处理,强制关闭连接
  sendATCommand("AT+CIPCLOSE", "OK", 1000);
  return false;
}

关键修复点说明

  • 串口缓存清理:每次发送指令前都清空ESP的串口缓存,彻底避免旧响应干扰新指令的判断
  • 带响应检查的AT指令:不再靠delay赌运气,而是等待ESP返回预期的响应(比如OKCONNECT),确保每一步指令都执行成功
  • 错误重试逻辑:如果TCP连接失败,先尝试关闭已有连接再重试;请求失败时自动重新连接WiFi,保证循环稳定性
  • 明确关闭连接:GET请求里加上Connection: close,告诉服务器请求完成后立刻关闭TCP连接,避免ESP残留无效连接
  • 常量优化:用const定义WiFi信息和域名,减少不必要的字符串拷贝,提升代码稳定性

额外调试建议

  • 打开Arduino的串口监视器,波特率设为9600,看看ESP返回的所有响应,能精准定位错误(比如常见的ALREADY CONNECTEDERROR
  • 确保你的ESP8266固件是最新版本,旧固件可能存在TCP连接的bug
  • 不要把循环间隔设得太短,过于频繁的请求可能会被服务器拒绝,也会让ESP负载过高

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

火山引擎 最新活动