ESP8266-01与Arduino UNO使用SoftwareSerial通信异常问题排查
问题分析与修复方案
核心问题1:ESP8266的串口被混用导致调试信息泄露
你现在在ESP8266代码里用的Serial是它的硬件串口(对应GPIO1/TX和GPIO3/RX),这个串口同时承担了两个角色:
- 输出调试日志(比如
Serial.println("New Client.")) - 发送控制指令给Arduino Uno
所以所有通过Serial输出的内容都会被发送到Uno的接收端,这就是为什么你看到了"New Client."、"Client disconnected."这些非控制类消息。
核心问题2:Arduino Uno接收端的条件判断语法错误
你的接收端代码里,所有if判断用了赋值运算符=而不是比较运算符==:
if(IncomingString = "LED 1 ON") { ... }
这会把字符串"LED 1 ON"赋值给IncomingString,然后因为赋值操作返回的是被赋值的内容(非空字符串,布尔值为true),所以所有if分支都会被执行,这就是为什么你会看到所有LED的ON/OFF都被打印出来。
修复步骤
1. 修改ESP8266代码:分离调试串口与通信串口
我们给ESP8266和Uno之间的通信单独用一个模拟串口,调试信息保留在原来的硬件串口(用于你电脑监控ESP状态):
#include <ESP8266WiFi.h> #include <SoftwareSerial.h> // 引入软件串口库 // 定义ESP与Uno通信的软件串口(GPIO2=TX,GPIO4=RX,可根据你的接线调整) SoftwareSerial espToUno(2, 4); // Replace with your network credentials const char* ssid = "farzain_2"; const char* password = "1999fzyc"; WiFiServer server(80); String header; String output5State = "off"; String output4State = "off"; void setup() { Serial.begin(9600); // 硬件串口用于调试,连接电脑 espToUno.begin(9600); // 软件串口用于和Uno通信 Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); } void loop(){ WiFiClient client = server.available(); if (client) { Serial.println("New Client."); // 调试信息用硬件串口输出 String currentLine = ""; while (client.connected()) { if (client.available()) { char c = client.read(); header += c; if (c == '\n') { if (currentLine.length() == 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // 发送控制指令时用软件串口,而非硬件串口 if (header.indexOf("GET /5/on") >= 0) { Serial.println("GPIO 5 on"); // 调试信息 output5State = "on"; espToUno.println("LED 1 ON"); // 给Uno的指令 } else if (header.indexOf("GET /5/off") >= 0) { Serial.println("GPIO 5 off"); output5State = "off"; espToUno.println("LED 1 OFF"); } else if (header.indexOf("GET /4/on") >= 0) { Serial.println("GPIO 4 on"); output4State = "on"; espToUno.println("LED 2 ON"); } else if (header.indexOf("GET /4/off") >= 0) { Serial.println("GPIO 4 off"); output4State = "off"; espToUno.println("LED 2 OFF"); } // 以下HTML部分保留不变 client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}"); client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;"); client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".button2 {background-color: #77878A;}</style></head>"); client.println("<body><h1>ESP8266 Web Server</h1>"); client.println("<p>GPIO 5 - State " + output5State + "</p>"); if (output5State=="off") { client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>"); } else { client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>"); } client.println("<p>GPIO 4 - State " + output4State + "</p>"); if (output4State=="off") { client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>"); } else { client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>"); } client.println("</body></html>"); client.println(); break; } else { currentLine = ""; } } else if (c != '\r') { currentLine += c; } } } header = ""; client.stop(); Serial.println("Client disconnected."); // 调试信息 Serial.println(""); } }
2. 修改Arduino Uno接收端代码:修正条件判断并优化接收逻辑
#include <SoftwareSerial.h> SoftwareSerial mySerial(2,3); //RX, TX(注意:Uno的RX接ESP的软件串口TX,Uno的TX接ESP的软件串口RX) const int LED_ONE = 6; const int LED_TWO = 7; void setup(){ Serial.begin(9600); // 用于电脑监控Uno的状态 mySerial.begin(9600); pinMode(LED_ONE, OUTPUT); pinMode(LED_TWO, OUTPUT); } void loop(){ if(mySerial.available()){ String IncomingString = mySerial.readStringUntil('\n'); // 读取到换行符为止,避免超时问题 IncomingString.trim(); // 去掉字符串首尾的换行/空格等空白字符 Serial.print("From ESP = "); Serial.println(IncomingString); // 用==进行比较,而非=赋值 if(IncomingString == "LED 1 ON") { Serial.println("\nLED 1 ON\n"); digitalWrite(LED_ONE, HIGH); } else if(IncomingString == "LED 1 OFF") { // 用else if避免不必要的判断 Serial.println("\nLED 1 OFF\n"); digitalWrite(LED_ONE, LOW); } else if(IncomingString == "LED 2 ON") { Serial.println("\nLED 2 ON\n"); digitalWrite(LED_TWO, HIGH); } else if(IncomingString == "LED 2 OFF") { Serial.println("\nLED 2 OFF\n"); digitalWrite(LED_TWO, LOW); } } }
3. 接线注意事项
- ESP8266的软件串口TX(GPIO2) → Arduino Uno的SoftwareSerial RX(引脚2)
- ESP8266的软件串口RX(GPIO4) → Arduino Uno的SoftwareSerial TX(引脚3)
- 记得给ESP8266提供3.3V电源(不要接5V,会烧坏模块),并共地(ESP和Uno的GND连接在一起)
内容的提问来源于stack exchange,提问作者rendy ada




