Fix INMP441 silent meter: stereo I2S slots and DC removal.
ESP32 left/right naming often mismatches L/R=GND, and DC bias made dB look stuck. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -83,4 +83,5 @@ README.md
|
||||
|
||||
| 日期 | 说明 |
|
||||
|------|------|
|
||||
| 2026-10-27 | 修复无声贝变化:I2S 改立体声读槽(ESP32 L/R 与麦脚常反相)+ 去直流后再算 RMS |
|
||||
| 2026-10-27 | 初版:INMP441 I2S 声贝仪表盘(WS22/SCK27/SD35),LVGL 圆弧 + peak/min/max + 趋势图 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: CYD inmp441test (cyd_28r)
|
||||
git: unknown
|
||||
git: 59b85fb
|
||||
date: 2026-10-27
|
||||
board: ESP32-2432S028R (ILI9341)
|
||||
inmp441: WS=GPIO22 SCK=GPIO27 SD=GPIO35
|
||||
@@ -13,5 +13,5 @@ offsets:
|
||||
sha256:
|
||||
bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8
|
||||
boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0
|
||||
firmware.bin 0CA34A45377F5EDCAB501E510F97B28A9B7FCEB34D6C65F0B71691C784C41999
|
||||
firmware.bin 81B26992192E72F77396E0B71782C145EFE106F996D9E432F1551F5182CC6710
|
||||
partitions.bin 0A8B5720E7B77FF11F1462458C3A509DEE79224E5279898F26D6A2E3AE0517B7
|
||||
|
||||
Binary file not shown.
81
src/main.cpp
81
src/main.cpp
@@ -3,7 +3,8 @@
|
||||
* 2.8 (2432S028R): WS=22 SCK=27 SD=35, TFT_BL=21
|
||||
* 3.5C (3248S035C): WS=22 SCK=21 SD=35, TFT_BL=27 — see ../CYD_PROJECT_GUIDE.md
|
||||
*
|
||||
* L/R -> GND(左声道);VDD -> 3.3V(勿接 5V)
|
||||
* L/R -> GND(推荐);VDD -> 3.3V(勿接 5V)
|
||||
* ESP32 I2S 声道命名常与 INMP441 反相:L/R=GND 时用 RIGHT 槽才有数据。
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
@@ -17,7 +18,7 @@
|
||||
#define I2S_PORT I2S_NUM_0
|
||||
#define SAMPLE_RATE 16000
|
||||
#define SAMPLE_BITS 32
|
||||
#define DMA_BUF_COUNT 4
|
||||
#define DMA_BUF_COUNT 8
|
||||
#define DMA_BUF_LEN 256
|
||||
#define READ_SAMPLES 512
|
||||
#define MIC_READ_MS 80
|
||||
@@ -223,7 +224,9 @@ static bool mic_init(void) {
|
||||
cfg.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX);
|
||||
cfg.sample_rate = SAMPLE_RATE;
|
||||
cfg.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT;
|
||||
cfg.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
|
||||
/* Stereo: ESP32 left/right vs INMP441 L/R pin are often inverted.
|
||||
* L/R=GND usually lands in the RIGHT DMA slot on classic ESP32. */
|
||||
cfg.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
|
||||
cfg.communication_format = I2S_COMM_FORMAT_STAND_I2S;
|
||||
cfg.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1;
|
||||
cfg.dma_buf_count = DMA_BUF_COUNT;
|
||||
@@ -247,31 +250,79 @@ static bool mic_init(void) {
|
||||
return false;
|
||||
}
|
||||
i2s_zero_dma_buffer(I2S_PORT);
|
||||
Serial.printf("I2S stereo RX WS=%d SCK=%d SD=%d\n",
|
||||
I2S_WS_PIN, I2S_SCK_PIN, I2S_SD_PIN);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mic_read_db(float *out_db, float *out_rms) {
|
||||
size_t bytes_read = 0;
|
||||
esp_err_t err = i2s_read(I2S_PORT, (void *)i2s_samples, sizeof(i2s_samples),
|
||||
&bytes_read, pdMS_TO_TICKS(40));
|
||||
&bytes_read, pdMS_TO_TICKS(50));
|
||||
if (err != ESP_OK || bytes_read < sizeof(int32_t) * 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int n = (int)(bytes_read / sizeof(int32_t));
|
||||
double sum_sq = 0.0;
|
||||
int used = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
/* INMP441: 24-bit left-justified in 32-bit word */
|
||||
int32_t s = i2s_samples[i] >> 8;
|
||||
sum_sq += (double)s * (double)s;
|
||||
used++;
|
||||
}
|
||||
if (used < 16) return false;
|
||||
if (n < 32) return false;
|
||||
|
||||
/* Unpack 24-bit left-justified samples; stereo slots alternate. */
|
||||
static int32_t unpacked[READ_SAMPLES];
|
||||
for (int i = 0; i < n; i++) {
|
||||
unpacked[i] = i2s_samples[i] >> 8;
|
||||
}
|
||||
|
||||
/* Measure even/odd slots separately (ESP32 L/R naming vs mic L/R pin). */
|
||||
double mean_even = 0.0, mean_odd = 0.0;
|
||||
int n_even = 0, n_odd = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
if ((i & 1) == 0) {
|
||||
mean_even += unpacked[i];
|
||||
n_even++;
|
||||
} else {
|
||||
mean_odd += unpacked[i];
|
||||
n_odd++;
|
||||
}
|
||||
}
|
||||
if (n_even < 8 || n_odd < 8) return false;
|
||||
mean_even /= (double)n_even;
|
||||
mean_odd /= (double)n_odd;
|
||||
|
||||
double sum_even = 0.0, sum_odd = 0.0;
|
||||
int32_t peak_abs = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
double v;
|
||||
if ((i & 1) == 0) {
|
||||
v = (double)unpacked[i] - mean_even;
|
||||
sum_even += v * v;
|
||||
} else {
|
||||
v = (double)unpacked[i] - mean_odd;
|
||||
sum_odd += v * v;
|
||||
}
|
||||
int32_t a = (int32_t)((v < 0) ? -v : v);
|
||||
if (a > peak_abs) peak_abs = a;
|
||||
}
|
||||
|
||||
double rms_even = sqrt(sum_even / (double)n_even);
|
||||
double rms_odd = sqrt(sum_odd / (double)n_odd);
|
||||
double rms = (rms_even > rms_odd) ? rms_even : rms_odd;
|
||||
const char *slot = (rms_even >= rms_odd) ? "L/even" : "R/odd";
|
||||
|
||||
static uint8_t dbg = 0;
|
||||
if (dbg < 10) {
|
||||
dbg++;
|
||||
Serial.printf(
|
||||
"raw=%08lX/%08lX meanE=%.0f meanO=%.0f rmsE=%.0f rmsO=%.0f peak=%ld %s\n",
|
||||
(unsigned long)(uint32_t)i2s_samples[0],
|
||||
(unsigned long)(uint32_t)i2s_samples[1], mean_even, mean_odd, rms_even,
|
||||
rms_odd, (long)peak_abs, slot);
|
||||
}
|
||||
|
||||
double rms = sqrt(sum_sq / (double)used);
|
||||
*out_rms = (float)rms;
|
||||
if (rms < 1.0) rms = 1.0;
|
||||
if (rms < 1.0) {
|
||||
*out_db = 0.0f;
|
||||
return true;
|
||||
}
|
||||
/* dBFS vs 24-bit full scale, then map to approximate SPL */
|
||||
float dbfs = 20.0f * log10f((float)rms / 8388607.0f);
|
||||
*out_db = dbfs + MIC_DB_OFFSET;
|
||||
|
||||
Reference in New Issue
Block a user