基于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-S3通过MicroPython读取INMP441麦克风数据并使用MAX98357进行实时音频播放 为了实现这一目标,需要配置I2S接口用于连接INMP441麦克风MAX98357扬声器模块。下面提供了一个具体的代码实例,展示了如何利用MicroPython完成上述任务。 #### 初始化硬件设置 首先定义所需的引脚分配以及初始化I2S对象: ```python from machine import I2S, Pin # 定义I2S总线参数 bclk = Pin(26) # BCLK pin for INMP441 wsi = Pin(25) # WS/IWS pin for INMP441 din = Pin(22) # DIN/SDATA pin from INMP441 to MAX98357A dout = Pin(21) # DOUT pin of INMP441 (not used here) audio_out = I2S( I2S.NUM0, bck=bclk, ws=wsi, sd=din, mode=I2S.TX, bits=16, format=I2S.MONO, rate=16000, ibuf=20000 ) ``` 这段代码设置了I2S通信模式为传输(TX),指定了采样率为16kHz,并创建了大小为20KB的内部缓冲区[^1]。 #### 数据处理与回放逻辑 接下来编写循环结构来持续获取来自INMP441的数据流并通过MAX98357输出声音信号: ```python import time while True: try: buf = bytearray(1024) num_read = audio_out.readinto(buf) if not num_read: continue # 将接收到的数据立即发送出去形成回音效果 audio_out.write(buf[:num_read]) except KeyboardInterrupt: break time.sleep_ms(10) ``` 此部分实现了简单的回声功能,即捕获到的声音会几乎同步地被重播出来。`readinto()`方法用来填充字节数组,而`write()`则负责将这些数据推送到DAC端口以便于发声设备发出声响[^2]。 请注意,在实际应用中可能还需要考虑更多细节,比如噪声抑制、增益调整等高级特性;此外,由于这里采用的是最基础的方式来进行即时录音与播放,因此可能会存在轻微延迟现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

承前智

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

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

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

打赏作者

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

抵扣说明:

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

余额充值