Appearance
Arduino UNO R4 WiFi TCP 通信示例文档
1. 简介
本示例演示如何使用 Arduino UNO R4 WiFi 通过 TCP 协议进行网络通信。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输层协议,保证数据完整有序地到达目的地,适合需要高可靠性的数据传输场景。
Arduino UNO R4 WiFi 采用双核架构——Renesas RA4M1(48 MHz Arm Cortex-M4) 负责运行主程序和外设控制,ESP32-S3 模块独立处理 WiFi 通信,网络通信不占用主控资源。
2. TCP vs UDP:如何选择?
| 特性 | TCP | UDP |
|---|---|---|
| 连接方式 | 面向连接(需建立连接) | 无连接 |
| 可靠性 | 可靠传输,保证数据到达 | 不保证到达 |
| 数据顺序 | 按序到达 | 可能乱序 |
| 适用场景 | 需要可靠通信的控制指令、状态上报 | 实时数据流、广播信息 |
提示:对于需要确认指令执行结果的控制场景,推荐使用 TCP;对于传感器数据上报这类实时性要求高但允许偶尔丢包的场景,UDP 更轻量高效。
3. 硬件准备
| 部件 | 说明 |
|---|---|
| Arduino UNO R4 WiFi | 主控板 |
| LM35 / 传感器(可选) | 数据采集 |
| USB Type-C 数据线 | 供电和程序下载 |
| WiFi 网络 | 2.4GHz 无线网络 |
| PC 端 TCP 服务端软件 | 测试用(如 ezTerm、netcat、Putty) |
4. 软件准备
4.1 安装开发板支持包
- 打开 Arduino IDE
- 点击 工具 → 开发板 → 开发板管理器
- 搜索 "Arduino UNO R4 WiFi",点击安装
4.2 核心库
UNO R4 WiFi 使用 WiFiS3 库(与旧版 UNO WiFi 的 WiFiNINA 不同,请注意区分):
cpp
#include <WiFiS3.h>5. 示例 1:TCP 客户端(向服务器发送数据)
以下代码实现 Arduino 作为 TCP 客户端,连接到 PC 端的 TCP 服务器,并发送数据。
5.1 完整代码
cpp
#include <WiFiS3.h>
// ========== WiFi 配置 ==========
const char* WIFI_SSID = "你的WiFi名称"; // 修改为实际 WiFi SSID
const char* WIFI_PASSWORD = "你的WiFi密码"; // 修改为实际 WiFi 密码
// ========== TCP 服务器配置 ==========
const char* TCP_SERVER_ADDR = "192.168.1.100"; // 修改为服务器 IP 地址
const int TCP_SERVER_PORT = 1470; // 修改为服务器端口
WiFiClient tcpClient;
void setup() {
Serial.begin(9600);
while (!Serial) delay(10);
Serial.println("=== Arduino UNO R4 WiFi TCP Client ===");
// 检查 WiFi 模块状态
if (WiFi.status() == WL_NO_MODULE) {
Serial.println("WiFi 模块通信失败!");
while (true);
}
// 检查固件版本
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
Serial.println("请升级 WiFi 固件");
}
// ----- 连接 WiFi -----
Serial.print("正在连接 WiFi: ");
Serial.println(WIFI_SSID);
while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
delay(10000);
}
Serial.print("WiFi 连接成功! IP 地址: ");
Serial.println(WiFi.localIP());
// ----- 连接 TCP 服务器 -----
Serial.print("正在连接 TCP 服务器: ");
Serial.print(TCP_SERVER_ADDR);
Serial.print(":");
Serial.println(TCP_SERVER_PORT);
if (tcpClient.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
Serial.println("TCP 服务器连接成功!");
tcpClient.println("Hello from Arduino UNO R4 WiFi!");
} else {
Serial.println("TCP 服务器连接失败!");
}
}
void loop() {
// ----- 接收服务器数据并打印到串口 -----
if (tcpClient.available()) {
char c = tcpClient.read();
Serial.print(c);
}
// ----- 检查连接状态,断开则尝试重连 -----
if (!tcpClient.connected()) {
Serial.println("连接已断开,尝试重连...");
tcpClient.stop();
if (tcpClient.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
Serial.println("重新连接成功!");
tcpClient.println("Reconnected!");
} else {
Serial.println("重新连接失败,等待 1 秒后重试...");
delay(1000);
}
}
}5.2 PC 端 TCP 服务器测试
方法一:使用 netcat(Linux/macOS)
bash
# 在终端中监听端口 1470
nc -l 1470方法二:使用 Windows 端 TCP 服务器软件
- 下载并运行
ezTerm或其他 TCP 服务器软件 - 配置为 TCP Server 模式,监听端口 1470
- 点击 Listen 按钮
方法三:使用 Python 快速启动 TCP 服务器
python
# server.py
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 1470))
server.listen(1)
print("监听端口 1470...")
conn, addr = server.accept()
print(f"客户端已连接: {addr}")
while True:
data = conn.recv(1024)
if not data:
break
print(f"收到: {data.decode()}")
conn.send(b"ACK: " + data)6. 示例 2:双向通信(串口 ↔ TCP 透传)
以下代码将 Arduino 的串口数据转发到 TCP 服务器,并将 TCP 服务器返回的数据转发到串口,实现双向透传。
cpp
#include <WiFiS3.h>
// ========== WiFi 配置 ==========
const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PASSWORD = "你的WiFi密码";
// ========== TCP 服务器配置 ==========
const char* TCP_SERVER_ADDR = "192.168.1.100";
const int TCP_SERVER_PORT = 1470;
WiFiClient tcpClient;
void setup() {
Serial.begin(9600);
while (!Serial) delay(10);
Serial.println("=== Serial ↔ TCP Bridge ===");
// 连接 WiFi
while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
Serial.print(".");
delay(10000);
}
Serial.println("\nWiFi 已连接!IP: " + WiFi.localIP().toString());
// 连接 TCP 服务器
if (tcpClient.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
Serial.println("TCP 服务器已连接");
} else {
Serial.println("TCP 服务器连接失败");
}
}
void loop() {
if (tcpClient.connected()) {
// ----- TCP → 串口 -----
if (tcpClient.available()) {
char c = tcpClient.read();
Serial.write(c); // 转发到串口
}
// ----- 串口 → TCP -----
if (Serial.available()) {
char c = Serial.read();
tcpClient.write(c); // 转发到 TCP 服务器
}
} else {
// 断线重连
Serial.println("TCP 连接断开,尝试重连...");
tcpClient.stop();
delay(1000);
if (tcpClient.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
Serial.println("重新连接成功!");
}
}
}7. 示例 3:两个 UNO R4 WiFi 之间通过 TCP 通信
架构说明
┌──────────────────┐ TCP 连接 ┌──────────────────┐
│ UNO R4 WiFi │ ──────────────────────► │ UNO R4 WiFi │
│ (TCP Server) │ 192.168.1.101:1470 │ (TCP Client) │
│ 传感器采集 │ 发送传感器数据 │ 接收并处理 │
└──────────────────┘ └──────────────────┘7.1 TCP 服务器端(数据发布方)
cpp
#include <WiFiS3.h>
const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PASSWORD = "你的WiFi密码";
const int TCP_PORT = 1470;
WiFiServer server(TCP_PORT);
WiFiClient client;
void setup() {
Serial.begin(9600);
while (!Serial) delay(10);
// 连接 WiFi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
}
Serial.println("WiFi 已连接!IP: " + WiFi.localIP().toString());
// 启动 TCP 服务器
server.begin();
Serial.print("TCP 服务器已启动,端口: ");
Serial.println(TCP_PORT);
}
void loop() {
// 等待客户端连接
client = server.available();
if (client) {
Serial.println("客户端已连接!");
while (client.connected()) {
// 模拟读取传感器数据
float temperature = 25.0 + random(-10, 10) * 0.1;
float humidity = 60.0 + random(-15, 15) * 0.1;
// 格式:温度,湿度
String data = String(temperature, 1) + "," + String(humidity, 1);
// 发送数据到客户端
client.println(data);
Serial.print("已发送: ");
Serial.println(data);
delay(2000); // 每 2 秒发送一次
}
client.stop();
Serial.println("客户端已断开");
}
}7.2 TCP 客户端(数据接收方)
cpp
#include <WiFiS3.h>
const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PASSWORD = "你的WiFi密码";
const char* TCP_SERVER_ADDR = "192.168.1.101"; // 服务器端的 IP
const int TCP_SERVER_PORT = 1470;
WiFiClient tcpClient;
void setup() {
Serial.begin(9600);
while (!Serial) delay(10);
// 连接 WiFi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
}
Serial.println("WiFi 已连接!IP: " + WiFi.localIP().toString());
// 连接 TCP 服务器
connectToServer();
}
void connectToServer() {
if (tcpClient.connect(TCP_SERVER_ADDR, TCP_SERVER_PORT)) {
Serial.println("已连接到 TCP 服务器!");
} else {
Serial.println("连接服务器失败,5 秒后重试...");
delay(5000);
connectToServer();
}
}
void loop() {
if (tcpClient.connected()) {
// 接收服务器数据
if (tcpClient.available()) {
String data = tcpClient.readStringUntil('\n');
data.trim();
Serial.print("收到数据: ");
Serial.println(data);
// 解析数据:温度,湿度
int commaIndex = data.indexOf(',');
if (commaIndex > 0) {
String temp = data.substring(0, commaIndex);
String humi = data.substring(commaIndex + 1);
Serial.print(" 温度: ");
Serial.print(temp);
Serial.print("°C, 湿度: ");
Serial.print(humi);
Serial.println("%");
}
}
} else {
Serial.println("服务器连接断开,尝试重连...");
tcpClient.stop();
delay(5000);
connectToServer();
}
}8. 常用测试工具
| 工具 | 平台 | 用途 |
|---|---|---|
netcat (nc) | Linux/macOS/Windows | 命令行 TCP 测试 |
ezTerm | Windows | 图形化 TCP 服务器/客户端 |
| Putty | 全平台 | 串口和 TCP 连接测试 |
Python socket | 全平台 | 自定义 TCP 服务端测试脚本 |
9. 常见问题排查
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| WiFi 连接失败 | SSID/密码错误 | 确认 WiFi 名称和密码,确保为 2.4GHz 网络 |
| TCP 连接失败 | 服务器 IP/端口错误 | 确认服务器 IP 和端口,检查防火墙 |
| 连接后立即断开 | 服务器端主动关闭 | 检查服务器端程序是否保持监听 |
| 数据接收乱码 | 编码不一致 | 统一使用 ASCII 或 UTF-8 编码 |
| 长时间运行后无响应 | 连接超时 | 增加心跳包或重连机制 |
编译错误 WiFiS3.h not found | 未安装 R4 支持包 | 在开发板管理器中安装 "Arduino UNO R4 WiFi" |
10. 进阶参考
- Web Server 模式:UNO R4 WiFi 可以作为 Web 服务器,通过浏览器 HTTP 请求控制设备
- 固件升级:通过 工具 → 固件更新器 更新 ESP32-S3 模块固件
- 更多示例:在 Arduino IDE 中打开 文件 → 示例 → WiFiS3 查看官方示例程序