基于Arduino的ESP32-S3+inmp441+max98357(录音机/麦克风喇叭)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本系列将以0基础新手视角,完整演示ESP32+ inmp441+max98357 的全流程及代码实现。建议搭配Arduino IDE 2.0+和ESP32-S3开发板使用。

(二)本文为ESP32-S3连接 inmp441+max98357

一、前期准备

1.1 硬件配置

需准备ESP32-S3开发板 和 inmp441全向麦克风模块 和 max98357

1.2 软件环境配置

安装Arduino IDE 2.0.2
安装 ESP32 库(工具→开发板管理→搜索ESP32→安装)

二、接线

ESP32-S3inmp441
3.3vVDD
GNDGND
6WS
4SD
7SCK
ESP32-S3max98357
3.3vVDD
GNDGND
16MAX98357_LRC
17MAX98357_BCLK
18MAX98357_DIN
喇叭max98357
++

三、核心代码

3.1 (录音机)代码

注意

11号引脚置底,开始录音(录音时间要低于5s,不然超出内存),置高则停止录音
10号引脚置底,开始播放录音,置底则停止播放
若是播放无声音,说明录音过长,需要重新录音
9号引脚,接LED灯显示用,可不接

调节音量,修改代码中的 5 倍数太高,声音会是失真+for (int i = 0; i < count; i++) {
    int32_t amplified = sample[i] * 5; // 乘以3倍音量
    if (amplified > 32767) amplified = 32767;
    if (amplified < -32768) amplified = -32768;
    tempBuffer[i] = (int16_t)amplified;
  }

代码(录音机):

#include <Arduino.h>
#include <driver/i2s.h>
#include <hal/i2s_types.h>

#define INMP441_WS 6
#define INMP441_SCK 7
#define INMP441_SD 4

#define MAX98357_LRC 16
#define MAX98357_BCLK 17
#define MAX98357_DIN 18

#define SAMPLE_RATE 16000
#define SAMPLE_SECONDS 5  // 最多录音秒数(内存限制)
#define BUFFER_SIZE (SAMPLE_RATE * SAMPLE_SECONDS)

const int recordPin = 11;
const int playPin = 10;
const int LEDPin = 9;


i2s_config_t inmp441_i2s_config = {
  .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
  .sample_rate = SAMPLE_RATE,
  .bits_per_sample = i2s_bits_per_sample_t(16),
  .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  .dma_buf_count = 8,
  .dma_buf_len = 128
};

const i2s_pin_config_t inmp441_gpio_config = {
  .bck_io_num = INMP441_SCK,
  .ws_io_num = INMP441_WS,
  .data_out_num = -1,
  .data_in_num = INMP441_SD
};

i2s_config_t max98357_i2s_config = {
  .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
  .sample_rate = SAMPLE_RATE,
  .bits_per_sample = i2s_bits_per_sample_t(16),
  .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  .dma_buf_count = 8,
  .dma_buf_len = 128
};

const i2s_pin_config_t max98357_gpio_config = {
  .bck_io_num = MAX98357_BCLK,
  .ws_io_num = MAX98357_LRC,
  .data_out_num = MAX98357_DIN,
  .data_in_num = -1
};

uint8_t *recordBuffer = nullptr;
size_t recordedBytes = 0;

void setup() {
  Serial.begin(115200);
  pinMode(recordPin, INPUT_PULLUP); // D11
  pinMode(playPin, INPUT);          // D10
 pinMode(LEDPin, OUTPUT);          // D9
  // 初始化麦克风 I2S
  i2s_driver_install(I2S_NUM_0, &inmp441_i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &inmp441_gpio_config);

  // 初始化扬声器 I2S
  i2s_driver_install(I2S_NUM_1, &max98357_i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_1, &max98357_gpio_config);

  // 分配录音缓冲区
  recordBuffer = (uint8_t *)malloc(BUFFER_SIZE * sizeof(uint16_t));
  if (!recordBuffer) {
    Serial.println("Failed to allocate memory!");
    while (1);
  }
}

