第11周:个人作业 - 双节点手势控制智能网络系统
本周小组作业主要任务是:设计并实现一个能够进行分布式通信的网络系统,探索多节点之间的信息交互与协作。通过搭建有线或无线的网络结构,实现节点间的数据传输与同步控制,提升对网络通信原理和实际应用的理解。小组成员需协作完成系统的设计、节点的搭建以及网络协议的实现,最终实现多节点之间的信息共享与联动。
本周的小组作业见:https://fabacademy.org/2025/labs/chaihuo/docs/week11/chaihuo/week11_group_assignment/
1. 项目介绍
本周个人项目的主要目标是:设计、构建和连接具有网络或总线地址的有线或无线节点,并实现本地输入/输出设备的控制。基于我之前的手势传感器控制风扇和LED项目和最终项目构想,我决定创建一个双节点智能网络系统,实现两个设备间的手势控制同步(最终项目的智能走马灯,多个走马灯之间可以通过无线同步动作,就是在任意走马灯做手势,所有走马灯都会响应)。
项目具体目标包括:
- 构建两个相同的节点,每个节点包含 XIAO ESP32C3 扩展板和 APDS-9960 手势传感器
- 实现节点间的无线通信,使两个节点能够相互发送和接收控制指令
- 设计一个通信协议,确保任一节点检测到的手势都能同步控制两个节点的 LED
- 创建直观的用户反馈机制,展示网络连接状态和控制同步情况
2. 材料与设备
硬件组件
- 2 块 XIAO ESP32C3 开发板(自制)
- 2 个 APDS-9960 手势传感器模块
- 连接线/杜邦线
- USB 数据线(2根)
- 电源适配器(5V/2A,2个)
第 8 周我通过嘉立创制作了 5 块 XIAO 扩展板 PCB,之前的课程只用了 1 块,这次课程我又焊接了 1 块的元件,第 2 次焊这个 PCB 感觉容易了很多,一次点亮。
为第 2 块 PCB 焊接元器件,这次顺利很多,一次点亮
为了方便区分,新焊接的的板子 6 颗 LED,我安装了 5 颗红色 LED(之前使用的是蓝色 LED) 。
为了便于区分,新焊的 PCB 上我使用了红色的 LED
另外,记得为 XIAO ESP32C3 安装天线,因为我们在下面的工作需要使用其 Wi-Fi 功能。
记得为 XIAO ESP32C3 安装天线
安装天线的时候稍微用点力下压,直到天线牢固的卡在基座上。
用点力下压,直到天线牢固的卡在基座上
软件工具
- Arduino IDE
- XLOT_APDS9960AD 库(用于手势传感器)
- WiFiManager 库(用于 Wi-Fi连接管理)
- ArduinoJson 库(用于结构化消息处理)
- ESPAsyncUDP 库(用于 UDP 通信)
3. 系统设计
3.1 网络架构设计
本项目采用点对点的无线网络架构,两个节点都连接到同一 Wi-Fi 网络,并通过 UDP 协议直接通信。选择 UDP 而非 TCP 的原因是:
- 低延迟:UDP 没有连接建立过程,传输延迟更低,适合实时控制场景
- 简单高效:无需维护连接状态,协议开销小,适合简单指令传输
- 广播能力:UDP 支持广播,便于未来扩展到多节点系统
系统的网络拓扑如下图所示:
[节点1] [节点2]
┌─────────────┐ ┌─────────────┐
│ ESP32C3 │ │ ESP32C3 │
│ 手势传感器 │◄──Wi-Fi───►│ 手势传感器 │
│ LED │ (UDP) │ LED │
└─────────────┘ └─────────────┘
3.2 通信协议设计
定义一个简单但可靠的 JSON 格式消息协议:
{
"sender": "NODE_ID", // 发送节点标识
"cmd": "COMMAND_TYPE", // 命令类型
"data": { // 命令数据
"gesture": 0, // 手势类型
"ledCount": 0 // LED数量
},
"timestamp": 0 // 时间戳(毫秒)
}
主要命令类型:
HELLO
: 节点发现和状态同步GESTURE
: 手势控制命令STATUS
: 状态更新通知
3.3 节点标识与地址分配
每个节点需要唯一标识符,我使用简单的方法生成节点 ID:
- 基于 ESP32C3 的芯片 ID 生成唯一标识符
- 使用标识符的前8位作为节点名称
- 使用固定的UDP端口(如 8266)接收消息
- 广播消息到网络(
255.255.255.255
)或已知对方IP地址
节点启动后执行"发现"过程:
- 连接到 Wi-Fi 网络
- 广播 HELLO 消息
- 收到其他节点回复后建立通信连接
3.4 电路连接设计
由于每个节点的硬件连接与第10周作业相同,我将遵循之前验证过的连接方案:
APDS-9960手势传感器连接
APDS-9960引脚 | 连接到扩展板引脚 | XIAO ESP32C3引脚 | 功能 |
---|---|---|---|
VCC(红线) | J1-2 (3.3V) | 3.3V | 电源正极 |
GND(黑线) | J1-1 (GND) | GND | 电源地线 |
SDA(黄线) | J1-3 (RX/D7) | GPIO20 | I2C数据线(软件实现) |
SCL(绿线) | J1-4 (TX/D6) | GPIO21 | I2C时钟线(软件实现) |
LED 连接
开发板上已有 6 个 LED(D0-D5),直接通过板载电路连接到 XIAO ESP32C3 的对应 GPIO 引脚。
接线示意图如下所示,期望实现的效果是在任意手势传感器上操作,都能同步操作 2 个设备的 LED 灯(上下增加或减少 LED 亮灯个数,左右全开或全灭 LED )。
两组设备的接线方式完全一样
4. 程序设计
4.1 程序结构设计
程序主要分为以下几个模块:
- 初始化模块:Wi-Fi 连接、传感器设置、UDP 通信建立
- 手势处理模块:检测和解析手势指令
- 通信模块:发送和接收网络消息
- 指令执行模块:控制本地LED
- 状态管理模块:维护和同步节点状态
4.2 核心代码实现
这部分程序我借助 Claude 3.7 辅助编写,大致提示词如下,同时我还提供了第 10 周个人作业的完整 Markdown 文档,第 11 周的课程大纲链接(让 AI 了解课程和作业要求)作为背景资料给 AI 参考。
对于第 11 周我的个人作业的想法是再准备一块功能一样的扩展板,搭配同样的手势传感器,通过无线网络实现双设备同步。就是任何一个设备的传感器收到的手势指令(上下和第 10 课一致,左右控制 LED 全开全关),都能同步驱动在2个设备上的 LED 灯。请根据这个创意帮我撰写第11周的个人作业的程序。
#include <WiFi.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include "XLOT_APDS9960AD.h"
// WiFi设置
const char* ssid = "YourWiFiName";
const char* password = "YourWiFiPassword";
// 网络通信设置
WiFiUDP udp;
const int UDP_PORT = 8266;
IPAddress broadcastIP(255, 255, 255, 255);
char packetBuffer[255];
// 引脚重定义 - 适应自制扩展板
#define SDA_PIN 20 // RX/D7 (GPIO20)
#define SCL_PIN 21 // TX/D6 (GPIO21)
// LED引脚定义
const int LED_PINS[] = {D5, D4, D3, D2, D1, D0};
const int LED_COUNT = 6;
// 手势传感器
XLOT_APDS9960AD apds;
// 控制变量
int ledCount = 0; // 点亮的LED数量(0-6)
unsigned long lastGestureTime = 0; // 最后手势时间戳
const int gestureDelay = 500; // 手势识别间隔(毫秒)
// 节点标识
String nodeId;
bool otherNodeConnected = false;
IPAddress otherNodeIP;
// 时间控制变量
unsigned long lastHelloTime = 0;
unsigned long lastHeartbeat = 0;
// 初始化节点标识,确保唯一性
void initNodeId() {
uint64_t chipId = ESP.getEfuseMac(); // 获取MAC地址作为唯一ID
char nodeIdBuffer[20];
snprintf(nodeIdBuffer, sizeof(nodeIdBuffer), "Node%llX", chipId);
nodeId = String(nodeIdBuffer);
Serial.print("节点ID: ");
Serial.println(nodeId);
}
// 连接WiFi
void connectToWiFi() {
Serial.println("连接到WiFi...");
WiFi.begin(ssid, password);
int retries = 0;
while (WiFi.status() != WL_CONNECTED && retries < 20) {
delay(500);
Serial.print(".");
retries++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi连接成功!");
Serial.print("IP地址: ");
Serial.println(WiFi.localIP());
// 初始化UDP
udp.begin(UDP_PORT);
Serial.print("监听UDP端口: ");
Serial.println(UDP_PORT);
// 发送广播消息通知其他节点
sendHelloMessage(false);
} else {
Serial.println("\nWiFi连接失败!");
// 闪烁LED指示连接失败
for (int i = 0; i < 10; i++) {
digitalWrite(LED_PINS[0], HIGH);
delay(100);
digitalWrite(LED_PINS[0], LOW);
delay(100);
}
}
}
// 发送广播消息
void sendHelloMessage(bool isReply) {
unsigned long now = millis();
// 限制HELLO消息频率
if (!isReply && (now - lastHelloTime < 5000)) {
return;
}
lastHelloTime = now;
DynamicJsonDocument doc(256);
doc["sender"] = nodeId;
doc["cmd"] = "HELLO";
doc["isReply"] = isReply;
doc["data"]["ledCount"] = ledCount;
doc["timestamp"] = now;
String jsonString;
serializeJson(doc, jsonString);
IPAddress targetIP = isReply ? otherNodeIP : broadcastIP;
udp.beginPacket(targetIP, UDP_PORT);
udp.print(jsonString);
udp.endPacket();
Serial.print("发送");
Serial.print(isReply ? "回复" : "广播");
Serial.println("消息: " + jsonString);
}
// 发送手势控制消息
void sendGestureCommand(uint8_t gesture) {
if (!otherNodeConnected) {
Serial.println("未发现其他节点,使用广播");
}
DynamicJsonDocument doc(256);
doc["sender"] = nodeId;
doc["cmd"] = "GESTURE";
doc["data"]["gesture"] = gesture;
doc["data"]["ledCount"] = ledCount;
doc["timestamp"] = millis();
String jsonString;
serializeJson(doc, jsonString);
IPAddress targetIP = otherNodeConnected ? otherNodeIP : broadcastIP;
udp.beginPacket(targetIP, UDP_PORT);
udp.print(jsonString);
udp.endPacket();
Serial.println("发送手势命令: " + jsonString);
}
// 处理接收到的消息
void processReceivedMessage(String message) {
DynamicJsonDocument doc(256);
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.print("解析JSON失败: ");
Serial.println(error.c_str());
return;
}
String sender = doc["sender"];
if (sender == nodeId) {
// 忽略自己发送的消息
return;
}
String cmd = doc["cmd"];
Serial.print("收到命令: ");
Serial.print(cmd);
Serial.print(" 来自: ");
Serial.println(sender);
if (cmd == "HELLO") {
// 检查是否已经与该节点建立连接,避免重复处理
bool isReply = doc.containsKey("isReply") && doc["isReply"].as<bool>();
if (!otherNodeConnected || otherNodeIP != udp.remoteIP()) {
otherNodeConnected = true;
otherNodeIP = udp.remoteIP();
// 如果这不是回复消息,则发送回复
if (!isReply) {
sendHelloMessage(true); // 发送带有回复标记的HELLO消息
}
Serial.print("与节点 ");
Serial.print(sender);
Serial.println(" 建立连接");
// 闪烁LED指示连接成功(仅一次)
bool originalLedStates[LED_COUNT];
for(int i = 0; i < LED_COUNT; i++) {
originalLedStates[i] = (i < ledCount); // 保存当前LED状态
digitalWrite(LED_PINS[i], HIGH);
delay(100);
}
delay(300);
for(int i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], originalLedStates[i] ? HIGH : LOW); // 恢复原始状态
delay(50);
}
}
// 同步对方状态(无论是否是回复消息)
if (doc["data"].containsKey("ledCount")) {
int remoteLedCount = doc["data"]["ledCount"];
if (ledCount != remoteLedCount) {
ledCount = remoteLedCount;
updateLEDs();
Serial.print("同步LED数量: ");
Serial.println(ledCount);
}
}
} else if (cmd == "GESTURE") {
// 处理手势命令
uint8_t gesture = doc["data"]["gesture"];
processGesture(gesture, false);
// 同步其他状态
if (doc["data"].containsKey("ledCount")) {
int remoteLedCount = doc["data"]["ledCount"];
if (ledCount != remoteLedCount) {
ledCount = remoteLedCount;
updateLEDs();
}
}
}
}
// 检查接收的消息
void checkForMessages() {
int packetSize = udp.parsePacket();
if (packetSize) {
// 接收消息
int len = udp.read(packetBuffer, 255);
if (len > 0) {
packetBuffer[len] = 0;
}
String message = String(packetBuffer);
processReceivedMessage(message);
}
}
// 更新LED显示
void updateLEDs() {
for(int i = 0; i < LED_COUNT; i++) {
// 如果i小于ledCount,点亮LED,否则熄灭
digitalWrite(LED_PINS[i], (i < ledCount) ? HIGH : LOW);
}
}
// 处理手势
void processGesture(uint8_t gesture, bool sendCommand) {
switch(gesture) {
case APDS9960_RIGHT:
// 右划 - 全部点亮LED
if(ledCount < LED_COUNT) {
ledCount = LED_COUNT;
updateLEDs();
Serial.println("全部LED点亮");
}
break;
case APDS9960_LEFT:
// 左划 - 全部关闭LED
if(ledCount > 0) {
ledCount = 0;
updateLEDs();
Serial.println("全部LED关闭");
}
break;
case APDS9960_UP:
// 上划 - 增加LED亮灯数量
if(ledCount < LED_COUNT) {
ledCount++;
updateLEDs();
Serial.print("LED亮灯数量: ");
Serial.println(ledCount);
}
break;
case APDS9960_DOWN:
// 下划 - 减少LED亮灯数量
if(ledCount > 0) {
ledCount--;
updateLEDs();
Serial.print("LED亮灯数量: ");
Serial.println(ledCount);
}
break;
}
// 如果需要发送指令到其他节点
if (sendCommand && gesture != 0) {
sendGestureCommand(gesture);
}
}
// 监控网络连接
void monitorConnection() {
// 检查WiFi连接
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi连接丢失,尝试重连...");
connectToWiFi();
return;
}
// 发送周期性心跳消息
unsigned long now = millis();
if (now - lastHeartbeat > 60000) { // 每60秒
lastHeartbeat = now;
if (otherNodeConnected) {
DynamicJsonDocument doc(128);
doc["sender"] = nodeId;
doc["cmd"] = "HEARTBEAT";
doc["timestamp"] = now;
String jsonString;
serializeJson(doc, jsonString);
udp.beginPacket(otherNodeIP, UDP_PORT);
udp.print(jsonString);
udp.endPacket();
Serial.println("发送心跳信息");
} else {
// 如果没有连接到其他节点,尝试再次发送广播
sendHelloMessage(false);
}
}
}
void setup() {
Serial.begin(115200);
delay(3000); // 增加延迟,确保有足够时间上传新代码
Serial.println("\n双节点手势控制LED系统启动...");
// 初始化节点ID
initNodeId();
// 使用重定义的引脚初始化I2C
Wire.begin(SDA_PIN, SCL_PIN);
// 初始化所有LED引脚
for(int i = 0; i < LED_COUNT; i++) {
pinMode(LED_PINS[i], OUTPUT);
digitalWrite(LED_PINS[i], LOW); // 初始状态全部关闭
}
// 初始化手势传感器
if(!apds.begin()){
Serial.println("手势传感器初始化失败! 请检查接线。");
// 错误指示 - 闪烁第一个LED
while(1) {
digitalWrite(LED_PINS[0], HIGH);
delay(100);
digitalWrite(LED_PINS[0], LOW);
delay(100);
}
} else {
Serial.println("手势传感器初始化成功!");
apds.enableProximity(true);
apds.enableGesture(true);
apds.setProxGain(APDS9960_PGAIN_8X);
apds.setGestureGain(APDS9960_PGAIN_8X);
apds.setGestureGain(APDS9960_AGAIN_64X);
apds.setGestureGain(APDS9960_GGAIN_8);
// 成功指示 - 所有LED依次亮起再熄灭
for(int i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], HIGH);
delay(200);
}
delay(500);
for(int i = 0; i < LED_COUNT; i++) {
digitalWrite(LED_PINS[i], LOW);
delay(200);
}
}
// 连接WiFi并初始化UDP
connectToWiFi();
// 初始化时间变量
lastHelloTime = millis();
lastHeartbeat = millis();
Serial.println("系统初始化完成,等待手势控制或网络消息...");
}
void loop() {
// 检查网络消息
checkForMessages();
// 监控网络连接
monitorConnection();
// 读取手势
uint8_t gesture = apds.readGesture();
// 处理手势(添加延迟以防止过快响应)
if(gesture != 0 && millis() - lastGestureTime > gestureDelay) {
lastGestureTime = millis();
// 处理手势并发送到网络
processGesture(gesture, true);
}
// 短暂延迟以减少CPU使用率
delay(10);
}
注意修改程序中的 Wi-Fi 名和密码为自己现场的,然后一次将程序上传到 2 个 XIAO ESP32C3 中。
安装 ArduinoJson 库
接下来的程序需要 ArduinoJson 库,这是一个流行的 Arduino 库,用于处理 JSON 数据,它在我们的网络通信项目中是必需的。
你需要先安装这个库才能编译该代码,否则会报错。以下是安装 ArduinoJson 库的步骤:
通过 Arduino IDE 库管理器安装
- 打开 Arduino IDE
- 点击顶部菜单的 工具(Tools) → 管理库(Manage Libraries)
- 在弹出的库管理器窗口中,在搜索框输入 ArduinoJson
- 找到由 Benoit Blanchon 开发的 ArduinoJson 库
- 选择最新版本(推荐6.x版本)并点击 安装(Install) 按钮
- 等待安装完成
- 关闭库管理器窗口
- 重新编译你的代码
在库管理界面搜索 ArduinoJson,安装由 Benoit Blanchon 开发的 ArduinoJson 库
手动安装(如果上述方法不起作用)
- 访问 ArduinoJson GitHub 仓库
- 点击 Code 下拉菜单,然后选择 Download ZIP
- 下载完成后解压ZIP文件
- 把解压后的 ArduinoJson 文件夹复制到你的 Arduino 库文件夹中
- Windows:
Documents\Arduino\libraries\
- macOS:
~/Documents/Arduino/libraries/
- Linux:
~/Arduino/libraries/
- Windows:
- 重启 Arduino IDE
- 重新编译你的代码
如果你的代码还使用了其他未安装的库(如 XLOT_APDS9960AD 库),你也需要按照类似的方式安装这些库。
已内置的 Wire.h
库
#include <Wire.h>
是包含 Arduino 的内置 I2C 通信库。你不需要额外安装任何库,因为 Wire 库是Arduino IDE 内置的标准库。
它用于通过 I2C 协议与各种传感器和设备进行通信,例如我们项目中使用的 APDS-9960 手势传感器。
当你安装 Arduino IDE 时,Wire 库已经包含在内,因此不需要任何额外安装步骤。只需要在代码中包含这个头文件即可使用 I2C 功能。
4.3 程序功能说明
- 节点识别与初始化:
- 基于 ESP32 芯片 ID 生成唯一节点标识
- 初始化 Wi-Fi 连接和 UDP 通信
- 发送广播消息寻找其他节点
- 网络通信功能:
- 使用 UDP 协议实现低延迟通信
- JSON 格式消息确保数据交换的灵活性
- 广播和点对点消息支持双节点通信
- 手势控制与命令同步:
- 本地手势检测后同时控制本地设备并发送网络命令
- 接收远程手势命令并执行相应操作
- 确保两个节点的 LED 状态保持同步
- 状态管理与反馈:
- 通过 LED 显示连接状态和操作反馈
- 定期发送心跳消息确保连接稳定
- 自动同步加入网络时的初始状态
- 应对网络中断:
- 通信中断后继续维持本地功能
- 自动尝试重新发现和连接节点
- 恢复连接后进行状态同步
5. 硬件实现
5.2 布局考量
- Wi-Fi 信号强度:
- 确保为 XIAO ESP32C3 安装好天线(否则信号强度极低)
- 确保两个节点都在 Wi-Fi 覆盖范围内
- 避免金属物体等可能干扰Wi-Fi信号的障碍
- 手势识别优化:
- 传感器表面保持清洁
- 避免强光直射传感器表面
- 两个节点的传感器相互不干扰
- 视觉显示效果:
- 两个节点的 LED 灯阵列可以同时观察到,便于比较同步效果
- 使用不同颜色的LED(一个节点使用红色,一个节点使用蓝色)以便区分
我将两组设备分别固定在 2 个酒瓶上。
两组设备被分别固定在 2 个酒瓶上
6. 系统测试与演示
我将两个设备分别固定在两个酒瓶上进行测试,我依次对 2 个设备的传感器部分进行了适当遮挡,确保分别测试不同设备的手势是否都能确保同步,下面是测试结果:
6.1 网络连接测试
两个节点启动后能够顺利完成以下网络连接流程:
- 各节点成功连接到Wi-Fi网络,并通过广播消息自动发现对方
- 建立连接时LED显示闪烁确认,提供直观的连接反馈
- 当一个节点的Wi-Fi连接暂时断开后,系统能够自动重连并恢复设备状态同步
测试过程中观察到的平均延迟约为50-80ms,完全满足实时控制需求,延迟对用户体验几乎无影响。在正常Wi-Fi环境下,丢包率保持在较低水平,通信稳定性良好。
6.2 同步控制测试
LED控制同步效果表现如下:
- 上划手势:两个设备的LED数量同步增加,视觉反馈一致
- 下划手势:两个设备的LED数量同步减少,视觉反馈一致
- 左划手势(全关):两个设备的LED同时熄灭
- 右划手势(全开):两个设备的LED同时全部点亮
测试期间偶尔出现手势识别不准确的情况,导致部分手势命令未被识别,但这主要是传感器本身的局限性,而非网络同步问题。当手势被正确识别时,同步控制准确率接近100%。
6.3 实际测试体验
实际测试中,系统表现出良好的稳定性和可靠性:
- 两个设备之间的同步延迟几乎不可察觉,视觉上呈现几乎同时响应的效果
- 手势控制接口直观,上下手势调节LED数量,左右手势实现全开/全关功能
- 网络断开后,本地功能继续正常运行,网络恢复后自动重新同步状态
- 偶尔手势识别不太准确导致响应没有出现,但这主要是传感器识别率的限制
总体而言,测试证明了系统的网络通信架构可靠,手势控制机制有效,两个设备能够保持良好的状态同步。虽然手势识别准确率有时受到限制,但在大部分情况下系统表现良好,成功实现了双节点的无线同步控制。
串口展示的同步数据
实际的效果视频如下所示。
7. 项目问题与解决方案
遇到的问题
在项目实施过程中,我遇到了以下几个主要挑战:
- Wi-Fi连接稳定性:
- 问题:ESP32C3在某些Wi-Fi环境下连接不稳定,偶尔断开
- 原因:Wi-Fi信号干扰或电源波动
- 解决方案:
- 添加自动重连机制,监控Wi-Fi状态
- 实现"心跳"机制定期检查连接状态
- 增加连接失败的LED指示反馈
- UDP通信可靠性:
- 问题:UDP协议不保证消息送达,可能丢失关键控制指令
- 解决方案:
- 添加简单的消息确认机制
- 关键状态变更后发送额外的状态同步消息
- 增加状态更新的周期性广播
- 手势冲突处理:
- 问题:两个节点同时接收不同手势时的状态冲突
- 解决方案:
- 使用时间戳解决冲突,接受最新的命令
- 添加简单的状态版本号机制
- 冲突后主动发起状态同步
8. 结论与反思
8.1 项目成果
本项目成功构建了一个双节点网络化手势控制系统,实现了以下目标:
- 设计并实现了基于ESP32C3的无线网络节点,每个节点集成了手势输入和LED输出功能
- 创建了简单而高效的UDP通信架构,实现了节点间的自动发现和状态同步
- 开发了直观的手势控制协议,使两个节点能响应来自任一节点的手势指令
- 构建了可靠的状态同步机制,确保系统在网络波动下仍能保持一致性
系统展示了ESP32C3的强大网络能力,并证明了基于UDP的轻量级通信协议在实时控制场景中的优势。LED状态指示器提供了直观的系统状态反馈,使用户能够轻松理解系统工作状态。
8.2 与最终项目的关联
本项目是"智幻走马灯"最终项目的关键技术验证,特别是在以下方面:
- 无线控制验证:
- 验证了ESP32C3的Wi-Fi通信能力,为走马灯的远程控制打下基础
- 测试了无线网络在实时控制场景下的性能和可靠性
- 探索了多设备协同工作的架构模式
- 系统模块化设计:
- 验证了将功能分散到不同节点的可行性
- 为最终项目的功能分离提供了参考架构
- 演示了如何在模块化系统中保持状态一致性
- 交互方式拓展:
- 扩展了手势控制的应用范围,从单设备控制到网络化控制
- 验证了通过网络传递复杂交互指令的可行性
- 为未来集成手机APP控制提供了技术基础
- 控制协议设计:
- 开发了可扩展的控制指令协议,能够支持更复杂的灯光效果
- 探索了不同控制维度的组合控制
- 为最终项目的多模式控制提供了架构参考
这些技术验证和架构设计将直接用于最终项目,帮助我实现更加可靠和功能丰富的"智幻走马灯"系统。通过本次双节点网络实验,我更加确信ESP32C3是实现走马灯网络控制的理想平台,并获得了宝贵的系统设计经验。