💡 划重点

  • 用 ESP32 做主控,INMP441 采音、MAX98357A 放音,全部走 I2S 数字链路,底噪低、接线少。
  • 拼图块识别不靠摄像头,靠拼图底座上的轻触/磁簧触点组合映射“拼图 ID”,成本低且对幼儿友好。
  • 语音复读做“短句录制 + 变调回放”:孩子拼对一块,机器人用卡通音复述该块名称,强化认知闭环。
  • SD 卡存放预置语音与录音缓存,离线可用,不依赖网络,适合家庭与幼儿园场景。
  • 整机物料控制在 85 元内,外壳用 3D 打印或纸盒改造,适合亲子共创。

需求洞察

目标用户是 3 至 6 岁儿童及其家长、幼儿园教师。这个年龄段的孩子注意力短、识字量低,传统拼图只有“拼对/拼错”的视觉反馈,缺少语言强化;而市面上的语音玩具多为固定音效,不能跟随拼图内容变化,孩子玩两三次就失去兴趣。

真实痛点有三:其一,家长希望孩子在玩中练习发音与词汇,但陪玩时间有限,需要设备能“接话”;其二,幼儿对机械按键和屏幕不敏感,需要“放上去就有反应”的直接交互;其三,家庭场景对隐私敏感,不希望录音上传云端。

值得做的原因在于:拼图是几乎每个家庭都有的玩具,复读功能把“动手”与“开口”结合,符合语言敏感期的学习规律;同时硬件成本低、可复制性强,家长能带着孩子一起组装,项目本身也是一次亲子 STEM 体验。

方案设计

感知层:INMP441 数字麦克风通过 I2S 采集孩子跟读的声音,采样率 16 kHz、16 位单声道,够用且省存储。拼图底座在 6 个卡位下各放一个轻触开关,按下即代表该位置有拼图块,通过 GPIO 扩展读取组合状态。麦克风只在按下“录音键”或检测到拼图块放入后 2 秒内开启,减少无效采集。

控制层:ESP32 负责三件事——拼图状态扫描与去抖、录音缓存管理、语音播放调度。录音写入 SD 卡的 WAV 文件,播放时读取并做简单的变速变调(重采样实现“卡通音”)。主循环采用非阻塞状态机,避免录音与播放互相卡死。

执行层:MAX98357A 是 I2S 功放,直接驱动 4 欧 3 瓦小喇叭,无需外部 DAC。拼对时播放预置短句(如“这是小象”),并按需回放孩子刚才的录音,形成“你说—它学”的互动。另加一颗 RGB 灯珠做状态提示:蓝色录音、绿色正确、橙色重试。

日志/联网层:SD 卡记录每次拼图完成的时间、卡位组合与录音文件名,形成简单的学习日志,家长可用读卡器导出。ESP32 的 Wi-Fi 默认关闭,仅在长按按键 5 秒时开启热点,提供网页查看日志,兼顾隐私与可维护性。

物料清单

物料 数量 用途 估算单价(元) 合计(元)
ESP32 开发板(DevKitC) 1 主控 22 22
INMP441 麦克风模块 1 采音 9 9
MAX98357A 功放模块 1 音频输出 12 12
4Ω 3W 喇叭 1 发声 6 6
Micro SD 卡模块 + 8GB 卡 1 语音与日志存储 14 14
轻触开关 6 拼图卡位检测 0.5 3
RGB 灯珠(WS2812) 1 状态提示 2 2
洞洞板、排针、导线 1 批 连接 6 6
外壳(纸盒/3D 打印) 1 结构 5 5
电源(USB 5V 2A) 1 供电 5 5
合计 84

接线与结构

按给定建议接线,I2S 共用一组时钟:BCLK=26、LRC=25。麦克风与功放的数据脚分开,避免半双工冲突:功放 DIN=22,麦克风 SD=32。麦克风的 SCK 与 WS 分别接 26 与 25,形成“同组时钟、双向数据”的接法。麦克风 L/R 脚接地选择左声道。

