这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » ATOMS3R-CAM AI CHATBOT 开发指南【语音底座使用之录音机】

共1条 1/1 1 跳转至

ATOMS3R-CAM AI CHATBOT 开发指南【语音底座使用之录音机】

助工
2026-05-30 22:08:03     打赏

摘要:本文主要介绍开发板搭配的语音底座(Atomic Voice Base)的使用方法,实现一个通过串口输入任意按键开始/停止录制音频,并实时显示当前录制时长的录音机功能;

一、硬件介绍

产品特点

AtomS3R-CAM AI Chatbot 套件由控制器与语音底座两大核心部分组成;

控制器部分采用AtomS3R-CAM (集成0.3MP GC0308摄像头、9轴IMU、IR发射管等);

语音底座部分采用Atomic Voice Base (基于ES831音频编解码芯片);


1780149171452643.png

image-20260504212417200


主要特性

  • 集成 ESP32-S3-PICO-1-N8R8 主控

  • 0.3MP GC0308 摄像头

  • 九轴传感器系统

  • 8MB Flash 和 8MB PSRAM

  • 集成红外发射管

  • 可扩展的引脚与接口

  • 全双工 I2S 语音

  • MEMS 数字麦克风



功能引脚示意图

image-20260504213854017.png

image-20260504213854017





二、功能实现

1、硬件介绍

Atomic Voice Base 是一款专为 M5 Atom 系列主机设计的语音识别底座,采用了ES8311单声道音频解码器、MEMS麦克风和NS4150B功率放大器,该设备支持全双工通信;


image-20260521114630339.png



主要特性

  • 单声道音频编解码

  • MEMS 麦克风

  • D类功放扬声器


引脚原理图

MIC / Speaker:Atomic Voice Base 麦克风支持的采样率范围为 16KHz-64KHz;


Sch_ECHO_Base_v1.0_page_01.png


特性


image.png


实物效果搭建


image-20260521162630868.png


2、功能效果

1、安装Arduino 底座驱动库

M5Atomic-EchoBase

image-20260521115251868

image-20260521115251868.png



功能:通过串口输入任意按键开始/停止录制音频,并实时显示当前录制时长的录音机效果;

  • 按任意键 → 开始录制

  • 再次按任意键 → 停止录制

  • 按任意键 → 播放录制内容

  • 循环到第1步 (若录制达到60秒自动停止,循环至第3步)






三、代码编写

相关代码

#include <M5Unified.h>
#include <M5EchoBase.h>

// 音频参数配置
#define SAMPLE_RATE 16000
#define MAX_RECORD_SECONDS 60
#define MIC_GAIN ES8311_MIC_GAIN_6DB

M5EchoBase echobase;

static uint8_t *buffer = nullptr;
static uint32_t actual_record_size = 0;
static uint32_t actual_record_seconds = 0;

// 等待按键按下
void waitForKeyPress(const char *prompt) {
    Serial.println(prompt);
    while (!Serial.available()) {
        M5.update();
        delay(10);
    }
    while (Serial.available()) { Serial.read(); }
}

// 检查是否有按键按下
bool isKeyPressed() {
    if (Serial.available()) {
        while (Serial.available()) { Serial.read(); }
        return true;
    }
    return false;
}

void setup() {
    auto cfg = M5.config();
    cfg.serial_baudrate = 115200;
    M5.begin(cfg);
    delay(1000);

    while (Serial.available()) { Serial.read(); }

    // 初始化 EchoBase
    Serial.print("正在初始化 EchoBase... ");
    if (!echobase.init(SAMPLE_RATE, 38, 39, 7, 6, 5, 8, Wire)) {
        Serial.println("初始化失败!");
        while (true) { delay(1000); }
    }
    Serial.println("初始化成功!");

    echobase.setSpeakerVolume(70);
    echobase.setMicGain(MIC_GAIN);
    echobase.setMute(true);

    uint32_t buffer_size = echobase.getBufferSize(MAX_RECORD_SECONDS, SAMPLE_RATE);
    
    // 检查内存
    size_t psram_free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
    if (psram_free < buffer_size) {
        Serial.printf("PSRAM 不足!需要: %d, 可用: %d\n", buffer_size, psram_free);
        while (true) { delay(1000); }
    }

    buffer = (uint8_t *)malloc(buffer_size);
    if (!buffer) {
        Serial.println("内存分配失败!");
        while (true) { delay(1000); }
    }
    Serial.printf("缓冲区分配成功 (%.1f KB)\n", buffer_size / 1024.0);

    Serial.println("\n===== 功能说明 =====");
    Serial.println("1. 按任意键 → 开始录制");
    Serial.println("2. 按任意键 → 停止录制");
    Serial.println("3. 按任意键 → 播放录制内容");
    Serial.println("4. 循环到第1步");
    Serial.println("(录制达到60秒自动停止,进入第3步)");
    Serial.println("====================\n");
}

void loop() {
    waitForKeyPress("按任意键开始录制...");

    Serial.println("\n===== 开始录制 =====");
    Serial.println("(按任意键停止,最长60秒)");

    echobase.setMute(true);
    delay(50);

    // 每次录制前重置
    actual_record_size = 0;
    actual_record_seconds = 0;
    bool stopped_by_user = false;

    uint32_t chunk_size = echobase.getBufferSize(1, SAMPLE_RATE);
    uint8_t *chunk_buffer = (uint8_t *)malloc(chunk_size);

    if (!chunk_buffer) {
        Serial.println("分段缓冲区分配失败!");
        return;
    }

    while (actual_record_seconds < MAX_RECORD_SECONDS) {
        if (!echobase.record(chunk_buffer, chunk_size)) {
            Serial.println("录音失败!");
            free(chunk_buffer);
            return;
        }

        memcpy(buffer + actual_record_size, chunk_buffer, chunk_size);
        actual_record_size += chunk_size;
        actual_record_seconds++;

        Serial.printf("录制中: %d 秒\n", actual_record_seconds);

        if (isKeyPressed()) {
            stopped_by_user = true;
            Serial.println("检测到按键,停止录制!");
            break;
        }
    }

    free(chunk_buffer);

    if (actual_record_seconds >= MAX_RECORD_SECONDS && !stopped_by_user) {
        Serial.println("已达到最大录制时长 (60秒)");
    }

    Serial.printf("录制完成: %d 秒, %d 字节 (%.1f KB)\n",
                  actual_record_seconds, actual_record_size, actual_record_size / 1024.0);
    Serial.printf("PSRAM 剩余: %.1f MB\n\n",
                  heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / (1024.0 * 1024.0));

    if (actual_record_size == 0) {
        Serial.println("没有录制任何内容\n");
        return;
    }

    waitForKeyPress("按任意键播放录音...");

    Serial.println("\n===== 开始播放 =====");
    echobase.setMute(false);
    delay(50);

    if (!echobase.play(buffer, actual_record_size, false)) {
        Serial.println("播放失败!");
        echobase.setMute(true);
        return;
    }

    Serial.println("播放完成!\n");

    echobase.setMute(true);
    delay(200);
}




四、程序烧录

1、连接USB数据线至开发板;

2、选择端口号对应的开发板;

3、点击 上传 烧录程序到开发板上;

image-20260518203300906.png




五、效果演示


效果演示视频


image-20260522173741422.png











关键词: ATOMS3R-CAM    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]