Передача звука с INMP441 на декодер PCM5102A с помощью ESP32

     Практического применения этого проекта я не вижу (не мегафон же). Но, для меня это был довольно хороший опыт работы со звуком на ESP32-WROOM. Скетч разрабатывался в среде Arduino IDE 2.3.5. Заменил на Arduino IDE 2.3.6, скетч компилируется, загружается и работает.

Скачать Arduino IDE 2.3.6

arduino-ide_2.3.6_Windows_64bit.exe (35 Загрузок)

     Насчет железа. Дополнил предыдущий проект “ESP32 — проигрывание mp3 файлов с SD через декодер PCM5102A” (там и о распайке перемычек на PCM5102A).

https://conntest.ru/program/esp32-proigryvanie-mp3-fajlov-s-sd-cherez-dekoder-pcm5102a

модулем микрофона INMP441 и еще одной кнопкой, которая управляет изменением коэффициента усиления выходного сигнала от 0.5 до 3.0 через 0.5, по кругу. Еще добавил светодиод, который степенью яркости отражает величину этого коэффициента. Показания также выводятся в Serial Port после изменения (нажатия кнопки). Звук довольно чистый.

     Подключение кнопки управления коэффициентом усиления: один контакт на GND, другой на P4. Светодиод индикации коэффициента подключен плюсом к 3,3 V через резистор 180 Ом, минусом к P2.

     Таблица подключения модулей к ESP32-WROOM (обозначения контактов ESP32 относятся к переходной плате).

     Микрофон INMP441 с интерфейсом I2S – моно (контакт L/R подключен к GND, наверное, можно подключить этот контакт к ESP32 и обрабатывать стерео), а декодер интерфейса I2S PCM5102A – стерео. В принципе, преобразование возможно, но я остановился на моно, работает только одна колонка.

КнопкиSDPCM5102AINMP441ESP32
RSTEN
BOOTP0
GNDGND
VCC5V
MISOP19
MOSIP23
SCKP18
CS (SS)P5
VIN5V
GNDGND
LRCK (LCK)P25
DINP22
BCKP26
SCKGND
WSP14
SCKP32
SDP33
L/RGND
VDD3,3V
GNDGND

Скетч:

 


#include <Arduino.h>
#include <driver/i2s.h>
#include <driver/ledc.h>

// === Пины подключения INMP441 ===
#define I2S_WS 14
#define I2S_SD 33
#define I2S_SCK 32

// === Пины подключения PCM5102A ===
#define I2S_LRCK 25
#define I2S_DIN 22
#define I2S_BCK 26

#define I2S_MIC_PORT (I2S_NUM_0)
#define I2S_DAC_PORT (I2S_NUM_1)

#define bufferLen 128
int32_t sBuffer[bufferLen];

// === Кнопка ===
#define BUTTON_PIN 4
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50;
bool lastButtonState = HIGH;
bool buttonPressed = false;

// === Усиление ===
float gainLevels[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0};
int gainIndex = 0;

// === Светодиод (PWM) ===
#define LED_PIN 2
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_TIMER LEDC_TIMER_0

void setup_pwm() {
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_8_BIT,
.timer_num = LEDC_TIMER,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);

ledc_channel_config_t ledc_channel = {
.gpio_num = LED_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LEDC_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&ledc_channel);
}

void set_pwm_brightness(int brightness) {
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL, brightness);
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL);
}

// === Усиление сигнала ===
void applyGain(int32_t* buffer, int samples, float gain) {
for (int i = 0; i < samples; ++i) {
float amplified = buffer[i] * gain;
if (amplified > INT32_MAX) amplified = INT32_MAX;
if (amplified < INT32_MIN) amplified = INT32_MIN;
buffer[i] = (int32_t)amplified;
}
}

// === I2S: вход ===
void i2s_install_in() {
const i2s_config_t i2s_config_in = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 48000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = 0,
.dma_buf_count = 16,
.dma_buf_len = bufferLen,
.use_apll = false
};
i2s_driver_install(I2S_MIC_PORT, &i2s_config_in, 0, NULL);
}

void i2s_setpin_in() {
const i2s_pin_config_t pin_config_in = {
.mck_io_num = -1,
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD,
};
i2s_set_pin(I2S_MIC_PORT, &pin_config_in);
}

// === I2S: выход ===
void i2s_install_out() {
const i2s_config_t i2s_config_out = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 48000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = 0,
.dma_buf_count = 16,
.dma_buf_len = bufferLen,
.use_apll = false
};
i2s_driver_install(I2S_DAC_PORT, &i2s_config_out, 0, NULL);
}

void i2s_setpin_out() {
const i2s_pin_config_t pin_config_out = {
.mck_io_num = -1,
.bck_io_num = I2S_BCK,
.ws_io_num = I2S_LRCK,
.data_out_num = I2S_DIN,
.data_in_num = -1,
};
i2s_set_pin(I2S_DAC_PORT, &pin_config_out);
}

// === Проверка кнопки ===
void checkButton() {
static bool lastStableState = HIGH;
static bool lastReadState = HIGH;
static unsigned long lastChangeTime = 0;

bool currentRead = digitalRead(BUTTON_PIN);

if (currentRead != lastReadState) {
lastChangeTime = millis();
}

if ((millis() - lastChangeTime) > debounceDelay) {
if (currentRead != lastStableState) {
lastStableState = currentRead;
if (lastStableState == LOW) {
buttonPressed = true;
}
}
}

lastReadState = currentRead;
}

void setup() {
Serial.begin(115200);
Serial.println("Старт...");

pinMode(BUTTON_PIN, INPUT_PULLUP);

i2s_install_in();
i2s_setpin_in();
i2s_start(I2S_MIC_PORT);

i2s_install_out();
i2s_setpin_out();
i2s_start(I2S_DAC_PORT);

setup_pwm();
set_pwm_brightness(map(gainIndex, 0, 5, 255, 0));

delay(500);
}

void loop() {
checkButton();

if (buttonPressed) {
gainIndex = (gainIndex + 1) % (sizeof(gainLevels) / sizeof(gainLevels[0]));
int brightness = map(gainIndex, 0, 5, 255, 0);
set_pwm_brightness(brightness);

Serial.print("Нажата кнопка! Новое усиление: ");
Serial.println(gainLevels[gainIndex]);
buttonPressed = false;
}

size_t bytesIn;
esp_err_t result = i2s_read(I2S_MIC_PORT, &sBuffer, sizeof(sBuffer), &bytesIn, portMAX_DELAY);

if (result == ESP_OK && bytesIn > 0) {
int samples = bytesIn / sizeof(int32_t);
float gain = gainLevels[gainIndex];

applyGain(sBuffer, samples, gain);

size_t bytesOut;
esp_err_t res = i2s_write(I2S_DAC_PORT, sBuffer, bytesIn, &bytesOut, portMAX_DELAY);

if (res != ESP_OK || bytesOut != bytesIn) {
Serial.println("Ошибка записи в I2S DAC");
}
} else {
Serial.println("Ошибка чтения из I2S микрофона");
}
}

Скачать INMP441_ESP32_ PCM5202A_32bit_MONO.INO

INMP441_ESP32__PCM5202A_32bit_MONO.ino (22 Загрузки)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *