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

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

文章目录

  • 前言
  • 一、前期准备
    • 1.1 硬件配置
    • 1.2 软件环境配置
  • 二、接线
  • 三、核心代码
    • 3.1 (录音机)代码
    • 3.2 (麦克风喇叭)代码
  • 四、(录音机)最终效果
  • 五、(麦克风喇叭)最终效果
  • 总结


前言

本系列将以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-S3 inmp441
3.3v VDD
GND GND
6 WS
4 SD
7 SCK
ESP32-S3 max98357
3.3v VDD
GND GND
16 MAX98357_LRC
17 MAX98357_BCLK
18 MAX98357_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 
#include 
#include 

#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 
#include 
#include 

#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(录音机/麦克风喇叭)_第1张图片

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

对着麦克风,讲话。
喇叭会对应出声。
基于Arduino的ESP32-S3+inmp441+max98357(录音机/麦克风喇叭)_第2张图片

总结

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

你可能感兴趣的:(嵌入式硬件,单片机,嵌入式)