贝博恩创新科技网

Arduino Ethernet教程如何快速上手?

Arduino Ethernet 教程:从零开始打造你的网络设备

目录

  1. 准备工作
    • 硬件清单
    • 软件环境
  2. 硬件连接
    • W5100 模块连接
    • W5500 模块连接
  3. 核心库介绍
    • Ethernet 库
    • EthernetBonjour 库 (可选,用于 mDNS)
  4. 实践案例一:最简单的 Web 服务器
    • 代码解析
    • 访问你的 Arduino
  5. 实践案例二:动态 Web 服务器 - 读取模拟传感器
    • 代码解析
    • 效果展示
  6. 进阶主题:使用 DHCP 和静态 IP
  7. 常见问题与排查 (FAQ)
  8. 总结与拓展

准备工作

硬件清单

  1. 一块 Arduino 主板:推荐 Arduino UNO, Mega, Due 等,注意,一些较新的板子(如 Arduino Nano Every)可能需要不同的 SPI 引脚定义。
  2. Arduino Ethernet 扩展板:这是最简单的方式,直接插在 Arduino 上,引脚已对齐。
    • W5100 模块:经典、常见、价格便宜。
    • W5500 模块:性能更强,速度更快,是 W5100 的升级版,推荐新项目使用。
  3. 以太网线:一根标准的 CAT5/CAT6 网线。
  4. 路由器:用于将 Arduino 连接到你的局域网。
  5. (可选) 模拟传感器:如光敏电阻、温湿度传感器等,用于案例二。

软件环境

  1. Arduino IDE:确保你安装了最新版本的 Arduino IDE。
  2. 驱动程序:如果你的 Arduino 是通过 USB 连接的,通常无需额外驱动(Windows 10/11 和 macOS 通常能自动识别)。

硬件连接

使用 Arduino Ethernet 扩展板(最简单)

这是最推荐给初学者的方式,将扩展板直接插在 Arduino 的引脚排上即可,SPI 通信(SCK, MISO, MOSI, SS)和电源引脚都会自动连接。

Arduino Ethernet教程如何快速上手?-图1
(图片来源网络,侵删)

使用独立的 W5100/W5500 模块

如果你的模块是独立的“面包板友好”型,你需要手动连接引脚。

W5100/W5500 模块引脚 Arduino UNO 引脚 功能说明
VCC 5V 电源正极
GND GND 电源地
SCK D13 SPI 时钟
MISO D12 SPI 主机输入,从机输出
MOSI D11 SPI 主机输出,从机输入
SS (or CS) D10 SPI 片选,用于选择 Ethernet 模块
INT (不接) 中断引脚,可选

注意

  • Mega 板:SPI 引脚不同(SCK=52, MISO=50, MOSI=51, SS=10 或 53)。
  • Due 板:SPI 引脚也不同(SCK=76, MISO=75, MOSI=74, SS=10)。
  • CS (SS) 引脚:你可以在代码中更改,但必须确保与硬件连接一致,并且不要与其他使用 SPI 的设备冲突。

核心库介绍

Arduino 的网络功能主要通过 Ethernet 库实现。

Ethernet 库

这是最核心的库,提供了所有网络功能,包括:

Arduino Ethernet教程如何快速上手?-图2
(图片来源网络,侵删)
  • Ethernet.begin(): 初始化以太网连接,可以配置为使用 DHCP(自动获取IP)或静态 IP。
  • Ethernet.localIP(): 获取 Arduino 分配到的 IP 地址。
  • Ethernet.server(): 创建一个 TCP 服务器(用于 Web 服务器)。
  • EthernetClient client: 代表一个客户端连接,用于与服务器通信。

EthernetBonjour 库 (可选)

这个库用于实现 mDNS (Multicast DNS) 功能,有了它,你就不需要记忆 Arduino 的 IP 地址,而是可以通过一个友好的主机名(如 arduino.local)来访问它,非常方便。


实践案例一:最简单的 Web 服务器

这个案例将让你的 Arduino 在网络上创建一个简单的网页,访问该 IP 地址即可看到 "Hello from Arduino!"。

代码

