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;
};