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

小智语音控制ESP32 S3三颗外接LED灯|极简MCP插件教程 简单

头像 rzyzzxw 2025.08.08 28 0

8.8

【写在前面】

这个帖子其实是复习课,用小智语音控制ESP32 S3-DevKitC-1开发板(N16R8)板载灯后,把代码改改,变成控制外接LED灯,可以是控制一颗、二颗、三颗或者更多,建议最少两颗吧,能达到对小智MCP语音控制过程的更好理解。

e281a873cb0d6fb6cafd57cac2aaea1.jpg

材料清单

  • K10小智AI X1
  • ESP32 S3-DevKitC-1开发板(N16R8) X1
  • 红绿黄LED X1

步骤1 开发板连接Ardino IDE

步骤2 从库管理中找到xiaozhi-mcp,打开示例BasicExample,修改代码

连接电路,红--IO4,黄--IO5,绿--IO6。

代码中指定三个LED的引脚。

image.png

红框内是一个完整的控制工具,由原来的代码修改得到。

image.png

复制红框内的红色LED控制工具,修改成黄灯和绿灯的。

image.png
image.png

初始化引脚,并将三个灯初始化为关(低电平)

image.png

完整代码如下:

代码
#include <WiFi.h>
#include <WebSocketMCP.h>

#define RED_LED    4     // 引脚 (GPIO4)
#define GREEN_LED  6     // 引脚 (GPIO6)
#define YELLOW_LED 5     // 引脚 (GPIO5)

// WiFi配置
const char* ssid = "*****";
const char* password = "******";

// MCP服务器配置
const char* mcpEndpoint = "ws://api.xiaozhi.me/mcp/?token=******";

// 创建WebSocketMCP实例
WebSocketMCP mcpClient;

// 连接状态回调函数
void onConnectionStatus(bool connected) {
  if (connected) {
    Serial.println("[MCP] 已连接到服务器");
    // 连接成功后注册工具
    registerMcpTools();
  } else {
    Serial.println("[MCP] 与服务器断开连接");
  }
}

// 注册MCP工具
void registerMcpTools() {
  // 注册红色LED控制工具
  mcpClient.registerTool(
    "red_led",
    "控制ESP32 GPIO4引脚上的RED_LED",
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    [](const String& args) {
      DynamicJsonDocument doc(256);
      deserializeJson(doc, args);
      String state = doc["state"].as<String>();
      
      if (state == "on") {
        digitalWrite(RED_LED, HIGH);
      } else if (state == "off") {
        digitalWrite(RED_LED, LOW);
      } else if (state == "blink") {
        for (int i = 0; i < 5; i++) {
          digitalWrite(RED_LED, HIGH);
          delay(200);
          digitalWrite(RED_LED, LOW);
          delay(200);
        }
      }
      return WebSocketMCP::ToolResponse("{\"success\":true,\"state\":\"" + state + "\"}");
    }
  );
    // 注册黄色LED控制工具
  mcpClient.registerTool(
    "yellow_led",
    "控制ESP32 GPIO5引脚上的YELLOW_LED",
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    [](const String& args) {
      DynamicJsonDocument doc(256);
      deserializeJson(doc, args);
      String state = doc["state"].as<String>();
      
      if (state == "on") {
        digitalWrite(YELLOW_LED, HIGH);
      } else if (state == "off") {
        digitalWrite(YELLOW_LED, LOW);
      } else if (state == "blink") {
        for (int i = 0; i < 5; i++) {
          digitalWrite(YELLOW_LED, HIGH);
          delay(200);
          digitalWrite(YELLOW_LED, LOW);
          delay(200);
        }
      } 
        return WebSocketMCP::ToolResponse("{\"success\":true,\"state\":\"" + state + "\"}");
    }
  );
  // 注册绿色LED控制工具
  mcpClient.registerTool(
    "green_led",  // 
    "控制ESP32 GPIO6引脚上的GREEN_LED",  // 修正引脚描述
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    [](const String& args) {
      DynamicJsonDocument doc(256);
      deserializeJson(doc, args);
      String state = doc["state"].as<String>();
      
      if (state == "on") {
        digitalWrite(GREEN_LED, HIGH);
      } else if (state == "off") {
        digitalWrite(GREEN_LED, LOW);
      } else if (state == "blink") {
        for (int i = 0; i < 5; i++) {
          digitalWrite(GREEN_LED, HIGH);
          delay(200);
          digitalWrite(GREEN_LED, LOW);
          delay(200);
        }
      }
      return WebSocketMCP::ToolResponse("{\"success\":true,\"state\":\"" + state + "\"}"); // 添加返回值
    }
  );
  Serial.println("[MCP] LED控制工具已注册");
}



