回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

读取传感器实时数据,控制双电机小车,体验ROCO小智的MCP功能 简单

头像 rzyzzxw 2025.08.28 24 0

8.28

【写在前面】

这个帖子是roco小智双电机小车+传感器,变身环境监测小车- Makelog(造物记)的续集,也是体验编程狮Roco的最后一帖,其实加上创意,用roco可以完成很多好玩的功能,不过我就是浅浅的体验一下,所以在体验ROCO的MCP功能后,就结束了。

先说结论,ROCO的MCP功能用图形化实现,简单且方便。

78d0d8fff4d4fa30cb2ff96d3372056.jpg

材料清单

  • K10小智AI X1
  • ESP32 S3 N16R8开发板 X1
  • DF L298N电机驱动模块 X1
  • 7V 电池盒 X1
  • 双电机小车底盘 X1
  • DHT11温湿度传感器 X1
  • DF模拟光线传感器 X1

步骤1 先记录小车的组装与接线

组装双电机小车+DHT11和光线传感器接线:

image.png

组装完成后:

696f889d7bcec33d8f8386741de1439.jpg

步骤2 编写程序,读取传感器数据,小车运动。

软件编程狮1.3.0

选择roco小智AI开发板

image.png

添加DHT和ESP MCP库

image.png

程序功能,读取温湿度和光线数据,小车运动(只能控制前后左右停,不能准确控制运动时间)

image.png
image.png

小智后台

image.png

代码
//代码部分
#include <Arduino.h>
#include <WiFi.h>
#include "RocoMCP.h"
#include <dhtESP32-rmt.h>

const char* WIFI_SSID = "your_ssid";
const char* WIFI_PASS = "your_password";
const char* MCP_ENDPOINT = "wss://api.xiaozhi.me/mcp/?token=...";
RocoMCP mcpClient;
DHT dht(20, DHT11);

