前言

随着国产大语言模型的发展,我们不仅可以用它来回答问题、写代码,还可以让它直接控制硬件设备,现在逐步添加最新的大模型支持。这个是基于【ESP32接入国产大模型之豆包】【ESP32接入国产豆包大模型控制灯和舵机】升级的哦!😘😘😘💕💕💕

用 ESP32 接入“豆包”最新大模型,不仅实现通过自然语言控制 LED 灯亮度和舵机角度!优化指令集可查看大模型状态。🤣🤣🤣

在这里插入图片描述

首先声明没有恰饭广告,源代码已经匿名处理,制作细节非常完善,方便大家复刻才会提供快捷的相关链接跳转!!!😘😘😘
在这里插入图片描述

本文将重点介绍如何通过ESP32S3接入国产大模型之豆包升级版。

上一篇博客已经分享了:
【ESP32接入国产大模型之腾讯混元】
【ESP32接入国产大模型之豆包】
【ESP32接入国产大模型之星火】
【ESP32接入国产大模型之MiniMax】
【ESP32接入语言大模型之智谱清言】
【ESP32接入国产大模型之文心一言】
【ESP32接入语言大模型之通义千问】
【ESP32接入国产大模型之kimi】
【ESP32接入国产大模型之Deepseek】
【ESP32接入国产大模型之阿里Deepseek】
【ESP32接入国产大模型之豆包升级版】
【ESP32接入国产豆包大模型控制灯和舵机】
下面是不标准测评,参考而已:

模型 响应时间 内容质量 免费token次数 地址
豆包 2s 9分 50万 https://www.volcengine.com/product/doubao
讯飞星火 4s 8分 1亿 https://www.xfyun.cn/doc/spark/HTTP%E8%B0%83%E7%94%A8%E6%96%87%E6%A1%A3.html
MiniMax 3s 8分 500万 https://www.minimaxi.com/
智谱清言 7s 7分 300万 https://open.bigmodel.cn/
文心一言 10s 7分 500万 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu
通义千问 8s 7分 800万 https://tongyi.aliyun.com/qianwen/
Kimi 2s 9分 50万 https://platform.moonshot.cn/docs/guide/start-using-kimi-api
混元 6s 8分 50万 https://cloud.tencent.com/document/product/1729/105701
Deepseek 12s 9分 50万 https://api-docs.deepseek.com/
阿里Deepseek 10s 9分 50万 https://help.aliyun.com/zh/model-studio/developer-reference/deepseek?spm=a2c4g.11186623.help-menu-search-2400256.d_1#2048aa1f92x46

这一次还是采用Platformio编程就会轻松许多开发。这样就可以把大模型装进口袋啦🤣🤣🤣


1. 豆包大模型

请大家点击豆包火山注册地址,不注册是不能完成下面的实验哦:https://t.vncps.com/5LOve
谢谢啦大家的支持💖💖💖

豆包与火山方舟、火山引擎之间的关系主要体现为技术同源、产品定位互补,三者均隶属于字节跳动旗下。具体联系如下:

🛠️ 1. 火山引擎:底层技术基座

定位:字节跳动推出的企业级云服务平台,提供云计算、大数据、AI 中台、容器服务等基础技术能力。 功能:为火山方舟提供算力支持(GPU
集群)、模型训练 / 推理框架、数据存储等基础设施。 关系:是豆包和火山方舟的技术底层支撑。

🤖 2. 豆包:AI 产品化终端应用

定位:面向公众的AI 对话助手(类似 ChatGPT),可提供问答、写作、编程等能力。 技术来源:依赖于火山引擎的算力资源及自研大模型(如
Skywork 天工、Cloud 系列模型)。 产品形态:直接向用户提供服务的 C 端应用(网页 / App),如 doubao.com。

🔧 3. 火山方舟:AI 模型开发与服务平台

定位:聚焦于企业级 AI 模型的开发、部署与管理平台(类似百度文心千帆)。 核心功能:
模型接入:支持集成第三方大模型(如百川、MiniMax)。 工具链:提供模型精调(Fine-tuning)、评测、API 部署等工具。
场景方案:针对企业需求定制客服、营销等 AI 解决方案。 与豆包的联系: 技术同源:共用火山引擎的 AI 训练框架和推理加速技术。
能力互补:企业可通过火山方舟训练模型,再以 SDK/API 形式接入自身产品(如集成类似豆包的聊天功能)。
模型共享:豆包的底层模型可能通过火山方舟向企业客户开放定制。

产品简介:https://www.volcengine.com/docs/82379/1099455
在这里插入图片描述

1.1 方舟定位