void setup() {
  Serial.begin(115200);
  
   // 初始化所有LED引脚
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  
  // 初始状态全关
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);

  // 连接WiFi
  Serial.print("连接到WiFi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("WiFi已连接");
  Serial.println("IP地址: " + WiFi.localIP().toString());

  // 初始化MCP客户端
  mcpClient.begin(mcpEndpoint, onConnectionStatus);
}

void loop() {
  // 处理MCP客户端事件
  mcpClient.loop();
  
  // 其他代码...
  delay(10);
}

填入配网信息和小智MCP接入点地址。

点击上传,等待编译烧录完成。(如果有报错,要根据日志提示修改代码,当然小白简单粗暴的懒人方法是交给DS处理。)

image.png

打开串口监视器,波特率115200,重启ESP32 S3开发板,可以看到连接服务器非常迅速哦。

image.png

我的K10小智控制台:

屏幕截图 2025-08-08 145234.png

AI一键优化后

屏幕截图 2025-08-08 145541.png

MCP接入点

image.png

步骤3 代码优化

上面代码可以运行,然后放给DS,它帮助给出了优化,学习一下,也是有很多收获的啊。

主要优化处在:

用了一个通用LED控制函数,合并了三个灯的开、关、闪烁功能。

image.png

然后控制工具就省去很多行代码了。

image.png

哈哈,DS果然强大。

代码
#include <WiFi.h>
#include <WebSocketMCP.h>

#define RED_LED    4     // A0引脚 (GPIO4)
#define GREEN_LED  6     // A2引脚 (GPIO6)
#define YELLOW_LED 5     // A1引脚 (GPIO5)

// WiFi配置
const char* ssid = "*****";
const char* password = "*****";

// MCP服务器配置
const char* mcpEndpoint = "ws://api.xiaozhi.me/mcp/?token=*******";

// 创建WebSocketMCP实例
WebSocketMCP mcpClient;

// 连接状态回调函数
void onConnectionStatus(bool connected) {
  if (connected) {
    Serial.println("[MCP] 已连接到服务器");
    // 连接成功后注册工具
    registerMcpTools();
  } else {
    Serial.println("[MCP] 与服务器断开连接");
  }
}

// 通用LED控制函数
auto createLedControlTool(const String& toolName, const String& description, int ledPin, const String& ledColor) {
  return [ledPin, ledColor](const String& args) {
    DynamicJsonDocument doc(256);
    deserializeJson(doc, args);
    String state = doc["state"].as<String>();
    
    if (state == "on") {
      digitalWrite(ledPin, HIGH);
    } else if (state == "off") {
      digitalWrite(ledPin, LOW);
    } else if (state == "blink") {
      for (int i = 0; i < 5; i++) {
        digitalWrite(ledPin, HIGH);
        delay(200);
        digitalWrite(ledPin, LOW);
        delay(200);
      }
    }
    
    return WebSocketMCP::ToolResponse(
      "{\"success\":true,\"led_color\":\"" + ledColor + "\",\"state\":\"" + state + "\"}"
    );
  };
}

// 注册MCP工具
void registerMcpTools() {
  // 注册红灯控制工具
  mcpClient.registerTool(
    "red_led_control",
    "控制红色LED灯 (GPIO4)",
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    createLedControlTool("red_led_control", "红色LED控制", RED_LED, "red")
  );
  
  // 注册绿灯控制工具
  mcpClient.registerTool(
    "green_led_control",
    "控制绿色LED灯 (GPIO6)",
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    createLedControlTool("green_led_control", "绿色LED控制", GREEN_LED, "green")
  );
  
  // 注册黄灯控制工具
  mcpClient.registerTool(
    "yellow_led_control",
    "控制黄色LED灯 (GPIO5)",
    "{\"type\":\"object\",\"properties\":{\"state\":{\"type\":\"string\",\"enum\":[\"on\",\"off\",\"blink\"]}},\"required\":[\"state\"]}",
    createLedControlTool("yellow_led_control", "黄色LED控制", YELLOW_LED, "yellow")
  );
  
  Serial.println("[MCP] 三色LED控制工具已注册");
}

void setup() {
  Serial.begin(115200);
  
  // 初始化所有LED引脚
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  
  // 初始状态全关
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);

  // 连接WiFi
  Serial.print("连接到WiFi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("WiFi已连接");
  Serial.println("IP地址: " + WiFi.localIP().toString());

  // 初始化MCP客户端
  mcpClient.begin(mcpEndpoint, onConnectionStatus);
}

void loop() {
  // 处理MCP客户端事件
  mcpClient.loop();
  
  // 其他代码...
  delay(10);
}

6fa015c74e98e050f0e919b570c51f3.jpg
image.png

测试通过了哈。

没有视频。

评论

user-avatar