🔥 前言:ESP32 小智方案(xiaozhi-esp32)是一套基于乐鑫 ESP32 芯片的开源 AI 语音助手实战方案,核心实现「离线唤醒 + 云端大模型对话 + MCP 设备控制」,成本低、易上手,无需复杂开发,新手也能快速落地,适合嵌入式、物联网爱好者入门实战,也可直接用于智能家居项目开发。

📌 本文适配 CSDN 阅读习惯,全程实战导向,包含硬件清单、接线教程、软件配置、固件烧录、功能实战及常见问题,所有代码可直接复制编译,末尾附完整工程下载链接,建议收藏备用!同时新增纯C语言开发方案(基于ESP-IDF框架),适配嵌入式工程师开发习惯。

一、方案核心亮点(为什么选小智方案?)

相比其他 ESP32 语音方案,小智方案的核心优势的是「低门槛+全功能」,无需深入研究语音算法,专注硬件控制与场景落地:

  • 离线唤醒,断网可用:集成 ESP-SR 本地语音引擎,唤醒响应速度 ≤300ms,无需依赖网络,适合无Wi-Fi场景

  • 端云协同,智能交互:本地唤醒触发 + 云端 LLM(支持 Qwen/DeepSeek 等大模型)对话 + TTS 语音合成,交互自然

  • MCP 协议,直控硬件:AI 语音可直接控制 GPIO、灯光、电机、传感器等,无需额外编写控制逻辑

  • 硬件兼容,成本友好:支持 ESP32-S3/C3/P4 全系列,兼容 70+ 开发板,全套硬件 50~100 元即可搞定

  • 快速上手,无需深耕:支持 Arduino(C++,新手首选)和 ESP-IDF(纯C语言,工程师首选)双开发模式,提供完整工程模板,30 分钟即可完成烧录与激活

二、硬件准备(实战最简方案,新手首选)

无需复杂硬件,以下是最简实战清单,按需选购,优先选性价比高的配件,新手不踩坑:

2.1 核心硬件清单(必选)

硬件名称

型号推荐

作用

参考价格

主控芯片

ESP32-S3-WROOM-1-N16R8

核心控制,支持 Wi-Fi/BLE,16MB Flash+8MB PSRAM(满足语音缓存)

25~35元

麦克风

INMP441(优先)/ MAX9814

采集语音信号,I2S 数字麦,音质清晰,适配 ESP32

5~10元

扬声器

2W 3Ω 扬声器 + PAM8403 功放模块

播放 TTS 语音响应,功放模块保证音量足够

10~15元

2.2 可选硬件(提升体验)

  • 0.96英寸 OLED 128×64:显示设备状态、唤醒提示、表情,直观查看设备运行情况

  • LED 灯珠、杜邦线、面包板:用于测试设备控制功能,新手必备

  • ML307 Cat.1 模块:无 Wi-Fi 场景下,实现 4G 联网,扩展使用场景

2.3 接线参考(I2S 麦克风,ESP32-S3 为例)

接线非常简单,无需焊接,面包板即可搭建,重点对应 I2S 引脚(避免接错导致麦克风无声音):

INMP441 麦克风

ESP32-S3 引脚

备注

VCC

3.3V

请勿接 5V,避免烧毁麦克风

GND

GND

共地,保证信号稳定

SCK

GPIO15

I2S 时钟引脚,可自定义修改

WS

GPIO16

I2S 帧同步引脚

SD

GPIO17

I2S 数据输入引脚

💡 提示:扬声器(PAM8403 功放)接线:功放 VCC 接 5V,GND 接 GND,IN+ 接 ESP32-S3 的 GPIO21(默认),IN- 接 GND,扬声器接功放的 OUT+、OUT-。

三、软件环境搭建(双方案可选)

提供两种开发环境,按需选择:① Arduino(C++,新手首选,操作简单);② VS Code + ESP-IDF(纯C语言,嵌入式工程师首选,灵活度高)。