为您提供大模型服务的开发平台,提供功能丰富、安全以及具备价格竞争力的模型调用服务,同时提供模型数据、精调、推理、评测等端到端功能,全方位保障您的 AI 应用开发落地。

1. 极速体验

您可以访问火山方舟大模型体验中心,免登录极速体验模型能力。
点击页面中心的模型切换按钮,可以切换体验Doubao或DeepSeek系列模型能力。
未登录状态下可以体验部分模型。如果您需要体验所有模型能力,建议您登录火山引擎账号,选择并开通模型

点击开启MCP服务器,可以连接使用更多火山云产品与三方工具。
您也可以尝试选择下方的图片理解任务进行尝试。
在这里插入图片描述

1.3 深度思考

官方文档:https://www.volcengine.com/docs/82379/1449737
您可以使用具备深度思考能力的模型,如 deepseek r1、doubao thinking 系列模型,来提升最终答案的准确性。模型在回答问题前,会对问题进行分析和拆解,并基于对问题的拆解回答问题,回答会更加全面和深入。当您向模型提问时,方舟返回模型回答问题前的问题思考逻辑(思维链内容),基于此可观察模型推导过程并使用这部分信息。

1.4 最新模型选择

地址:https://www.volcengine.com/docs/82379/1330310
方舟提供多种模型供您使用。您可依据教程或者API说明,便捷地将模型服务整合到自身业务当中。

模型推荐

2.1 环境配置

  1. Arduino IDE:下载并安装 Arduino IDE;
  2. ESP32 开发板库:在 Arduino IDE 中添加 ESP32 支持;
    参考博客:【esp32c3配置arduino IDE教程】
    为安装过程留出一些时间,具体时间可能因您的互联网连接而异。

2.2 所需零件

要学习本教程,您需要1个 ESP32 开发板或者ESP32C3,建议使用后者,笔者发现同样的代码后者可以轻松调用,ESP32不行(可能板子坏了)

目前这是我使用的ESP32S3官方硬件👍👍👍(小小的身材有大大的力量)只需要35元加摄像头麦克风79元,后期我会整理相关专栏进行Arduino系统学习😘😘😘。有需要可以购买xiao开发板💕💕💕

  1. SeeedXIAO ESP32S3 Sense硬件购买地址:https://s.click.taobao.com/lekazrt
    在这里插入图片描述

  2. ESP32-S3-CAM 核心开发板 N16R8 wifi蓝牙模块 OV2640摄像头硬件购买地址:https://s.click.taobao.com/1PTagos

在这里插入图片描述

  1. ESP32-S3 NANO开发板 虾哥小智AI 蓝牙WiFi核心板N16R8兼容立创S3
    在这里插入图片描述
    WiFi+蓝牙模块 + OV2640/5640摄像头!!高性能S3芯片!多功能开发!创新设计!!板载天线,稳定连接!!关键是全能开发套装!!
    【下单链接】https://s.click.taobao.com/3eH0Gmq
    在这里插入图片描述

上面硬件丝选一,我是第四款硬件

舵机选择,sg90舵机小型航模大扭力舵机伺服控制模块MG90S微型经典舵机云台
【下单链接】https://s.click.taobao.com/gbAzFmq

在这里插入图片描述
LED 引脚接 ESP32 的 GPIO2(可改),这个第四块开发板自带管脚2的LED

舵机信号线接 GPIO3(可改)

GND 公共接地

舵机电源建议单独供电(防止电流过大重启)
在这里插入图片描述

3. 核心代码

对话参考案例:https://www.volcengine.com/docs/82379/1449737
请求数据

curl https://ark.cn-beijing.volces.com/api/v3/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ARK_API_KEY" \
  -d '{ 
    "model": "doubao-seed-1-6-250615",
    "messages": [
        {
            "role": "user",
            "content": "我要研究深度思考模型与非深度思考模型区别的课题,怎么体现我的专业性"
        }
    ]
  }'

在这里插入图片描述

3.1 源码分享

#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <driver/ledc.h>
#include <esp_task_wdt.h>  // 引入ESP32看门狗库

#include <ESP32Servo.h>
// 硬件配置
#define LED_PIN 2       // PWM调光引脚
#define SERVO_PIN 3      // 舵机控制引脚

Servo myservo;  // create servo object to control a servo

// 网络配置
const char *ssid = "IQOO";
const char *password = "12345678";

String apiKey = "Bearer 211f9e11-cd39-4a68-b4a605822";
String apiUrl = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";