微调说明:原建议中麦克风写作“32/33/35”,本方案固定 SD=32,把 33、35 留给两颗拼图卡位开关,减少引脚浪费;6 个卡位开关使用 32 以外的 GPIO(如 4、5、13、14、16、17),其余通过二极管矩阵可再压缩,但首版优先可读性。

结构上,拼图底座做成浅槽,每个槽底开孔露出轻触开关的帽子;ESP32 与音频模块装在底座后仓,喇叭朝上,麦克风开小孔朝前。喇叭与麦克风之间加一层泡棉,降低回授啸叫。

核心代码

以下为 Arduino 骨架,基于 ESP32 Arduino Core,可编译。


#include <Arduino.h>
#include <driver/i2s.h>
#include <SPI.h>
#include <SD.h>

#define I2S_BCLK 26
#define I2S_LRC  25
#define I2S_DOUT 22   // MAX98357A DIN
#define I2S_MIC  32   // INMP441 SD

static const int kSlots[6] = {4, 5, 13, 14, 16, 17};
static bool lastState[6] = {false};

void i2sInit() {
  i2s_config_t cfg = {};
  cfg.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX);
  cfg.sample_rate = 16000;
  cfg.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
  cfg.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
  cfg.communication_format = I2S_COMM_FORMAT_STAND_I2S;
  cfg.dma_buf_count = 8;
  cfg.dma_buf_len = 256;
  cfg.use_apll = false;
  i2s_driver_install(I2S_NUM_0, &cfg;, 0, NULL);

  i2s_pin_config_t pin = {};
  pin.mck_io_num = I2S_PIN_NO_CHANGE;
  pin.bck_io_num = I2S_BCLK;
  pin.ws_io_num = I2S_LRC;
  pin.data_out_num = I2S_DOUT;
  pin.data_in_num = I2S_MIC;
  i2s_set_pin(I2S_NUM_0, &pin;);
}

void playWav(const char* path) {
  File f = SD.open(path);
  if (!f) return;
  f.seek(44);  // 跳过 WAV 头
  uint8_t buf[512];
  size_t n;
  while ((n = f.read(buf, sizeof(buf))) > 0) {
    size_t written = 0;
    i2s_write(I2S_NUM_0, buf, n, &written;, portMAX_DELAY);
  }
  f.close();
}

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 6; i++) pinMode(kSlots[i], INPUT_PULLUP);
  i2sInit();
  if (!SD.begin(5)) Serial.println("SD 初始化失败");
}

void loop() {
  for (int i = 0; i < 6; i++) {
    bool now = (digitalRead(kSlots[i]) == LOW);
    if (now && !lastState[i]) {           // 去抖后的“放入”沿
      char path[24];
      snprintf(path, sizeof(path), "/p%d.wav", i);
      playWav(path);
      delay(200);
    }
    lastState[i] = now;
  }
  delay(20);
}

录音路径可用 i2s_read 把 MIC 数据写入 WAV 文件,注意写入前先写 44 字节头并回填长度;播放录音时可对采样做 1.25 倍重采样实现“变声”效果。

调试步骤

  1. 先只接 ESP32 与 MAX98357A,播放 SD 卡中的测试音,确认喇叭有声且无爆音;若无声,检查 SD 模式脚与功放 EN 脚电平。
  2. 接入 INMP441,用 i2s_read 打印峰值,确认说话时数值明显变化;若一直为零,核对 L/R 是否接地、时钟是否与功放共用。
  3. 逐个测试 6 个卡位开关,串口打印状态,确认按下为 LOW,并加入 20 ms 去抖。
  4. 联调“放入即播”:先放预置语音,再测试录音回放,注意录放之间加 100 ms 静默,避免电流冲击。
  5. 整机装壳后测啸叫:把喇叭音量限制在 70%,麦克风与喇叭错位安装,必要时加泡棉隔断。
  6. 连续运行 30 分钟,观察 SD 写入是否掉卡、灯珠颜色是否正确。

设计图

儿童拼图机器人语音复读结构flow
1
感知输入
→
2
控制处理
→
3
执行反馈
→
4
数据上报