Практического применения этого проекта я не вижу (не мегафон же). Но, для меня это был довольно хороший опыт работы со звуком на 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).
модулем микрофона 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 – стерео. В принципе, преобразование возможно, но я остановился на моно, работает только одна колонка.
Кнопки SD PCM5102A INMP441 ESP32 RST EN BOOT P0 GND GND VCC 5V MISO P19 MOSI P23 SCK P18 CS (SS) P5 VIN 5V GND GND LRCK (LCK) P25 DIN P22 BCK P26 SCK GND WS P14 SCK P32 SD P33 L/R GND VDD 3,3V GND GND
Скетч:
#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 Загрузки)