// 模型定义
#define MODEL_COUNT 3
const String models[MODEL_COUNT] = {
  "doubao-seed-1-6-251015",        // 模型0: 原模型
  "doubao-seed-1-6-flash-250828",  // 模型1: 最新快速模型
  "doubao-seed-1-6-lite-251015"    // 模型2: 最新轻量模型
};

String currentModel = models[0];  // 默认使用原模型
int currentModelIndex = 0;

// 预设指令模板
String pre_Text = "如果用户需要控制灯或者舵机,请参考以下格式回复硬件控制指令:1. LED控制(device:led,value:0-255);2. 舵机控制(device:servo,value:0-180);3. 其他回答:直接返回文本内容";

// 定义控制结构体
QueueHandle_t xCommandQueue;
struct Command {
  String device;
  int value;
};

// 初始化PWM
void initPWM() {
    ledcSetup(1, 50, 14); // 通道1用于舵机(50Hz, 14bit)
    ledcAttachPin(SERVO_PIN, 1);
    pinMode(LED_PIN, OUTPUT);
    analogWrite(LED_PIN, 100);
}

// 显示可用模型列表
void showModels() {
  Serial.println("\n=== 可用模型列表 ===");
  for (int i = 0; i < MODEL_COUNT; i++) {
    Serial.printf("[%d] %s", i, models[i].c_str());
    if (i == currentModelIndex) {
      Serial.print(" ← 当前使用");
    }
    Serial.println();
  }
  Serial.println("使用 'model X' 切换模型 (X=0,1,2)");
  Serial.println("使用 'current' 查看当前模型");
  Serial.println("====================\n");
}

// 切换模型函数
void switchModel(int modelIndex) {
  if (modelIndex >= 0 && modelIndex < MODEL_COUNT) {
    currentModelIndex = modelIndex;
    currentModel = models[modelIndex];
    Serial.printf("[系统] 已切换到模型: %s\n", currentModel.c_str());
  } else {
    Serial.println("[错误] 无效的模型编号,请使用 0, 1, 2");
  }
}

// 处理系统指令
bool handleSystemCommand(String input) {
  input.trim();
  input.toLowerCase();
  
  if (input == "help" || input == "?") {
    Serial.println("\n=== 系统帮助 ===");
    Serial.println("普通对话: 直接输入问题");
    Serial.println("模型切换: model 0 / model 1 / model 2");
    Serial.println("当前模型: current");
    Serial.println("模型列表: models");
    Serial.println("系统帮助: help 或 ?");
    Serial.println("===============\n");
    return true;
  }
  else if (input == "models") {
    showModels();
    return true;
  }
  else if (input == "current") {
    Serial.printf("[系统] 当前使用模型: %s (编号: %d)\n", currentModel.c_str(), currentModelIndex);
    return true;
  }
  else if (input.startsWith("model ")) {
    String modelStr = input.substring(6);
    modelStr.trim();
    int modelIndex = modelStr.toInt();
    switchModel(modelIndex);
    return true;
  }
  
  return false;
}

// 控制任务
void controlTask(void *pvParameters) {
  Command cmd;
  while (1) {
    if (xQueueReceive(xCommandQueue, &cmd, portMAX_DELAY)) {
      if (cmd.device == "led") {
        analogWrite(LED_PIN, cmd.value);
        Serial.printf("[执行] LED亮度设置为: %d\n", cmd.value);
      }
      else if (cmd.device == "servo") {
        int pulseWidth = map(cmd.value, 0, 180, 1000, 5000);
        ledcWrite(1, pulseWidth * 8192 / 20000);
        Serial.printf("[执行] 舵机角度设置为: %d°\n", cmd.value);
      }
    }

    // 喂狗操作
    esp_task_wdt_reset();
  }
}

