Appearance
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:如何选择?
| 特性 | UDP | TCP |
|---|---|---|
| 连接方式 | 无连接(发送即可) | 面向连接(需建立连接) |
| 可靠性 | 不保证到达 | 可靠传输 |
| 数据顺序 | 可能乱序 | 按序到达 |
| 速度 | 快 | 较慢 |
| 适用场景 | 实时数据流、传感器广播、控制指令 | 需要确认接收的重要数据 |
提示:对于需要低延迟的实时控制(如无人机控制、传感器数据广播),UDP 是更合适的选择。如果数据不容丢失,可在应用层增加简单的确认机制。
3. 硬件准备
| 部件 | 说明 |
|---|---|
| Arduino UNO R4 WiFi | 主控板 |
| USB Type-C 数据线 | 供电和程序下载 |
| WiFi 网络 | 2.4GHz 无线网络 |
| PC / 手机 | 用于测试 UDP 通信 |
4. 软件准备
4.1 安装开发板支持包
- 打开 Arduino IDE
- 点击 工具 → 开发板 → 开发板管理器
- 搜索 "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 Sender | Windows/Linux/macOS | UDP/TCP 数据包收发测试 |
| Python socket | 全平台 | 自定义 UDP 服务端/客户端 |
| sokit | Windows | 轻量级 UDP/TCP 测试工具 |
| WireShark | 全平台 | 网络抓包分析 |
9. 常见问题排查
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| WiFi 连接失败 | SSID/密码错误 | 确认 WiFi 名称和密码,确保为 2.4GHz 网络 |
| UDP 收不到数据 | 端口未开放或 IP 地址错误 | 确认目标 IP 和端口,检查防火墙 |
parsePacket() 返回 0 | 无数据包到达 | 检查发送端是否正常发送,网络是否连通 |
| 接收数据为乱码 | 编码不一致 | 统一使用 ASCII 或 UTF-8 编码 |
| IP 地址显示 0.0.0.0 | WiFi 连接未完全建立 | 检查连接状态,增加等待时间 |
编译错误 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;
};