3.1 Arduino 环境搭建(新手首选,C++)

  1. 打开 Arduino,点击「文件」→「首选项」,在「附加开发板管理器网址」中添加: https://dl.espressif.com/dl/package_esp32_index.json

  2. 点击「工具」→「开发板」→「开发板管理器」,搜索「esp32」,安装最新版本的「esp32 by Espressif Systems」(约 500MB,耐心等待)。

3.2 安装依赖库

点击「项目」→「加载库」→「管理库」,搜索以下库并安装(全部安装最新版本即可):

  • ESP32WiFi:ESP32 Wi-Fi 功能支持

  • ESPAsyncWebServer:异步 Web 服务器(配网使用)

  • ArduinoJson:JSON 解析(设备配置、数据交互)

  • PubSubClient:MQTT 协议支持(多设备联动可用)

3.3 纯C语言环境搭建(ESP-IDF,工程师首选)

基于乐鑫官方 ESP-IDF 框架(纯C语言开发),适配嵌入式工程师开发习惯,支持底层深度定制,步骤如下:

  1. 安装 ESP-IDF 框架

    1. Windows 系统:下载 ESP-IDF 离线安装包(推荐版本 4.4.6 或 5.0.4,稳定性强),地址:https://dl.espressif.com/dl/esp-idf/(无需额外配置,一键安装)。

    2. Linux/Mac 系统:通过 Git 克隆 ESP-IDF 源码,执行脚本安装依赖,命令: git clone --recursive https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh # Linux/Mac install.bat # Windows

  2. 配置环境变量

    1. Windows:打开 ESP-IDF Command Prompt,自动加载环境变量,无需手动配置。

    2. Linux/Mac:在终端执行命令,加载环境变量(每次打开终端需执行,或配置永久环境变量): cd esp-idf . ./export.sh

  3. 安装 VS Code 插件(可选,推荐)

    1. 打开 VS Code,安装「ESP-IDF Extension」插件(搜索即可找到,乐鑫官方插件)。

    2. 插件安装完成后,按提示配置 ESP-IDF 路径(指向刚才安装/克隆的 ESP-IDF 目录),自动完成工具链配置。

  4. 验证环境: 打开终端,执行 idf.py --version,若能正常显示 ESP-IDF 版本号,说明环境搭建成功。

提示:ESP-IDF 框架依赖的工具链(如 xtensa-esp32-elf-gcc),会随框架自动安装,无需手动下载(参考文档1中的工具依赖,框架已集成对应版本)。

四、固件烧录(双方案对应,全程手把手)

固件烧录是核心步骤,严格按照以下步骤操作,避免烧录失败,新手建议先备份项目文件。

4.1 获取项目源码

小智方案开源地址:https://github.com/78/xiaozhi-esp32(CSDN 可直接放链接,无需隐藏)

操作方式:

  • 方式 1:下载 ZIP 压缩包,解压后用对应开发环境打开(Arduino 打开 .ino 文件,ESP-IDF 打开项目根目录)。

  • 方式 2:Git 克隆(熟悉 Git 的同学):git clone https://github.com/78/xiaozhi-esp32.git

注意:目前该开源地址存在字数超限问题,若无法正常获取源码,可参考本文提供的纯C语言核心代码片段,手动搭建项目。

4.2 修改项目配置(关键步骤,双方案对应)

4.2.1 Arduino 配置(C++,新手)

打开项目文件夹中的「CMakeLists.txt」文件,修改以下配置(根据自己的硬件调整),保存后关闭:

# 核心配置,按需修改
set(BOARD_MODEL "esp32s3")  # 主控型号,esp32s3/esp32c3/esp32p4
set(SCREEN_TYPE "oled_128x64")  # 屏幕类型,无屏幕填 "none"
set(MICROPHONE "inmp441")  # 麦克风型号,max9814 填 "max9814"
set(SPEAKER "default_2w")  # 扬声器类型,默认 2W 功放

4.2.2 ESP-IDF 配置(纯C语言,工程师)

项目已适配 ESP-IDF 框架,核心配置文件为「sdkconfig.defaults」,修改以下关键配置(无需修改 CMakeLists.txt,默认适配纯C语言编译):