// 解析JSON响应并提取控制指令
void parseAndQueue(String jsonResponse) {
  DynamicJsonDocument doc(4096); // 根据响应大小调整
  DeserializationError error = deserializeJson(doc, jsonResponse);
  
  if (error) {
    Serial.printf("[错误] JSON解析失败: %s\n", error.c_str());
    Serial.println("[原始响应]: " + jsonResponse);
    return;
  }

  // 提取模型信息
  const char* model = doc["model"];
  const char* id = doc["id"];
  
  // 提取回复内容
  const char* content = doc["choices"][0]["message"]["content"];
  const char* finishReason = doc["choices"][0]["finish_reason"];
  
  // 提取使用情况
  JsonObject usage = doc["usage"];
  int totalTokens = usage["total_tokens"];
  int promptTokens = usage["prompt_tokens"];
  int completionTokens = usage["completion_tokens"];

  Serial.println("\n=== AI回复 ===");
  Serial.printf("模型: %s\n", model);
  Serial.printf("回复ID: %s\n", id);
  Serial.printf("完成状态: %s\n", finishReason);
  Serial.println("--------------");
  Serial.printf("内容: %s\n", content);
  Serial.println("--------------");
  Serial.printf("Token使用: 总计%d (输入%d + 输出%d)\n", totalTokens, promptTokens, completionTokens);
  Serial.println("==============\n");

  // 检查回复内容中是否包含硬件控制指令
  String contentStr = String(content);
  if (contentStr.indexOf("device:") != -1 && contentStr.indexOf("value:") != -1) {
    int deviceStart = contentStr.indexOf("device:") + 7;
    int deviceEnd = contentStr.indexOf(",", deviceStart);
    String device = contentStr.substring(deviceStart, deviceEnd);
    device.trim();

    int valueStart = contentStr.indexOf("value:") + 6;
    int valueEnd = contentStr.indexOf(")", valueStart);
    int value = contentStr.substring(valueStart, valueEnd).toInt();

    // 参数范围验证
    if (device == "led") value = constrain(value, 0, 255);
    if (device == "servo") value = constrain(value, 0, 180);

    Command cmd = {device, value};
    xQueueSend(xCommandQueue, &cmd, 0);
    Serial.printf("[解析] 设备: %s, 值: %d\n", device.c_str(), value);
  }
}

// 发送HTTP请求并获取API响应
String getGPTAnswer(String inputText) {
  HTTPClient http;
  http.setTimeout(15000);  // 增加超时时间以适应不同模型
  http.setReuse(false);
  
  Serial.printf("[请求] 使用模型: %s\n", currentModel.c_str());
  Serial.println("[请求] 发送中...");
  
  http.begin(apiUrl);
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Authorization", apiKey);
  
  // 转义特殊字符
  inputText.replace("\"", "\\\"");
  inputText.replace("\n", "\\n");
  
  String payload = "{\"model\":\"" + currentModel + "\",\"messages\":[{\"role\": \"system\",\"content\": \"" + pre_Text + "\"},{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}";
  
  int httpResponseCode = http.POST(payload);
  
  if (httpResponseCode == 200) {
    String response = http.getString();
    http.end();
    Serial.println("[请求] 响应成功");
    return response;
  } else {
    String errorResponse = http.getString();
    http.end();
    
    // 尝试解析错误响应
    DynamicJsonDocument errorDoc(1024);
    DeserializationError error = deserializeJson(errorDoc, errorResponse);
    
    if (!error && errorDoc.containsKey("error")) {
      const char* errorMessage = errorDoc["error"]["message"];
      Serial.printf("[错误] HTTP代码: %d, 错误信息: %s\n", httpResponseCode, errorMessage);
    } else {
      Serial.printf("[错误] HTTP代码: %d\n", httpResponseCode);
      Serial.println("[错误响应]: " + errorResponse);
    }
    return "<error>";
  }
}

