Skip to content

Arduino UNO R4 WiFi UDP 通信示例文档 ​

1. 简介 ​

本示例演示如何使用 Arduino UNO R4 WiFi 通过 UDP 协议进行网络通信。UDP(User Datagram Protocol)是一种无连接的传输层协议,相比 TCP,它不保证数据可靠到达,但具有低延迟、高效率的特点,适合实时数据传输场景。

Arduino UNO R4 WiFi 采用双核架构——Renesas RA4M1(48 MHz Arm Cortex-M4) 负责运行主程序和外设控制,ESP32-S3 模块独立处理 WiFi 通信,网络通信不占用主控资源。UDP 协议已经过测试并完全兼容 UNO R4 WiFi。


2. UDP vs TCP:如何选择? ​

特性UDPTCP
连接方式无连接(发送即可)面向连接(需建立连接)
可靠性不保证到达可靠传输
数据顺序可能乱序按序到达
速度快较慢
适用场景实时数据流、传感器广播、控制指令需要确认接收的重要数据

提示:对于需要低延迟的实时控制(如无人机控制、传感器数据广播),UDP 是更合适的选择。如果数据不容丢失,可在应用层增加简单的确认机制。


3. 硬件准备 ​

部件说明
Arduino UNO R4 WiFi主控板
USB Type-C 数据线供电和程序下载
WiFi 网络2.4GHz 无线网络
PC / 手机用于测试 UDP 通信

4. 软件准备 ​

4.1 安装开发板支持包 ​

  1. 打开 Arduino IDE
  2. 点击 工具 → 开发板 → 开发板管理器
  3. 搜索 "Arduino UNO R4 WiFi",点击安装

4.2 核心库 ​

UNO R4 WiFi 使用 WiFiS3 库,UDP 通信需要包含 WiFiUdp.h:

cpp
#include <WiFiS3.h>
#include <WiFiUdp.h>

安装核心会自动安装 WiFiS3 库。


5. 示例 1:UDP 发送端(向 PC 发送数据) ​

以下代码实现 Arduino UNO R4 WiFi 作为 UDP 客户端,定期向 PC 端的 UDP 服务器发送数据。

5.1 完整代码 ​

cpp
#include <WiFiS3.h>
#include <WiFiUdp.h>

// ========== WiFi 配置 ==========
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";

// ========== UDP 配置 ==========
const char* remote_pc_ip = "192.168.1.100";  // 修改为 PC 的 IP 地址
const int remote_port = 50007;              // PC 端 UDP 接收端口
const int local_port = 50008;               // 本地监听端口(可选)

WiFiUDP Udp;
char sendBuffer[] = "0";

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  // 检查 WiFi 模块
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("WiFi 模块通信失败!");
    while (true);
  }

  // 连接 WiFi
  Serial.print("正在连接 WiFi: ");
  Serial.println(ssid);
  
  while (WiFi.begin(ssid, password) != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi 连接成功!");
  Serial.print("本机 IP 地址: ");
  Serial.println(WiFi.localIP());

  // 启动 UDP
  Udp.begin(local_port);
  Serial.print("UDP 已启动,本地端口: ");
  Serial.println(local_port);
}

void loop() {
  // 发送 UDP 数据包
  Udp.beginPacket(remote_pc_ip, remote_port);
  Udp.write(sendBuffer);
  Udp.endPacket();

  Serial.print("已发送: ");
  Serial.println(sendBuffer);

  // 自增发送的数据
  sendBuffer[0]++;

  delay(1000);
}

5.2 PC 端 Python UDP 服务器 ​

将以下 Python 代码保存为 udp_server.py,在 PC 上运行:

python
import socket

# 配置 UDP 服务器
host = '0.0.0.0'      # 监听所有网卡
port = 50007          # 端口号

# 创建 UDP Socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind((host, port))

print(f"UDP 服务器已启动,监听端口: {port}")

while True:
    data, address = server_socket.recvfrom(2048)
    try:
        data_str = data.decode('utf-8')
        print(f"收到来自 {address} 的数据: {data_str}")
    except:
        print(f"收到无法解码的数据: {data}")

6. 示例 2:UDP 接收端(接收并响应) ​

以下代码实现 Arduino UNO R4 WiFi 作为 UDP 服务器,接收来自客户端的 UDP 数据包,并回复确认消息。

cpp
#include <WiFiS3.h>
#include <WiFiUdp.h>

// ========== WiFi 配置 ==========
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";

// ========== UDP 配置 ==========
const int local_udp_port = 4210;              // 本地监听端口
char incoming_packet[255];                    // 接收数据缓冲
char reply_packet[] = "ACK: 收到消息!";      // 回复消息

WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  // 连接 WiFi(参考示例 1)
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi 连接成功!");
  Serial.print("本机 IP 地址: ");
  Serial.println(WiFi.localIP());

  // 启动 UDP 服务器
  Udp.begin(local_udp_port);
  Serial.print("UDP 服务器已启动,监听端口: ");
  Serial.println(local_udp_port);
}