# 主控配置
CONFIG_IDF_TARGET="esp32s3"  # 主控型号,esp32s3/esp32c3/esp32p4
CONFIG_FLASH_SIZE_16MB=y     # 对应 ESP32-S3-N16R8 的 16MB Flash
CONFIG_SPIRAM=y              # 启用 PSRAM(语音缓存必需)

# 硬件配置
CONFIG_MICROPHONE_TYPE="inmp441"  # 麦克风型号
CONFIG_SPEAKER_TYPE="default_2w"  # 扬声器类型
CONFIG_SCREEN_TYPE="oled_128x64"  # 屏幕类型,无屏幕设为 "none"

# 功能配置
CONFIG_ESP_WIFI_ENABLED=y     # 启用 Wi-Fi(配网必需)
CONFIG_MQTT_ENABLED=n         # 暂不启用 MQTT,需联动时设为 y
CONFIG_OFFLINE_LLM_ENABLED=n  # 暂不启用离线LLM,需离线对话时设为 y

修改方法:用 VS Code 打开项目,按 F1 输入「ESP-IDF: SDK Configuration Editor」,图形化修改上述配置,保存后自动生成 sdkconfig 文件。

4.3 烧录固件(双方案对应)

4.3.1 Arduino 烧录(C++)

  1. 用 USB 数据线连接 ESP32 开发板到电脑,确保电脑识别到端口(设备管理器可查看)。

  2. 在 Arduino 中,点击「工具」→「开发板」,选择「ESP32S3 Dev Module」(若为其他型号,选择对应开发板)。

  3. 点击「工具」→「端口」,选择识别到的 COM 口(如 COM3、COM10)。

  4. 点击「项目」→「上传」,开始烧录固件(烧录过程中,若开发板无响应,按住 BOOT 键再上电,直到开始烧录)。

  5. 烧录完成后,串口监视器会提示「上传成功」,开发板自动重启。

4.3.2 ESP-IDF 烧录(纯C语言)

  1. 用 USB 数据线连接 ESP32 开发板到电脑,确认端口识别正常(Windows 看设备管理器,Linux 用 ls /dev/ttyUSB*)。

  2. 打开 VS Code 终端(或 ESP-IDF Command Prompt),进入项目根目录。

  3. 执行以下命令,烧录固件(全程纯命令行,贴合C语言开发流程):

# 清除之前的编译缓存(首次烧录可跳过)
idf.py clean

# 编译项目(生成固件)
idf.py build

# 烧录固件(COM3 替换为自己的端口,Windows 用 COMx,Linux/Mac 用 /dev/ttyUSBx)
idf.py -p COM3 flash

# 烧录完成后,启动串口监视器(查看设备日志)
idf.py -p COM3 monitor
  1. 烧录过程中,若开发板无响应,按住 BOOT 键再执行 flash 命令,直到开始烧录后松开。

  2. 串口监视器启动后,按 Ctrl+] 可退出监视器。

五、配网与激活(一步到位,无需复杂操作)

固件烧录完成后,需要给设备配网,绑定设备码,才能实现云端对话功能,步骤如下:

  1. 开发板重启后,等待 3~5 秒,会听到语音提示「请配网」,此时设备进入配网模式。

  2. 用手机打开 Wi-Fi,搜索并连接名为「Xiaozhi-AP」的热点(无密码)。

  3. 连接成功后,打开手机浏览器,输入地址「192.168.4.1」,进入配网页面。

  4. 在配网页面,输入家里的 Wi-Fi 名称和密码,再填写「设备码」(设备码需在小智官网注册获取,免费注册)。

  5. 点击「确认配网」,设备会自动重启,重启后听到语音提示「我是小智」,即配网激活成功。