#include <SPI.h>
#include <Ethernet.h>
// --- 网络设置 ---
// 如果你使用 DHCP,注释掉下面的 IP 地址
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC 地址,可以任意设置,但局域网内不能重复
IPAddress ip(192, 168, 1, 177); // 设置一个静态 IP 地址,需要符合你的路由器网段
// IPAddress myDns(192, 168, 1, 1); // DNS 服务器地址
// IPAddress gateway(192, 168, 1, 1); // 网关地址
// IPAddress subnet(255, 255, 255, 0); // 子网掩码
// 创建一个服务器,监听 80 端口(HTTP 的默认端口)
EthernetServer server(80);
void setup() {
  // 初始化串口通信,用于调试
  Serial.begin(9600);
  while (!Serial) {
    ; // 等待串口连接,仅适用于 Leonardo 类型的板子
  }
  // 启动以太网连接
  // Ethernet.begin(mac, ip, myDns, gateway, subnet); // 使用静态 IP
  Ethernet.begin(mac); // 使用 DHCP,自动获取 IP
  // 检查 Ethernet 模块是否成功初始化
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet 模块未找到!");
    while (true) {
      delay(1); // 没有硬件,就停在这里
    }
  }
  // 检查是否通过 DHCP 获取到 IP 地址
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("以太网线未连接!");
  }
  // 启动服务器
  server.begin();
  // 打印 Arduino 的 IP 地址
  Serial.print("服务器地址是: ");
  Serial.println(Ethernet.localIP());
}
void loop() {
  // 监听是否有客户端连接
  EthernetClient client = server.available();
  if (client) {
    Serial.println("新的客户端连接");
    bool currentLineIsBlank = true;
    // 读取客户端数据,直到收到换行符
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // 当收到换行符并且上一行也是空白行时,说明 HTTP 请求头已结束
        if (c == '\n' && currentLineIsBlank) {
          // 发送 HTTP 响应头
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close"); // 告诉浏览器连接完成后关闭
          client.println();
          // 发送 HTML 内容
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<head><title>Arduino Web Server</title></head>");
          client.println("<body style='font-family: Arial;'>");
          client.println("<h1>Hello from Arduino!</h1>");
          client.println("<p>这是一个由 Arduino 控制的简单网页。</p>");
          client.println("</body>");
          client.println("</html>");
          break;
        }
        // 如果收到了换行符,设置标志位为 true
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        // 如果收到了回车符,设置标志位为 false
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    // 等待浏览器接收数据
    delay(1);
    // 断开与客户端的连接
    client.stop();
    Serial.println("客户端断开连接");
  }
}

代码解析

  1. 包含库:引入 SPIEthernet 库。
  2. 网络配置
    • mac[]: MAC 地址,每个网络设备唯一的物理地址,你可以随便设置,但确保在局域网内唯一。
    • ip: 静态 IP 地址,你需要将此地址设置在你路由器所在的网段内,如果你的路由器 IP 是 168.1.1,那么你可以设置 168.1.100168.1.254 之间的任意一个未被占用的地址。
    • Ethernet.begin(mac): 使用 DHCP 自动获取 IP,这更方便,但 IP 地址可能会变。
  3. 初始化
    • Serial.begin(9600): 启动串口,用于在 Arduino IDE 的串口监视器中打印信息,方便调试。
    • Ethernet.begin(...): 初始化以太网模块。
    • server.begin(): 启动 TCP 服务器,开始在 80 端口监听请求。
  4. 主循环
    • server.available(): 检查是否有新的客户端尝试连接。
    • client.read(): 读取客户端发送过来的 HTTP 请求数据("GET / HTTP/1.1")。
    • client.println(...): 向客户端发送 HTTP 响应,这是构建网页的关键。
    • HTTP 响应头:告诉浏览器服务器返回的是什么类型的内容(Content-Type: text/html),以及状态码(200 OK 表示成功)。
    • HTML 内容:响应头之后,就可以直接发送 HTML 代码了,浏览器会将其渲染成网页。
    • client.stop(): 请求处理完毕后,关闭连接,以便下一个客户端可以接入。

如何访问你的 Arduino

  1. 将 Arduino 和路由器用网线连接好。
  2. 上传代码后,打开 Arduino IDE 的 工具 -> 串口监视器,你会看到打印出的 IP 地址,服务器地址是: 192.168.1.177
  3. 在电脑或手机的浏览器中,输入这个 IP 地址(http://192.168.1.177),你应该就能看到 "Hello from Arduino!" 的网页了。

实践案例二:动态 Web 服务器 - 读取模拟传感器

这个案例将读取 Arduino 上连接的模拟传感器(A0 口的光敏电阻),并将实时数据显示在网页上。

硬件准备

  • 一个光敏电阻
  • 一个 10kΩ 的电阻
  • 面包板和杜邦线

连接方式

Arduino Ethernet教程如何快速上手?-图3
(图片来源网络,侵删)
  • 光敏电阻一端接 5V
  • 光敏电阻另一端接 A0 口和 10kΩ 电阻的一端。
  • 10kΩ 电阻的另一端接 GND
  • 这样就构成了一个分压电路,光线越强,A0 口的电压越高,读数值越大。

代码

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 178);
EthernetServer server(80);
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("服务器地址是: ");
  Serial.println(Ethernet.localIP());
}
void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("新的客户端连接");
    bool currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {
          // 发送 HTTP 响应头
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println();
          // 发送 HTML 内容,并嵌入传感器数据
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          client.println("<head><title>Arduino Sensor Data</title></head>");
          client.println("<body style='font-family: Arial;'>");
          client.println("<h1>传感器实时数据</h1>");
          // 读取模拟传感器值 (0-1023)
          int sensorValue = analogRead(A0);
          client.print("<p>光敏传感器读数: ");
          client.print(sensorValue);
          client.println("</p>");
          // 根据读数给出一个简单的描述
          client.print("<p>环境光: ");
          if (sensorValue < 200) {
            client.print("很暗");
          } else if (sensorValue < 500) {
            client.print("较暗");
          } else if (sensorValue < 800) {
            client.print("明亮");
          } else {
            client.print("非常亮");
          }
          client.println("</p>");
          client.println("<script>setTimeout(function(){location.reload();}, 2000);</script>");
          client.println("</body>");
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("客户端断开连接");
  }
}