void setup() {
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        attempts++;
    }

    if (mcpClient.begin(MCP_ENDPOINT)) {
        Serial.println("[编程狮roco MCP客户端] 初始化成功");
    }
  ledcAttachChannel(4, 5000, 8, 0);
  pinMode(5, OUTPUT);
  ledcAttachChannel(6, 5000, 8, 1);
  pinMode(7, OUTPUT);
  mcpClient.registerTool(
            "system-info",
            "获取系统信息",
            "{\"properties\":{},\"title\":\"systemInfoArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String chipModel = ESP.getChipModel();
              uint32_t chipId = ESP.getEfuseMac() & 0xFFFFFFFF;
              uint32_t flashSize = ESP.getFlashChipSize() / 1024;
              uint32_t freeHeap = ESP.getFreeHeap() / 1024;

              String resultJson = "{\"success\":true,\"model\":\"" + chipModel +
                                 "\",\"chipId\":\"" + String(chipId, HEX) +
                                 "\",\"flashSize\":" + String(flashSize) +
                                 ",\"freeHeap\":" + String(freeHeap) +
                                 ",\"wifiStatus\":\"" +
                                 (WiFi.status() == WL_CONNECTED ? "connected" : "disconnected") +
                                 "\",\"ipAddress\":\"" + WiFi.localIP().toString() + "\"}";

              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_tem",
            "读取DHT11温度数值 单位:摄氏度",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readTemperature()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_hum",
            "读取DHT11温度数值 单位:%",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readHumidity()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "light_date",
            "读取模拟光线传感器数值 单位:勒克斯",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(analogRead(17)) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
          "car_forward",
          "控制小车前进",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车前进\", \"type\": \"string\", \"enum\": [\"前进\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "前进") {
                  ledcWrite(4, 180);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
  mcpClient.registerTool(
          "car_backward",
          "控制小车后退",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车后退\", \"type\": \"string\", \"enum\": [\"后退\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "后退") {
                  ledcWrite(4, 180);
                  digitalWrite(5, LOW);
                  ledcWrite(6, 180);
                  digitalWrite(7, LOW);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
  mcpClient.registerTool(
          "car_left",
          "控制小车左转",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车左转\", \"type\": \"string\", \"enum\": [\"左转\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "左转") {
                  ledcWrite(4, 150);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
  mcpClient.registerTool(
          "car_right",
          "控制小车右转",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车右转\", \"type\": \"string\", \"enum\": [\"右转\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "右转") {
                  ledcWrite(4, 220);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 150);
                  digitalWrite(7, HIGH);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
  mcpClient.registerTool(
          "car_stop",
          "控制小车停止",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车停止\", \"type\": \"string\", \"enum\": [\"停止\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "停止") {
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
}

void loop() {
  repeat();
}

void repeat() {
  mcpClient.loop();
}

步骤3 优化程序,用一个MCP工具控制小车

程序优化

image.png
image.png

小智后台

image.png

代码
//代码部分
#include <Arduino.h>
#include <WiFi.h>
#include "RocoMCP.h"
#include <dhtESP32-rmt.h>

const char* WIFI_SSID = "your_ssid";
const char* WIFI_PASS = "your_password";
const char* MCP_ENDPOINT = "wss://api.xiaozhi.me/mcp/?token=...";
RocoMCP mcpClient;
DHT dht(20, DHT11);

void setup() {
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        attempts++;
    }

    if (mcpClient.begin(MCP_ENDPOINT)) {
        Serial.println("[编程狮roco MCP客户端] 初始化成功");
    }
  ledcAttachChannel(4, 5000, 8, 0);
  pinMode(5, OUTPUT);
  ledcAttachChannel(6, 5000, 8, 1);
  pinMode(7, OUTPUT);
  mcpClient.registerTool(
            "system-info",
            "获取系统信息",
            "{\"properties\":{},\"title\":\"systemInfoArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String chipModel = ESP.getChipModel();
              uint32_t chipId = ESP.getEfuseMac() & 0xFFFFFFFF;
              uint32_t flashSize = ESP.getFlashChipSize() / 1024;
              uint32_t freeHeap = ESP.getFreeHeap() / 1024;

              String resultJson = "{\"success\":true,\"model\":\"" + chipModel +
                                 "\",\"chipId\":\"" + String(chipId, HEX) +
                                 "\",\"flashSize\":" + String(flashSize) +
                                 ",\"freeHeap\":" + String(freeHeap) +
                                 ",\"wifiStatus\":\"" +
                                 (WiFi.status() == WL_CONNECTED ? "connected" : "disconnected") +
                                 "\",\"ipAddress\":\"" + WiFi.localIP().toString() + "\"}";

              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_tem",
            "读取DHT11温度数值 单位:摄氏度",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readTemperature()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_hum",
            "读取DHT11温度数值 单位:%",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readHumidity()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "light_date",
            "读取模拟光线传感器数值 单位:勒克斯",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(analogRead(17)) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
          "car_control",
          "控制小车运动状态",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车运动状态\", \"type\": \"string\", \"enum\": [\"前进\",\"后退\",\"左转\",\"右转\",\"停止\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "前进") {
                  ledcWrite(4, 180);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                }
                if (state == "后退") {
                  ledcWrite(4, 180);
                  digitalWrite(5, LOW);
                  ledcWrite(6, 180);
                  digitalWrite(7, LOW);
                }
                if (state == "左转") {
                  ledcWrite(4, 150);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                }
                if (state == "右转") {
                  ledcWrite(4, 220);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 150);
                  digitalWrite(7, HIGH);
                }
                if (state == "停止") {
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
}

void loop() {
  repeat();
}

void repeat() {
  mcpClient.loop();
}

步骤4 优化程序,增加运动时间控制

程序优化

image.png
image.png
image.png

小智后台

image.png

代码
//代码部分
#include <Arduino.h>
#include <WiFi.h>
#include "RocoMCP.h"
#include <dhtESP32-rmt.h>

const char* WIFI_SSID = "your_ssid";
const char* WIFI_PASS = "your_password";
const char* MCP_ENDPOINT = "wss://api.xiaozhi.me/mcp/?token=...";
RocoMCP mcpClient;
DHT dht(20, DHT11);

void setup() {
    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
        delay(500);
        attempts++;
    }

    if (mcpClient.begin(MCP_ENDPOINT)) {
        Serial.println("[编程狮roco MCP客户端] 初始化成功");
    }
  ledcAttachChannel(4, 5000, 8, 0);
  pinMode(5, OUTPUT);
  ledcAttachChannel(6, 5000, 8, 1);
  pinMode(7, OUTPUT);
  mcpClient.registerTool(
            "system-info",
            "获取系统信息",
            "{\"properties\":{},\"title\":\"systemInfoArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String chipModel = ESP.getChipModel();
              uint32_t chipId = ESP.getEfuseMac() & 0xFFFFFFFF;
              uint32_t flashSize = ESP.getFlashChipSize() / 1024;
              uint32_t freeHeap = ESP.getFreeHeap() / 1024;

              String resultJson = "{\"success\":true,\"model\":\"" + chipModel +
                                 "\",\"chipId\":\"" + String(chipId, HEX) +
                                 "\",\"flashSize\":" + String(flashSize) +
                                 ",\"freeHeap\":" + String(freeHeap) +
                                 ",\"wifiStatus\":\"" +
                                 (WiFi.status() == WL_CONNECTED ? "connected" : "disconnected") +
                                 "\",\"ipAddress\":\"" + WiFi.localIP().toString() + "\"}";

              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_tem",
            "读取DHT11温度数值 单位:摄氏度",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readTemperature()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "dht_hum",
            "读取DHT11温度数值 单位:%",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(dht.readHumidity()) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
            "light_date",
            "读取模拟光线传感器数值 单位:勒克斯",
            "{\"properties\":{},\"required\":[],\"title\":\"sensorArguments\",\"type\":\"object\"}",
            [](const String& args) {
              String resultJson = "{\"success\":true,\"value\":" + String(analogRead(17)) + "}";
              return RocoMCP::ToolResponse(resultJson);
            }
        );
  mcpClient.registerTool(
          "car_control",
          "控制小车运动状态及时间",
          "{\n  \"properties\": {\n    \"angle\": {\"title\": \"控制数值\", \"type\": \"integer\"},\n    \"state\": {\"title\": \"控制小车运动状态及时间\", \"type\": \"string\", \"enum\": [\"前进\",\"后退\",\"左转\",\"右转\",\"停止\",\"时间\"]}\n  },\n  \"required\": [\"state\"],\n  \"title\": \"ledControlArguments\",\n  \"type\": \"object\"\n}",
          [](const String& args) {
              DynamicJsonDocument doc(256);
              deserializeJson(doc, args);
              String state = doc["state"].as<String>();
                if (state == "前进") {
                  ledcWrite(4, 180);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                  delay(doc["angle"].as<int>() * 1000);
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }
                if (state == "后退") {
                  ledcWrite(4, 180);
                  digitalWrite(5, LOW);
                  ledcWrite(6, 180);
                  digitalWrite(7, LOW);
                  delay(doc["angle"].as<int>() * 1000);
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }
                if (state == "左转") {
                  ledcWrite(4, 150);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 180);
                  digitalWrite(7, HIGH);
                  delay(doc["angle"].as<int>() * 1000);
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }
                if (state == "右转") {
                  ledcWrite(4, 220);
                  digitalWrite(5, HIGH);
                  ledcWrite(6, 150);
                  digitalWrite(7, HIGH);
                  delay(doc["angle"].as<int>() * 1000);
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }
                if (state == "停止") {
                  ledcWrite(4, 0);
                  ledcWrite(6, 0);
                }

              String resultJson = "{\"success\":true,\"state\":\"" + state + "\",\"angle\":" + String(doc["angle"].as<int>()) + "}";
              return RocoMCP::ToolResponse(resultJson);
          }
      );
}

void loop() {
  repeat();
}

void repeat() {
  mcpClient.loop();
}

评论

user-avatar