// HTTP请求任务
void httpTask(void *pvParameters) {
  while (1) {
    if (Serial.available()) {
      String userInput = Serial.readStringUntil('\n');
      userInput.trim();

      // 检查是否是系统指令
      if (handleSystemCommand(userInput)) {
        // 系统指令已处理,跳过AI请求
        continue;
      }

      // 普通对话,发送到AI
      Serial.printf("\n[用户] %s\n", userInput.c_str());
      String response = getGPTAnswer(userInput);
      
      if (response != "<error>") {
        parseAndQueue(response);
      } else {
        Serial.println("[错误] API请求失败,请检查网络或模型配置");
      }
    }

    // 喂狗操作
    esp_task_wdt_reset();
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void setup() {
  // Initialize Serial
  Serial.begin(115200);

  // Connect to Wi-Fi network
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
  Serial.println("\nConnected! IP: " + WiFi.localIP().toString());

  initPWM();
  xCommandQueue = xQueueCreate(5, sizeof(Command));

  // 初始化看门狗,设置超时时间为10秒
  esp_task_wdt_init(10, true);
  esp_task_wdt_add(NULL);  // 将当前任务添加到看门狗监控中

  // 创建任务
  xTaskCreatePinnedToCore(controlTask, "Control", 4096, NULL, 2, NULL, 0);
  xTaskCreatePinnedToCore(httpTask, "HTTP", 8192, NULL, 1, NULL, 1);

  Serial.println("\n=== 豆包大模型硬件控制系统 ===");
  Serial.println("系统初始化完成!");
  showModels();
  Serial.println("输入 'help' 查看使用说明");
  Serial.println("============================\n");
}

void loop() {
  // 主循环只负责喂狗
  esp_task_wdt_reset();
  delay(1000);
}

3.2 源码解析

  1. 导入库文件:
   #include <WiFi.h>
   #include <HTTPClient.h>
   #include <ArduinoJson.h>
  1. 定义Wi-Fi网络凭证:
const char *ssid = "IQOO";
const char *password = "12345678";
  1. 定义API Key:
String apiKey = "Bearer 211f9e11-cd39-4a68-b4a605822";

管理APIKEY地址:https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D&projectName=default
在这里插入图片描述

4. 上传验证

下面给出下载配置,请严格配置

4.1 platformio.ini

[env:freenove_esp32_s3_wroom]
platform = espressif32
board = freenove_esp32_s3_wroom
framework = arduino
lib_deps = 
    bblanchon/ArduinoJson@^7.4.2
    madhephaestus/ESP32Servo@^3.0.8

4.2 对话测试

打开串口监视器,注意右下角选择回车符,选择115200波特率,输入你想问的问题,它就可以回答你。

  1. 测试效果
    串口输入:
把舵机转到45度

AI 响应:

(device:servo,value:45)

控制任务输出:

[执行] 舵机角度: 45°

LED 灯控制同理,例如:

灯亮度调成一半

会解析为:

(device:led,value:128)
---- 已打开串行端口 COM11 ----
---- 已发送 utf8 编码消息: "打开灯" ----

[用户] 打开灯
[请求] 使用模型: doubao-seed-1-6-251015
[请求] 发送中...
[请求] 响应成功

=== AI��复 ===
模型: doubao-seed-1-6-251015
回复ID: 0217627879909809e37bd9714fa325a144f80ed4093445ad71550
完成状态: stop
--------------
内容: (device:led,value:255)
--------------
Token使用: 总计167 (输入100 + ���出67)
==============

[解��] 设备: led, 值: 255
[执行] LED亮度设置为: 255
---- 已发送 utf8 编码消息: "current" ----
[系统] 当前使用模型: doubao-seed-1-6-251015 (编号: 0)
---- 已发送 utf8 编码消息: "model 1" ----
[系统] 已切换到模型: doubao-seed-1-6-flash-250828
---- 已发送 utf8 编码消息: "关闭灯" ----

[用户] 关闭灯
[请求] 使用模型: doubao-seed-1-6-flash-250828
[请求] 发送中...
[请求] 响应成功

=== AI��复 ===
模型: doubao-seed-1-6-flash-250828
回复ID: 021762788015747aca79f59198e4bdac01b72c58693596351fc26
完成状态: stop
--------------
内容: LED控制(device:led,value:0)
--------------
Token使用: 总计230 (输入151 + 输出79)
==============

[解析] 设备: led, 值: 0
[执行] LED亮度设置为: 0
---- 已发送 utf8 编码消息: "你是谁" ----

[用户] 你是谁
[请求] 使用模型: doubao-seed-1-6-flash-250828
[请求] 发送中...
[请求] 响应成功

=== AI��复 ===
模型: doubao-seed-1-6-flash-250828
回复ID: 02176278804095142a36b1033b5cf9f6429381c66119fa7b8d13e
完成状态: stop
--------------
内容: 我是字节跳动研发的人工智��豆包,能够为你提供信���咨询、知识解答、生活建议等方面的帮助。如��你有硬件控制相关的需���,比如控制灯或舵机,可以按照指定格式提供��令。
--------------
Token使用: 总计260 (输入151 + 输���109)
==============


存在舵机峰值电流过大导致重启,可额外供电。有时候会因为网络无法控制,导致指令失败,建议换一个好一点的2.4G网络,本项目演示了ESP32 + 国产大模型 + 自然语言控制硬件的完整流程,适合智能家居、机器人等场景。
后续可以优化:

  • 增加更多外设(风扇、电机、继电器等)
  • 用 WebSocket 代替 HTTP 提升响应速度
  • 在 ESP32 上做离线指令解析以减少网络依赖

有了这个基础,你的 ESP32 就能听懂人话啦!

4.3 错误码

如果执行报错,请参见错误信息进行解决。

5. 总结

现在,本项目演示了ESP32 + 豆包最新大模型 + 自然语言控制硬件的完整流程,适合智能家居、机器人等场景。从而实现对外部世界的感知,充分认识这个有机与无机的环境,后期会持续分享ESP32跑FreeRTOS实用案例,为人类社会发展贡献一点微薄之力。🙌🙌🙌

如果你有任何问题,可以通过Q Group(945348278)加入鹏鹏小分队,期待与你思维的碰撞! 😘😘😘

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