代码解析

  • int sensorValue = analogRead(A0);: 读取 A0 口的模拟值,范围是 0 到 1023。
  • client.print(...): 使用 print 而不是 println 来输出数字和文本,避免产生不必要的换行。
  • 自动刷新<script>setTimeout(function(){location.reload();}, 2000);</script> 是一小段 JavaScript 代码,它会让网页在 2 秒后自动刷新,从而实现数据的实时更新。

效果展示

上传代码后,访问你的 Arduino IP 地址,你会看到一个显示光敏电阻读数的网页,这个网页会每 2 秒自动刷新一次,显示最新的数据。


进阶主题:使用 DHCP 和静态 IP

使用 DHCP(推荐)

在上面的案例中,如果你想使用 DHCP(让路由器自动分配 IP),只需修改 setup() 函数:

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac); // 只传入 MAC 地址,即可使用 DHCP
  server.begin();
  Serial.print("服务器地址是: ");
  Serial.println(Ethernet.localIP()); // 打印获取到的 IP
}

优点:配置简单,IP 地址不会冲突。 缺点:Arduino 的 IP 地址可能会在重启后改变,不方便长期访问。

使用静态 IP

如果你希望 Arduino 拥有一个固定的、不变的 IP 地址,方便通过 IP 访问或进行其他网络配置,就应该使用静态 IP。

void setup() {
  Serial.begin(9600);
  // 定义网络参数
  IPAddress ip(192, 168, 1, 178);
  IPAddress myDns(192, 168, 1, 1); // 通常和网关一样
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
  server.begin();
  Serial.print("服务器地址是: ");
  Serial.println(Ethernet.localIP());
}

优点:IP 地址固定,方便访问和管理。 缺点:需要确保你设置的 IP 没有被网络上的其他设备占用。


常见问题与排查

  1. 问题Ethernet 模块未找到!initialization failed, retrying...

    • 原因
      • 硬件连接错误,特别是 SPI 引脚(SCK, MISO, MOSI, CS)或电源。
      • 以太网模块损坏。
      • Arduino 的 SPI 引脚被其他设备占用。
    • 解决:仔细检查接线,确保 5VGND 连接正确,CS 引脚与代码中的一致。
  2. 问题以太网线未连接!

    • 原因:网线没有插好,或者网线/路由器端口有问题。
    • 解决:重新插拔网线,尝试换一个路由器端口,或换一根网线。
  3. 问题:浏览器无法访问 Arduino 的 IP 地址。

    • 原因
      • Arduino 和电脑不在同一个局域网(一个连 WiFi,一个插网线)。
      • 防火墙阻止了访问。
      • IP 地址设置错误(不在路由器网段内)。
      • 服务器没有正确启动。
    • 解决
      • 确保电脑和 Arduino 连接到同一个路由器下。
      • 暂时关闭电脑的防火墙。
      • 检查 IP 地址设置,可以通过串口监视器查看 Ethernet.localIP() 打印出的真实地址。
      • 检查 server.begin() 是否被调用。
  4. 问题错乱或无法加载。

    • 原因:HTTP 协议响应格式不正确,例如缺少了空行(client.println();)。
    • 解决:仔细检查 HTTP 响应头和正文之间的空行,确保 Content-Type 设置正确(通常是 text/html)。

总结与拓展

恭喜!你已经掌握了使用 Arduino Ethernet 模块创建 Web 服务器的核心技能。

拓展方向

  1. 控制 GPIO:在网页上添加按钮,通过点击按钮来控制 Arduino 的数字引脚,从而点亮 LED 或继电器。
  2. RESTful API:创建一个简单的 API,http://192.168.1.178/led/onhttp://192.168.1.178/led/off,让你的其他设备(如手机 App、ESP32)可以通过 HTTP 请求来控制 Arduino。
  3. MQTT 协议:对于更复杂的物联网项目,MQTT 是一个更轻量、更高效的通信协议,你可以将 Arduino 作为 MQTT 客户端,将传感器数据发布到 Broker(如 Mosquitto),或者订阅主题来接收控制命令。
  4. 使用 mDNS:集成 EthernetBonjour 库,你就可以通过 http://arduino.local 来访问设备,无需关心复杂的 IP 地址,体验更佳。

希望这份详细的教程能帮助你顺利开启 Arduino 网络开发之旅!

分享:
扫描分享到社交APP
上一篇
下一篇