void loop() {
  // 检查是否有 UDP 数据包到达
  int packet_size = Udp.parsePacket();
  
  if (packet_size) {
    // 获取发送方信息
    Serial.print("收到来自 ");
    Serial.print(Udp.remoteIP());
    Serial.print(",端口 ");
    Serial.print(Udp.remotePort());
    Serial.print(" 的数据包,大小: ");
    Serial.println(packet_size);

    // 读取数据
    int len = Udp.read(incoming_packet, sizeof(incoming_packet) - 1);
    if (len > 0) {
      incoming_packet[len] = '\0';  // 添加字符串结束符
    }
    
    Serial.print("数据内容: ");
    Serial.println(incoming_packet);

    // 回复确认消息(发送到发送方的 IP 和端口)
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(reply_packet);
    Udp.endPacket();
    
    Serial.println("已发送确认回复");
  }
}

7. 示例 3:两个 UNO R4 WiFi 之间 UDP 通信 ​

架构说明 ​

┌──────────────────┐         UDP 数据包        ┌──────────────────┐
│   UNO R4 WiFi    │  ──────────────────────► │   UNO R4 WiFi    │
│   (发送端)       │  192.168.1.101:1234    │   (接收端)       │
│  读取电位器      │  发送传感器数据           │  控制舵机        │
└──────────────────┘                          └──────────────────┘

7.1 发送端代码(读取电位器并发送) ​

cpp
#include <WiFiS3.h>
#include <WiFiUdp.h>

const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";
const char* receiver_ip = "192.168.1.101";  // 接收端的 IP 地址
const int udp_port = 1234;

WiFiUDP udp;
int potPin = A0;

void setup() {
  Serial.begin(115200);

  // 连接 WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi 已连接");
  Serial.print("发送端 IP: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  int potValue = analogRead(potPin);  // 读取电位器值 (0-1023)

  // 发送 UDP 数据
  udp.beginPacket(receiver_ip, udp_port);
  udp.print(potValue);
  udp.endPacket();

  Serial.print("已发送: ");
  Serial.println(potValue);

  delay(20);  // 低延迟传输
}

7.2 接收端代码(接收并控制舵机) ​

cpp
#include <WiFiS3.h>
#include <WiFiUdp.h>
#include <Servo.h>

const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";
const int udp_port = 1234;

WiFiUDP udp;
Servo servo;
const int servo_pin = 9;

char packet_buffer[8];
int pot_value = 0;
int servo_angle = 0;

void setup() {
  Serial.begin(115200);
  servo.attach(servo_pin);

  // 连接 WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi 已连接");
  Serial.print("接收端 IP: ");
  Serial.println(WiFi.localIP());

  // 启动 UDP 接收
  udp.begin(udp_port);
  Serial.print("UDP 监听端口: ");
  Serial.println(udp_port);
}

void loop() {
  int packet_size = udp.parsePacket();
  
  if (packet_size) {
    int len = udp.read(packet_buffer, sizeof(packet_buffer) - 1);
    if (len > 0) {
      packet_buffer[len] = '\0';
      pot_value = atoi(packet_buffer);  // 字符串转整数
      
      // 映射到舵机角度 (0-180度)
      servo_angle = map(pot_value, 0, 1023, 0, 180);
      servo.write(servo_angle);

      Serial.print("收到: ");
      Serial.print(pot_value);
      Serial.print(" → 舵机角度: ");
      Serial.println(servo_angle);
    }
  }
}

这个示例源自 Arduino 论坛中用户 ejwest 的 UDP 通信项目。


8. 测试工具 ​

工具平台用途
Packet SenderWindows/Linux/macOSUDP/TCP 数据包收发测试
Python socket全平台自定义 UDP 服务端/客户端
sokitWindows轻量级 UDP/TCP 测试工具
WireShark全平台网络抓包分析

9. 常见问题排查 ​

问题可能原因解决方法
WiFi 连接失败SSID/密码错误确认 WiFi 名称和密码,确保为 2.4GHz 网络
UDP 收不到数据端口未开放或 IP 地址错误确认目标 IP 和端口,检查防火墙
parsePacket() 返回 0无数据包到达检查发送端是否正常发送,网络是否连通
接收数据为乱码编码不一致统一使用 ASCII 或 UTF-8 编码
IP 地址显示 0.0.0.0WiFi 连接未完全建立检查连接状态,增加等待时间
编译错误 WiFiS3.h not found未安装 R4 支持包在开发板管理器中安装 "Arduino UNO R4 WiFi"

10. 进阶参考 ​

UDP 多播(Multicast) ​

UNO R4 WiFi 支持 UDP 多播,可实现一对多通信:

cpp
// 多播发送
udp.beginPacketMulticast(multicast_ip, port, WiFi.localIP());

// 多播接收
udp.beginMulticast(WiFi.localIP(), multicast_ip, port);

数据包结构传输 ​

对于复杂数据(如结构体),可使用 __attribute__((packed)) 确保数据对齐:

cpp
struct __attribute__((packed)) SensorData {
  byte nodeID;
  int16_t sequence;
  float temperature;
  float humidity;
};