9.3
【任务目标】
开学了,一下忙碌起来,又有93阅兵的期盼。看过阅兵,自豪满满,继续肝。
昨天做了一些用Arduino IDE 对K10行空板编程的准备工作,Arduino IDE K10行空板基础练习:屏幕显示与RGB灯控制- Makelog(造物记),继续做探究Arduino IDE K10行空板MCP控制,从简单的点灯开始,加上K10的屏幕显示,K10的点灯也有趣多了。

在本项目中,需要一个小智AI做上位机,通过自然语音发出控制命令,K10做下位机,K10的屏幕和RGB灯通过xiaozhi-mcp执行小智AI发来的指令。
材料清单
- 行空板K10 X1
- 小智AI X1
步骤1 准备工作
1、下载安装Arduino IDE
2、安装 Arduino IDE SDK
在Arduino IDE中,行空板K10将会以SDK(软件开发包)的形式在下载后集成入Arduino IDE。
SDK URL:
https://downloadcd.dfrobot.com.cn/UNIHIKER/package_unihiker_index.json
在Arduino IDE中打开 "文件→首选项…"
点击下图红圈中的按钮来添加SDK URL。

在对话框中另起一行,添加本文上方的SDK URL,最后点击确定。

打开 "工具→开发板→开发板管理",在对话框中搜索"unihiker"并且点击安装。

等待安装完成后,即可在Arduino IDE中选择行空板k10(unihiker k10)进行开发。

工具--库管理,搜索安装xiaozhi-mcp库。

步骤2 学习xiaozhi-mcp和Arduino IDE k10的官方例程,然后编写通过小智MCP控制K10屏幕和板载RGB灯
xiaozhi-mcp例程的学习可以参考我的另一个帖子:让小智语音控制ESP32 S3点灯|极简MCP插件教程- Makelog(造物记)
Arduino IDE K10官方例程:unihiker.com.cn/wiki/k10/Arduino_PIO_Example
Arduino IDE K10 API手册:unihiker.com.cn/wiki/k10/Arduino_PIO_API_List#UNIHIKER_K10
上面资料的学习,将指导我们进行后续开发。
小智MCP接入点获取:

下面的代码将进行小智通过MCP库控制K10板载RGB和屏幕控制的操作。
功能说明
1. 板载RGB灯控制
•精确颜色控制:通过MCP命令设置具体的RGB值(0-255)
•预设模式:支持红、绿、蓝、白、关闭、闪烁等模式
•亮度调节:支持0-100亮度调节
2. 屏幕显示功能
•黑屏白字:使用黑色背景和白色文字
•实时状态显示:
3. MCP工具接口
•rgb_control:精确控制RGB颜色
•rgb_mode:选择预设颜色模式
•rgb_brightness:调节亮度级别
•当前RGB颜色值
•颜色预览方块
•WiFi连接状态
•IP地址信息
•MCP连接状态

代码刷入,运行程序小智后台显示工具可用:

