Arduino UNO以太网直连笔记本发送POST请求失败求助
问题排查:Arduino以太网直连电脑通信失败
我在大学学期项目中制作小型温室原型,使用Arduino UNO采集传感器数据,需发送至本地电脑localhost:8080的服务器。传感器数据采集功能已验证正常,现计划通过带W5100核心的Ethernet Shield,仅用网线经Type-C hub直连电脑建立单向通信,但连接失败。不想使用路由器,请求协助排查代码问题。
运行代码(已翻译注释)
// 导入外部库 #include "DHT.h" #include "ArduinoJson.h" #include <SPI.h> #include <Ethernet.h> // 定义引脚 #define DHTPIN 2 #define DHTTYPE DHT11 #define LDRPIN A0 #define SOIL_MOISTUREPIN A1 #define WATER_LEVELPIN A2 #define RELAY1_PIN 8 // 定义变量 const unsigned long routineHttpSendInterval = 10000; // 定时发送间隔(10秒) unsigned long previousTime = 0; const float temperatureThresholdValue = 20.0; // 温度阈值 const float lightAmountThresholdValue = 35.0; // 光照阈值 // 初始化DHT传感器 DHT dht(DHTPIN, DHTTYPE); byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // Arduino MAC地址 IPAddress server(127, 0, 0, 1); // 目标服务器IP EthernetClient client; void setup() { // 初始化以太网 Ethernet.begin(mac); pinMode(13, OUTPUT); digitalWrite(13, LOW); Serial.begin(9600); // 开启串口调试 dht.begin(); // 初始化DHT传感器 pinMode(RELAY1_PIN, OUTPUT); digitalWrite(RELAY1_PIN, LOW); // 修正:原代码错误写入OUTPUT,改为电平状态 } void loop() { unsigned long currentTime = millis(); // 读取传感器数据 float humidity = readHumidity(); float celcius = readTemperatureCelcius(); float fahrenheit = readTemperatureFahrenheit(); float lightLevel = readLightLevel(); float soilMoisture = readSoilMoisture(); float waterLevel = readWaterLevel(); // 构造JSON数据 StaticJsonDocument<200> jsonDocument; jsonDocument["humidity"] = humidity; jsonDocument["temperatureAsC"] = celcius; jsonDocument["temperatureAsF"] = fahrenheit; jsonDocument["lightAmount"] = lightLevel; jsonDocument["soilMoisture"] = soilMoisture; jsonDocument["waterLevel"] = waterLevel; // 定时发送数据 if (currentTime - previousTime >= routineHttpSendInterval) { jsonDocument["operationType"] = 0; char jsonBuffer[512]; serializeJson(jsonDocument, jsonBuffer); if (client.connect(server, 8080)) { // 尝试连接服务器 client.println("POST /greenhouse/save HTTP/1.1"); client.println("Host: 127.0.0.1:8080/api"); // Host头错误 client.println("Content-Type: application/json"); client.print("Content-Length: "); client.println(strlen(jsonBuffer)); client.println(); client.println(jsonBuffer); } else { Serial.println("连接失败!"); } previousTime = currentTime; } // 温度低于阈值时启动加热(待实现) if (readTemperatureCelcius() <= temperatureThresholdValue) { /* 发送opcode=1的数据并启动加热器 */ } // 光照不足时开启灯光(待实现) if (readLightLevel() <= lightAmountThresholdValue) { /* 发送opcode=2的数据并开启灯光 */ } delay(5000); } // 读取湿度 float readHumidity() { float humidity = dht.readHumidity(); if (!isnan(humidity)) { Serial.print("湿度 %: "); Serial.println(humidity); return humidity; } else { Serial.println("读取DHT湿度失败!"); return NAN; } } // 读取摄氏温度 float readTemperatureCelcius() { float celcius = dht.readTemperature(); if (!isnan(celcius)) { Serial.print("温度 °C: "); Serial.println(celcius); return celcius; } else { Serial.println("读取DHT摄氏温度失败!"); return NAN; } } // 读取华氏温度 float readTemperatureFahrenheit() { float fahrenheit = dht.readTemperature(true); // 直接读取华氏温度 if (!isnan(fahrenheit)) { Serial.print("温度 °F: "); Serial.println(fahrenheit); return fahrenheit; } else { Serial.println("读取DHT华氏温度失败!"); return NAN; } } // 读取光照强度 float readLightLevel() { float lightLevel = (analogRead(LDRPIN) / 1023.0) * 100; Serial.print("光照强度 %: "); Serial.println(lightLevel); return lightLevel; } // 读取土壤湿度 float readSoilMoisture() { float soilMoisture = (analogRead(SOIL_MOISTUREPIN) / 1023.0) * 100; Serial.print("土壤湿度 %: "); Serial.println(soilMoisture); return soilMoisture; } // 读取水位 float readWaterLevel() { float waterLevel = (analogRead(WATER_LEVELPIN) / 1023.0) * 100; Serial.print("水位 %: "); Serial.println(waterLevel); return waterLevel; }
核心问题排查与修复方案
1. 本地回环地址错误
IPAddress server(127, 0, 0, 1) 是Arduino自身的回环地址,不是电脑的IP。直连场景下,必须给Arduino和电脑分配同网段静态IP:
- 示例:Arduino设为
192.168.1.100,电脑Type-C网卡设为192.168.1.101,子网掩码统一为255.255.255.0
2. 以太网初始化缺失静态配置
直连无DHCP服务器,Ethernet.begin(mac)会获取不到IP,必须手动指定网络参数:
IPAddress ip(192, 168, 1, 100); // Arduino静态IP IPAddress subnet(255, 255, 255, 0); // 子网掩码 IPAddress gateway(192, 168, 1, 101); // 网关设为电脑IP Ethernet.begin(mac, ip, gateway, gateway, subnet);
同时在setup()中添加串口打印,确认IP配置生效:
Serial.print("Arduino IP: "); Serial.println(Ethernet.localIP());
3. HTTP请求Host头错误
代码中Host: 127.0.0.1:8080/api格式错误,Host只需包含服务器IP和端口,路径已在POST行中指定:
client.println("Host: 192.168.1.101:8080"); // 替换为电脑静态IP
4. 未关闭客户端连接
发送数据后必须调用client.stop()释放连接,否则后续连接会被占用:
if (client.connect(server, 8080)) { // ...发送HTTP请求代码... client.stop(); // 发送完成后关闭连接 }
5. 电脑端网络配置检查
- 电脑Type-C网卡设置与Arduino同网段的静态IP
- 关闭电脑防火墙(或手动允许8080端口入站)
- 确认服务器程序监听
0.0.0.0:8080(而非仅127.0.0.1,否则无法接收外部设备连接)
6. 代码其他小问题修正
- 原代码
digitalWrite(RELAY1_PIN, OUTPUT)错误,应改为LOW或HIGH电平状态 readTemperatureFahrenheit()原逻辑冗余,直接调用dht.readTemperature(true)即可获取华氏温度
内容的提问来源于stack exchange,提问作者canercin
相关产品推荐
相关产品推荐