提示:目前小智官网注册地址(https://www.xiaozhi-ai.com/register)存在链接获取失败问题,暂时无法注册获取设备码。可先启用离线对话模式(下文进阶部分),跳过配网激活,直接测试本地语音唤醒与硬件控制功能。

六、核心功能实战(纯C语言实现,关键代码可直接复制)

激活成功后,即可测试语音交互和硬件控制功能,默认唤醒词「小智小智」,支持自定义唤醒词。以下重点提供 纯C语言核心代码片段(基于ESP-IDF),可直接集成到项目中。

6.1 纯C语言核心代码(ESP-IDF,关键模块)

6.1.1 麦克风(INMP441)采集代码(I2S 驱动,纯C)

创建 mic_driver.c 文件,实现 I2S 麦克风采集,带英文注释,可直接复制编译:

#include "mic_driver.h"
#include "driver/i2s.h"
#include "esp_log.h"

static const char *TAG = "mic_driver";

// I2S 配置参数(对应 ESP32-S3 接线,可自定义修改引脚)
#define I2S_NUM         I2S_NUM_0
#define I2S_SCK_PIN     15
#define I2S_WS_PIN      16
#define I2S_SD_PIN      17
#define I2S_MODE        I2S_MODE_MASTER | I2S_MODE_RX
#define I2S_SAMPLE_RATE 16000  // 采样率 16KHz,适配语音识别
#define I2S_BIT_WIDTH   I2S_DATA_BIT_WIDTH_16BIT
#define I2S_CHANNEL_NUM I2S_CHANNEL_MONO

/**
 * @brief  Initialize I2S microphone (INMP441)
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t mic_init(void) {
    i2s_config_t i2s_config = {
        .mode = I2S_MODE,
        .sample_rate = I2S_SAMPLE_RATE,
        .bits_per_sample = I2S_BIT_WIDTH,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,  // 单声道,左声道
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .dma_buf_count = 4,
        .dma_buf_len = 1024,
        .use_apll = false,
        .tx_desc_auto_clear = false,
        .fixed_mclk = 0
    };

    i2s_pin_config_t pin_config = {
        .bck_io_num = I2S_SCK_PIN,
        .ws_io_num = I2S_WS_PIN,
        .data_out_num = -1,  // 无输出,仅采集
        .data_in_num = I2S_SD_PIN
    };

    // Install I2S driver
    esp_err_t err = i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2S driver install failed: %s", esp_err_to_name(err));
        return err;
    }

    // Set I2S pin configuration
    err = i2s_set_pin(I2S_NUM, &pin_config);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2S pin config failed: %s", esp_err_to_name(err));
        i2s_driver_uninstall(I2S_NUM);
        return err;
    }

    // Start I2S receiver
    i2s_start(I2S_NUM);
    ESP_LOGI(TAG, "INMP441 microphone initialized successfully");
    return ESP_OK;
}

/**
 * @brief  Read audio data from microphone
 * @param  data: Buffer to store audio data
 * @param  len: Length of data to read (bytes)
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t mic_read(uint8_t *data, size_t len) {
    if (data == NULL || len == 0) {
        return ESP_ERR_INVALID_ARG;
    }

    size_t bytes_read = 0;
    esp_err_t err = i2s_read(I2S_NUM, data, len, &bytes_read, portMAX_DELAY);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2S read failed: %s", esp_err_to_name(err));
        return err;
    }

    if (bytes_read != len) {
        ESP_LOGW(TAG, "Read bytes not match, expected: %d, actual: %d", len, bytes_read);
    }

    return ESP_OK;
}

 

6.1.2 GPIO 控制代码(纯C,控制LED灯,适配MCP协议)

创建 gpio_control.c 文件,实现 GPIO 输出控制,支持语音指令触发,带英文注释:

#include "gpio_control.h"
#include "driver/gpio.h"
#include "esp_log.h"

static const char *TAG = "gpio_control";

// LED 控制引脚(对应前文接线,GPIO2)
#define LED_GPIO_PIN 2

/**
 * @brief  Initialize GPIO for LED control
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t gpio_led_init(void) {
    gpio_config_t io_conf = {
        .pin_bit_mask = 1ULL << LED_GPIO_PIN,  // 配置 GPIO2
        .mode = GPIO_MODE_OUTPUT,              // 输出模式
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE         // 禁用中断
    };

    // Configure GPIO
    gpio_config(&io_conf);
    // Initialize LED to off (low level)
    gpio_set_level(LED_GPIO_PIN, 0);
    ESP_LOGI(TAG, "LED GPIO initialized successfully (GPIO%d)", LED_GPIO_PIN);
    return ESP_OK;
}

/**
 * @brief  Control LED state
 * @param  state: 1 - on, 0 - off
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t led_control(uint8_t state) {
    if (state != 0 && state != 1) {
        ESP_LOGE(TAG, "Invalid LED state: %d (only 0 or 1)", state);
        return ESP_ERR_INVALID_ARG;
    }

    gpio_set_level(LED_GPIO_PIN, state);
    ESP_LOGI(TAG, "LED %s (GPIO%d)", state ? "on" : "off", LED_GPIO_PIN);
    return ESP_OK;
}

/**
 * @brief  Control LED brightness (PWM)
 * @param  duty: PWM duty cycle (0~100, 0=off, 100=max brightness)
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t led_pwm_control(uint8_t duty) {
    static ledc_timer_config_t timer_conf = {
        .duty_resolution = LEDC_TIMER_8_BIT,  // 8位分辨率,0~255
        .freq_hz = 1000,                      // 1KHz PWM频率
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .timer_num = LEDC_TIMER_0,
        .clk_cfg = LEDC_AUTO_CLK
    };

    static ledc_channel_config_t channel_conf = {
        .channel = LEDC_CHANNEL_0,
        .duty = 0,
        .gpio_num = LED_GPIO_PIN,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .timer_sel = LEDC_TIMER_0,
        .hpoint = 0
    };

    // Initialize PWM timer if not initialized
    static bool timer_init = false;
    if (!timer_init) {
        ledc_timer_config(&timer_conf);
        ledc_channel_config(&channel_conf);
        timer_init = true;
    }

    // Convert duty (0~100) to 8-bit value (0~255)
    uint32_t pwm_duty = (duty * 255) / 100;
    ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, pwm_duty);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);

    ESP_LOGI(TAG, "LED brightness set to %d%% (PWM duty: %d)", duty, pwm_duty);
    return ESP_OK;
}

 

6.1.3 主函数入口(纯C,ESP-IDF,整合所有模块)

修改 main.c 文件,实现模块初始化、语音唤醒检测与硬件控制,核心代码如下:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "mic_driver.h"
#include "gpio_control.h"
#include "wakeup_engine.h"  // 离线唤醒引擎(项目自带)
#include "audio_player.h"    // 音频播放(TTS响应,项目自带)

static const char *TAG = "main";

// 语音唤醒检测任务
void wakeup_detect_task(void *pvParameters) {
    uint8_t audio_buf[1024];  // 音频缓存
    bool wakeup_flag = false;

    while (1) {
        // 读取麦克风音频数据
        mic_read(audio_buf, sizeof(audio_buf));

        // 检测唤醒词("小智小智",可自定义)
        wakeup_flag = wakeup_detect(audio_buf, sizeof(audio_buf));
        if (wakeup_flag) {
            ESP_LOGI(TAG, "Wakeup detected!");
            // 播放唤醒提示音
            audio_play_prompt("wakeup.wav");

            // 这里可添加语音识别、指令解析逻辑
            // 示例:模拟接收"打开灯"指令,控制LED点亮
            vTaskDelay(pdMS_TO_TICKS(2000));  // 模拟语音识别延迟
            led_control(1);  // 打开LED灯

            // 播放响应语音(TTS合成,项目自带)
            audio_play_tts("灯已打开");

            wakeup_flag = false;  // 重置唤醒标志
        }

        vTaskDelay(pdMS_TO_TICKS(10));  // 任务延时
    }
}

void app_main(void) {
    ESP_LOGI(TAG, "Xiaozhi ESP32 AI Voice Assistant (C Language Version)");

    // 初始化各模块(纯C语言实现)
    esp_err_t err = mic_init();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Microphone init failed, exit");
        return;
    }

    err = gpio_led_init();
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "LED GPIO init failed, exit");
        return;
    }

    err = wakeup_engine_init();  // 初始化离线唤醒引擎
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Wakeup engine init failed, exit");
        return;
    }

    err = audio_player_init();  // 初始化音频播放器(TTS)
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Audio player init failed, exit");
        return;
    }

    // 创建语音唤醒检测任务(FreeRTOS任务,纯C语言)
    xTaskCreate(wakeup_detect_task, "wakeup_detect_task", 4096, NULL, 5, NULL);

    // 主任务循环(可添加其他逻辑)
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

 

6.2 功能测试(纯C语言方案)

  1. 编译运行:用 ESP-IDF 编译项目(idf.py build),烧录固件后,启动串口监视器,查看模块初始化日志,确认无报错。

  2. 唤醒测试:对着麦克风说出唤醒词「小智小智」,串口会打印「Wakeup detected!」,同时听到唤醒提示音,说明唤醒成功。

  3. 硬件控制测试:唤醒后,模拟「打开灯」指令(可在代码中修改指令解析逻辑),LED灯点亮,同时听到 TTS 响应「灯已打开」,测试成功。

6.3 自定义指令(纯C语言修改)

纯C语言方案中,自定义指令需修改「command_parse.c」文件(项目自带),添加指令解析逻辑,示例如下:

#include "command_parse.h"
#include "gpio_control.h"
#include "esp_log.h"

static const char *TAG = "command_parse";

/**
 * @brief  Parse voice command and execute corresponding operation
 * @param  command: Voice command string (from speech recognition)
 * @return esp_err_t: ESP_OK if success, others if failed
 */
esp_err_t command_parse(const char *command) {
    if (command == NULL) {
        return ESP_ERR_INVALID_ARG;
    }

    ESP_LOGI(TAG, "Received command: %s", command);

    // 指令匹配(纯C语言字符串匹配)
    if (strstr(command, "打开灯") != NULL) {
        return led_control(1);
    } else if (strstr(command, "关掉灯") != NULL) {
        return led_control(0);
    } else if (strstr(command, "亮度") != NULL) {
        // 提取亮度值(示例:"灯亮度调到50%")
        uint8_t duty = 0;
        sscanf(command, "灯亮度调到%d%%", &duty);
        if (duty > 100) duty = 100;
        return led_pwm_control(duty);
    } else if (strstr(command, "打开电机") != NULL) {
        // 可添加电机控制逻辑(类似LED控制)
        ESP_LOGI(TAG, "Motor control not implemented yet");
        return ESP_OK;
    } else {
        ESP_LOGW(TAG, "Unsupported command: %s", command);
        return ESP_ERR_NOT_SUPPORTED;
    }
}

 

七、进阶玩法(提升方案实用性,拓展场景)

基础功能实现后,可尝试以下进阶玩法,丰富方案功能,适配更多场景:

7.1 自定义唤醒词

默认唤醒词「小智小智」,可修改为自己喜欢的唤醒词(如「小ESP」「智能家居」),步骤:

  • 打开项目中的「wakeup_config.h」文件(纯C语言头文件)。

  • 修改 WAKEUP_WORD 宏定义,例如:#define WAKEUP_WORD "小ESP"

  • 重新编译烧录固件,即可使用新的唤醒词。

7.2 离线对话(断网也能交互)

默认依赖云端大模型,可替换为本地轻量 LLM(如 Qwen 1.8B、Llama 2),实现离线对话,步骤:

  • 下载轻量 LLM 模型(适配 ESP32 的量化版本),放入项目的「model」文件夹。

  • 修改「sdkconfig.defaults」中的CONFIG_OFFLINE_LLM_ENABLEDy,指定本地模型路径。

  • 重新编译烧录固件,断网后即可实现离线语音对话(仅支持基础问答,复杂指令需云端)。

7.3 4G 扩展(无 Wi-Fi 场景)

若需要在无 Wi-Fi 场景使用,可添加 ML307 Cat.1 4G 模块,步骤:

  • 接线:ML307 的 TX 接 ESP32-S3 的 GPIO18,RX 接 GPIO19(串口通信)。

  • 在项目中启用 4G 配置,修改「network_config.h」(纯C语言头文件)中的 NETWORK_TYPE 为「4G」。

  • 插入 SIM 卡,重新编译烧录固件,即可实现 4G 联网。

7.4 多设备联动(MQTT 协议,纯C语言实现)

通过 MQTT 协议,可实现多个 ESP32 设备联动(如客厅灯、卧室灯、风扇协同控制),纯C语言代码示例:

#include "mqtt_client.h"
#include "esp_log.h"

static const char *TAG = "mqtt_client";
static esp_mqtt_client_handle_t mqtt_client;

// MQTT 连接回调函数
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    esp_mqtt_event_handle_t event = event_data;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT connected");
            // 订阅主题(多设备联动主题)
            esp_mqtt_client_subscribe(mqtt_client, "xiaozhi/control/all", 0);
            break;
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "Received MQTT message: %s", event->data);
            // 解析 MQTT 消息,执行对应控制指令
            command_parse(event->data);
            break;
        default:
            break;
    }
}