#include <WiFi.h>
#include <WebSocketMCP.h>
#include "unihiker_k10.h"
// WiFi配置
const char* ssid = "your-ssid";
const char* password = "your-password";
// MCP服务器配置
const char* mcpEndpoint = "ws://api.xiaozhi.me/mcp/?token=";
// 创建对象
WebSocketMCP mcpClient;
UNIHIKER_K10 k10;
uint8_t screen_dir = 2;
// RGB颜色状态
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint8_t brightness = 100; // 使用百分比表示亮度 (0-100)
bool blinking = false;
unsigned long lastBlinkTime = 0;
bool blinkState = false;
void setup() {
Serial.begin(115200);
// 初始化K10屏幕
k10.begin();
k10.initScreen(screen_dir);
k10.creatCanvas();
// 设置黑色背景
k10.setScreenBackground(0x000000);
// 显示项目标题
k10.canvas->canvasText("K10 MCP控制系统", 10, 10, 0xFFFFFF, k10.canvas->eCNAndENFont24, 200, true);
k10.canvas->canvasText("等待WiFi连接...", 10, 50, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->updateCanvas();
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// WiFi连接成功显示
k10.canvas->canvasClear();
k10.canvas->canvasText("WiFi已连接", 10, 10, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->canvasText("IP: " + WiFi.localIP().toString(), 10, 40, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->updateCanvas();
delay(2000);
// 初始化MCP客户端
mcpClient.begin(mcpEndpoint, [](bool connected) {
if (connected) {
Serial.println("已连接到MCP服务器");
// 更新屏幕显示
k10.canvas->canvasClear();
k10.canvas->canvasText("MCP连接成功", 10, 10, 0x00FF00, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->updateCanvas();
registerTools();
} else {
Serial.println("与MCP服务器断开连接");
// 更新屏幕显示
k10.canvas->canvasClear();
k10.canvas->canvasText("MCP连接断开", 10, 10, 0xFF0000, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->updateCanvas();
}
});
}
void loop() {
mcpClient.loop();
// 处理闪烁效果
if (blinking && millis() - lastBlinkTime > 200) {
lastBlinkTime = millis();
blinkState = !blinkState;
if (blinkState) {
// 闪烁亮起时使用当前颜色
applyBrightness();
} else {
// 闪烁熄灭时关闭灯光
k10.rgb->write(-1, 0, 0, 0);
}
}
delay(10);
}
// 应用亮度到RGB颜色
void applyBrightness() {
// 计算应用亮度后的颜色值
uint8_t r = red * brightness / 100;
uint8_t g = green * brightness / 100;
uint8_t b = blue * brightness / 100;
// 设置RGB灯
k10.rgb->write(-1, r, g, b);
}
// 注册MCP工具
void registerTools() {
// 注册RGB颜色控制工具
mcpClient.registerTool(
"rgb_control",
"控制板载RGB灯颜色",
"{\"type\":\"object\",\"properties\":{\"red\":{\"type\":\"number\",\"minimum\":0,\"maximum\":255},\"green\":{\"type\":\"number\",\"minimum\":0,\"maximum\":255},\"blue\":{\"type\":\"number\",\"minimum\":0,\"maximum\":255}},\"required\":[\"red\",\"green\",\"blue\"]}",
[](const String& args) {
DynamicJsonDocument doc(256);
deserializeJson(doc, args);
red = doc["red"];
green = doc["green"];
blue = doc["blue"];
// 应用亮度并控制板载RGB灯
applyBrightness();
// 更新屏幕显示
updateScreenDisplay();
return WebSocketMCP::ToolResponse("{\"success\":true,\"message\":\"RGB颜色已设置\"}");
}
);
// 注册RGB模式控制工具
mcpClient.registerTool(
"rgb_mode",
"控制RGB灯模式",
"{\"type\":\"object\",\"properties\":{\"mode\":{\"type\":\"string\",\"enum\":[\"red\",\"green\",\"blue\",\"white\",\"off\",\"blink\"]}},\"required\":[\"mode\"]}",
[](const String& args) {
DynamicJsonDocument doc(256);
deserializeJson(doc, args);
String mode = doc["mode"].as<String>();
if (mode == "red") {
blinking = false;
red = 255; green = 0; blue = 0;
applyBrightness();
} else if (mode == "green") {
blinking = false;
red = 0; green = 255; blue = 0;
applyBrightness();
} else if (mode == "blue") {
blinking = false;
red = 0; green = 0; blue = 255;
applyBrightness();
} else if (mode == "white") {
blinking = false;
red = 255; green = 255; blue = 255;
applyBrightness();
} else if (mode == "off") {
blinking = false;
red = 0; green = 0; blue = 0;
k10.rgb->write(-1, 0, 0, 0);
} else if (mode == "blink") {
// 启用软件闪烁
blinking = true;
lastBlinkTime = millis();
}
// 更新屏幕显示
updateScreenDisplay();
return WebSocketMCP::ToolResponse("{\"success\":true,\"mode\":\"" + mode + "\"}");
}
);
// 注册亮度控制工具
mcpClient.registerTool(
"rgb_brightness",
"控制RGB灯亮度",
"{\"type\":\"object\",\"properties\":{\"brightness\":{\"type\":\"number\",\"minimum\":0,\"maximum\":100}},\"required\":[\"brightness\"]}",
[](const String& args) {
DynamicJsonDocument doc(256);
deserializeJson(doc, args);
brightness = doc["brightness"];
// 应用亮度到当前颜色
applyBrightness();
// 更新屏幕显示
updateScreenDisplay();
return WebSocketMCP::ToolResponse("{\"success\":true,\"brightness\":" + String(brightness) + "}");
}
);
Serial.println("RGB控制工具已注册");
}
// 更新屏幕显示
void updateScreenDisplay() {
k10.canvas->canvasClear();
// 显示项目标题
k10.canvas->canvasText("K10 MCP控制系统", 10, 10, 0xFFFFFF, k10.canvas->eCNAndENFont24, 200, true);
// 显示当前RGB值
k10.canvas->canvasText("RGB颜色值:", 10, 50, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->canvasText("R: " + String(red), 10, 80, 0xFF0000, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->canvasText("G: " + String(green), 10, 110, 0x00FF00, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->canvasText("B: " + String(blue), 10, 140, 0x0000FF, k10.canvas->eCNAndENFont16, 200, true);
// 显示亮度值
k10.canvas->canvasText("亮度: " + String(brightness) + "%", 10, 170, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
// 显示闪烁状态
if (blinking) {
k10.canvas->canvasText("状态: 闪烁中", 10, 200, 0xFFFF00, k10.canvas->eCNAndENFont16, 200, true);
} else {
k10.canvas->canvasText("状态: 常亮", 10, 200, 0x00FF00, k10.canvas->eCNAndENFont16, 200, true);
}
// 显示颜色方块
uint32_t currentColor = (red << 16) | (green << 8) | blue;
k10.canvas->canvasRectangle(150, 80, 60, 60, currentColor, currentColor, true);
// 显示连接状态
k10.canvas->canvasText("MCP连接状态: 已连接", 10, 230, 0x00FF00, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->canvasText("IP: " + WiFi.localIP().toString(), 10, 260, 0xFFFFFF, k10.canvas->eCNAndENFont16, 200, true);
k10.canvas->updateCanvas();
}
小智AI通过MCP控制K10行空板的逻辑架构

逻辑流程详解
控制指令流(下行)
1.用户通过小智AI平台界面发送控制指令
2.小智AI平台将指令封装为MCP协议格式
3.MCP服务器接收并转发指令到目标设备
4.K10行空板的WebSocketMCP客户端接收并解析指令
5.根据指令类型调用相应的控制函数:
RGB灯控制:调整颜色、亮度、闪烁模式
屏幕显示:更新文本、图形、状态信息
其他外设:控制扩展设备
数据反馈流(上行)
1.K10行空板采集传感器数据和设备状态
2.通过WebSocketMCP客户端封装数据
3.MCP服务器接收并转发数据
4.小智AI平台解析并展示数据
5.用户在平台上查看实时状态和历史数据
3. 核心组件功能
小智AI平台
•提供用户交互界面
•指令生成与封装
•数据可视化展示
•用户管理与权限控制
MCP服务器
•协议转换与路由
•设备连接管理
•消息队列处理
•安全认证与加密
K10行空板
•WebSocketMCP客户端连接
•硬件资源管理
•指令执行与反馈
•本地数据处理
在后面的系列帖子中,都是这个逻辑框架。
【小结】
假期中开始接触Arduino IDE ,因为对小智MCP入迷,所以写了一些小智和M10,小智和ESP32 S3的帖子,现在K10支持arduino IDE编程了,新的使命又开始了。
因为时间没有那么充裕,所以这帖做抛砖引玉,大家一起玩起来哈。
评论