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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:28:22