回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

Arduino IDE K10行空板MCP控制:屏幕显示与RGB灯 简单

头像 rzyzzxw 2025.09.03 30 0

9.3

【任务目标】

开学了,一下忙碌起来,又有93阅兵的期盼。看过阅兵,自豪满满,继续肝。

昨天做了一些用Arduino IDE 对K10行空板编程的准备工作,Arduino IDE K10行空板基础练习:屏幕显示与RGB灯控制- Makelog(造物记),继续做探究Arduino IDE K10行空板MCP控制,从简单的点灯开始,加上K10的屏幕显示,K10的点灯也有趣多了。

d3d839b9dc6a17d3528f9203d31f0b7.jpg

在本项目中,需要一个小智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。

image.png

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

image.png

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

11.png

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

image.png

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

image.png

步骤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接入点获取:

image.png

下面的代码将进行小智通过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连接状态

fce53a16b0544d383dff0b82e688bec.jpg

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

image.png

代码
#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行空板的逻辑架构

image.png

逻辑流程详解
控制指令流(下行)
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编程了,新的使命又开始了。

因为时间没有那么充裕,所以这帖做抛砖引玉,大家一起玩起来哈。

评论

user-avatar