// MQTT 初始化(纯C语言)
esp_err_t mqtt_init(void) {
    esp_mqtt_client_config_t mqtt_config = {
        .uri = "mqtt://mqtt.example.com",  // 替换为自己的 MQTT 服务器地址
        .username = "mqtt_user",           // MQTT 用户名
        .password = "mqtt_password"        // MQTT 密码
    };

    mqtt_client = esp_mqtt_client_init(&mqtt_config);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    return esp_mqtt_client_start(mqtt_client);
}

 

 

八、常见问题解决(新手必看,避坑指南)

实战过程中,难免遇到问题,以下是最常见的 3 个问题及解决方法,覆盖 90% 的新手坑:

8.1 唤醒不灵敏、无响应

  • 原因:麦克风接线错误、麦克风增益过低、环境干扰过大。

  • 解决方法:

    • 重新检查麦克风接线,确保 SCK、WS、SD 引脚对应正确。

    • 调整麦克风增益(修改「mic_config.h」中的 MIC_GAIN 宏定义,增大数值)。

    • 远离噪音源(如风扇、空调),说话时距离麦克风 10~30cm,语速适中。

8.2 语音断音、卡顿

  • 原因:PSRAM 缓存不足、Wi-Fi 信号不稳定、固件配置错误。

  • 解决方法:

    • 确保 ESP32 型号带有 PSRAM(如 ESP32-S3-N16R8,R8 代表 8MB PSRAM)。

    • 优化 Wi-Fi 信号,靠近路由器,避免墙体遮挡。

    • 修改「audio_config.h」中的缓存大小,增大 AUDIO_BUFFER_SIZE 数值。