void loop() {
  // 录音逻辑
  if (digitalRead(recordPin) == LOW) {
    digitalWrite(LEDPin,HIGH);
    Serial.println("开始录音...");

    // 清空缓冲区,防止旧数据残留
    memset(recordBuffer, 0, BUFFER_SIZE * sizeof(uint16_t));
    recordedBytes = 0;

    size_t bytesRead;
    while (digitalRead(recordPin) == LOW && recordedBytes < BUFFER_SIZE * sizeof(uint16_t)) {
      i2s_read(I2S_NUM_0, recordBuffer + recordedBytes, 512, &bytesRead, portMAX_DELAY);
      recordedBytes += bytesRead;
    }

    Serial.println("录音结束");
  }
   digitalWrite(LEDPin,LOW);
  // 播放逻辑
  if (digitalRead(playPin) == LOW && recordedBytes > 0) {
    Serial.println("开始播放...");
    size_t bytesWritten = 0;
while (bytesWritten < recordedBytes) {
  size_t writeSize;
  size_t chunkSize = 512;
  if (recordedBytes - bytesWritten < chunkSize) {
    chunkSize = recordedBytes - bytesWritten;
  }

  // 放大音量:把采样数据乘上一个倍数
  int16_t* sample = (int16_t*)(recordBuffer + bytesWritten);
  int16_t tempBuffer[256]; // 临时缓冲区,用来保存放大后的数据
  int count = chunkSize / 2;

  for (int i = 0; i < count; i++) {
    int32_t amplified = sample[i] * 5; // 乘以3倍音量
    if (amplified > 32767) amplified = 32767;
    if (amplified < -32768) amplified = -32768;
    tempBuffer[i] = (int16_t)amplified;
  }

  i2s_write(I2S_NUM_1, tempBuffer, chunkSize, &writeSize, portMAX_DELAY);
  bytesWritten += writeSize;
}

    Serial.println("播放完成");
    delay(1000); // 防止重复触发
  }
}


3.2 (麦克风喇叭)代码

注意

调节音量,修改代码中的 5 倍数太高,声音会是失真+for (int i = 0; i < count; i++) {
    int32_t amplified = sample[i] * 5; // 乘以3倍音量
    if (amplified > 32767) amplified = 32767;
    if (amplified < -32768) amplified = -32768;
    tempBuffer[i] = (int16_t)amplified;
  }
#include <Arduino.h>
#include <driver/i2s.h>
#include <hal/i2s_types.h>

#define INMP441_WS 6
#define INMP441_SCK 7
#define INMP441_SD 4



#define MAX98357_LRC 16
#define MAX98357_BCLK 17
#define MAX98357_DIN 18

// #define SAMPLE_RATE 44100
#define SAMPLE_RATE 16000

const int inputPin = 5;

i2s_config_t inmp441_i2s_config = {
  .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
  .sample_rate = SAMPLE_RATE,
  .bits_per_sample = i2s_bits_per_sample_t(16),
  .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  .dma_buf_count = 8,   // buffer 的数量
  .dma_buf_len = 128    // buffer的大小,单位是i2s_bits_per_sample_t 采样位数,越小播放需要越及时时延越小,否则相反
};


const i2s_pin_config_t inmp441_gpio_config = {
  .bck_io_num = INMP441_SCK,
  .ws_io_num = INMP441_WS,
  .data_out_num = -1,
  .data_in_num = INMP441_SD
};

i2s_config_t max98357_i2s_config = {
  .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
  .sample_rate = SAMPLE_RATE,
  .bits_per_sample = i2s_bits_per_sample_t(16),
  .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_MSB),
  .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
  .dma_buf_count = 8,
  .dma_buf_len = 128
};


const i2s_pin_config_t max98357_gpio_config = {
  .bck_io_num = MAX98357_BCLK,
  .ws_io_num = MAX98357_LRC,
  .data_out_num = MAX98357_DIN,
  .data_in_num = -1
};

void setup()
{
  pinMode(inputPin, INPUT);
  i2s_driver_install(I2S_NUM_0, &inmp441_i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &inmp441_gpio_config);

  i2s_driver_install(I2S_NUM_1, &max98357_i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_1, &max98357_gpio_config);

}

void loop()
{

  size_t bytes_read;

  uint16_t data[256];

  esp_err_t result = i2s_read(I2S_NUM_0, &data, sizeof(data), &bytes_read, portMAX_DELAY);
  size_t bytes_write;

  int val = digitalRead(inputPin); 
if (val == HIGH)
  {
  result = i2s_write(I2S_NUM_1, &data, sizeof(data), &bytes_write, portMAX_DELAY);
  }
}

四、(录音机)最终效果

11号引脚置底,开始录音(录音时间要低于5s,不然超出内存),置高则停止录音

10号引脚置底,开始播放录音,置底则停止播放

若是播放无声音,说明录音过长,需要重新录音

9号引脚,接LED灯显示用,可不接
在这里插入图片描述

五、(麦克风喇叭)最终效果

对着麦克风,讲话。
喇叭会对应出声。
在这里插入图片描述

总结

本文是为验证《基于Arduino的ESP32-S3+inmp441+max98357(录音机/麦克风喇叭)的驱动》

### 使用 ESP32-S3INMP441 录制音频并传输至电脑 为了实现使用 ESP32-S3INMP441 麦克风录制音频并通过串口/USB 将声音文件传输至电脑的功能,可以按照以下方法操作: #### 1. **硬件连接** ESP32-S3 提供了 I2S 接口用于与数字麦克风通信。INMP441 是一款支持 I2S 输出的 MEMS 麦克风,可以直接与 ESP32-S3 进行对接[^1]。 - **I2S 引脚配置** 根据官方文档说明,需将 INMP441 的 I2S 数据线 (SDOUT)、时钟线 (BCLK) 和帧同步线 (WS/LRCK) 对应连接到 ESP32-S3 上的相关 GPIO 引脚[^2]。 - **电源管理** 确保为 INMP441 提供电源电压稳定(通常为 1.8V 或 3.3V),并与 ESP32-S3 的逻辑电平匹配。 #### 2. **软件设置** 以下是基于 Arduino 平台的一个简单示例程序,展示如何初始化 I2S 设备来捕获音频数据,并将其通过 USB 发送至上位机。 ```cpp #include <driver/i2s.h> #define SAMPLE_RATE (16000) // 设置采样率为 16kHz #define BITS_PER_SAMPLE (16) // 每样本 16bit #define BUFFER_SIZE (1024) void setup() { Serial.begin(115200); // 初始化串口波特率 i2s_config_t i2s_config = { // 定义 I2S 参数结构体 .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = SAMPLE_RATE, .bits_per_sample = BITS_PER_SAMPLE, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = 0, .dma_buf_count = 8, .dma_buf_len = 64, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = 0 }; i2s_pin_config_t pin_config = { // 定义 I2S 引脚映射 .bck_io_num = 27, // BCLK -> GPIO27 .ws_io_num = 26, // LRCK -> GPIO26 .data_out_num = I2S_PIN_NO_CHANGE, .data_in_num = 35 // SDATA_IN -> GPIO35 }; i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config); } uint8_t buffer[BUFFER_SIZE]; int count = 0; void loop() { size_t bytes_read; i2s_read(I2S_NUM_0, buffer, sizeof(buffer), &bytes_read, portMAX_DELAY); if(bytes_read > 0){ Serial.write((char*)buffer, bytes_read); // 将音频数据发送给上位机 delay(10); } } ``` 此代码实现了从 INMP441 获取原始 PCM 数据流,并通过 `Serial` 接口实时上传到 PC。 #### 3. **PC端接收与存储** 在计算机一侧可以通过 Python 编写简单的脚本监听 COM 口上的数据包,并保存成 WAV 文件格式以便后续播放或分析。 ```python import serial from scipy.io.wavfile import write as wav_write ser = serial.Serial(&#39;COMX&#39;, 115200) # 替换 &#39;COMX&#39; 为你实际使用的串口号 audio_data = [] try: while True: data_chunk = ser.read(1024) # 假设每次读取固定大小的数据块 audio_data.extend(data_chunk) except KeyboardInterrupt: pass # 转换成 numpy 数组形式方便处理 wav_audio = bytearray(audio_data).decode() rate = 16000 # 同步于 MCU 中定义好的采样频率 wav_write("output.wav", rate, wav_audio) print("Audio saved successfully.") ``` 以上脚本会持续记录来自设备的所有传入字节直到手动中断为止,最后导出名为 `"output.wav"` 的波形文件。 #### 注意事项 当仅有一只 INMP441 微型电话筒可用时,则无法完成真正的双通道立体声录音任务;若追求高质量音效体验则建议配备两只独立工作的单元分别负责左右耳位置拾音工作[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈乾智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值