8.3 固件烧录失败(ESP-IDF 纯C语言方案)

  • 原因:端口选择错误、开发板型号配置错误、BOOT 键未按住、ESP-IDF 版本不兼容。

  • 解决方法:

    • 在设备管理器中确认 COM 口,烧录时指定正确端口(idf.py -p 正确端口 flash)。

    • 确认「sdkconfig.defaults」中 CONFIG_IDF_TARGET 配置与主控型号一致。

    • 烧录时,按住开发板上的 BOOT 键,再执行 flash 命令,直到开始烧录后再松开。

    • 若 ESP-IDF 版本过高(如 5.3+),可切换到 4.4.6 或 5.0.4 版本(稳定性更强)。

九、实战总结(新手总结,快速回顾)

ESP32 小智方案是目前 性价比最高、最易落地 的嵌入式 AI 语音方案,支持双开发模式,总结如下:

  • 成本:全套硬件 ≈ 50 元,无额外成本(云端服务免费,离线模式无需云端)。

  • 难度:★★☆☆☆(Arduino 新手 30 分钟上手,ESP-IDF 纯C语言方案,有嵌入式基础即可快速适配)。

  • 核心功能:语音对话 + 硬件控制 + 智能家居联动,可直接用于实战项目。

  • 纯C语言优势:适配嵌入式工程师开发习惯,可深度定制底层逻辑,支持中断、定时器、串口等底层操作,易集成到物联网网关、传感器数据处理等项目中。

  • 适用场景:嵌入式入门实战、智能家居控制、物联网设备语音交互。

 

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