LedB: el nivel de sonido a la vista de todos
Un indicador luminoso que mide la intensidad sonora en dB(A) y la muestra en una tira de LED: verde, ámbar, rojo. Pensado para aulas y comedores escolares acústicamente mejorados, con micrófono digital MEMS, ESP32 y código abierto.
Mejorar la acústica de una sala no cambia por sí solo cómo se habla dentro de ella. Hace falta que quien habla tome conciencia de su propio nivel sonoro, y para eso necesita verlo. LedB convierte los decibelios en una señal luminosa que está ahí para todo el grupo, no en un juicio del adulto que lo dirige.
LedB en funcionamiento: cada LED encendido equivale a un escalón de nivel sonoro medido en dB(A).
Por qué un indicador visual
La taxonomía de objetivos de aprendizaje de Marzano y Kendall (2007) incorpora, en el máximo nivel, el Sistema de Conciencia del Ser: la autorregulación.1 Modificar los hábitos de habla en un espacio mejorado acústicamente no es automático: requiere facilitar esa autorregulación evaluando la importancia, la eficacia, las emociones y la motivación.
El objetivo, entonces, es que los hablantes se autorregulen tomando conciencia del nivel de logro en la mejora. Para eso hemos creado un dispositivo colectivo que mide y muestra visualmente el nivel de intensidad sonora.
Más allá de una herramienta de aprendizaje STEM, este sonómetro visual es un agente de cambio conductual: devuelve el dato en el mismo momento en que se produce y lo hace visible para todo el grupo a la vez.
Qué muestra en el aula
- Lectura individual fluida
- Trabajo en grupos pequeños
- Explicaciones del profesorado claras
- Ruido excesivo que interfiere
- Pérdida de concentración
- Necesidad de intervención inmediata
Lo que hemos observado
- Autorregulación inmediata: el alumnado ajusta su volumen al ver los LED.
- Menos desgaste docente: menos necesidad de intervenciones verbales.
- Mejor ambiente de trabajo: un entorno más propicio para el aprendizaje.
- Conciencia social: respeto por el espacio compartido.
En el comedor escolar
El comedor es el otro espacio donde el indicador rinde de inmediato, porque ahí el ruido no solo dificulta la conversación: también cambia cómo se come. Los tramos de referencia son distintos a los del aula.
- Digestión óptima y conversación relajada
- Socialización saludable
- Experiencia gastronómica positiva
- Estrés alimentario
- Comunicación dificultada
- Ambiente poco saludable
Cómo se usa bien
El color no es un premio ni un castigo: es información. Cada tramo tiene una función pedagógica distinta, y conviene explicarla al grupo antes de encender el aparato por primera vez.
- Satisfacción inmediata al mantenerlo
- «Mantener el verde» funciona como juego natural
- El grupo se autorregula colectivamente
- Alerta temprana, sin consecuencias negativas
- Tiempo para autoajustarse antes del problema
- Desarrollo gradual de la conciencia acústica
- Señal clara, pero no punitiva
- Responsabilidad compartida por todo el grupo
- Conexión visible entre ruido y bienestar
Retroalimentación inmediata frente a intervención tardía
Reactivo: genera conflicto.
Proactivo: genera conciencia.
Competencias que se trabajan
| Competencia | Desarrollo | Evidencia observable |
|---|---|---|
| Empatía acústica | Consideración hacia otros | Reducción voluntaria del volumen |
| Autorregulación | Control interno del comportamiento | Ajuste proactivo sin supervisión |
| Responsabilidad colectiva | Cuidado del ambiente común | Intervención positiva entre iguales |
| Conciencia ambiental | Comprensión de causa y efecto | Correlación entre ruido y bienestar |
Y un proyecto STEM completo
| Ámbito | Componente | Aplicación |
|---|---|---|
| Ciencia | Análisis FFT y ponderación A | Física del sonido y psicoacústica |
| Tecnología | Micrófono I2S y ESP32 | Procesamiento digital de señales |
| Ingeniería | Diseño de circuitos y LED | Sistemas embebidos y visualización |
| Matemáticas | Algoritmos DSP y estadística | Transformadas, promedios y mapeo |
Medir el sonido no es sencillo
Medir bien la intensidad sonora tiene más dificultades de las que parece, y merece la pena conocerlas antes de elegir componentes: hay un buen repaso en este enlace.2
Queremos una sensibilidad y una banda de frecuencia suficientes para medir desde 40 dB hasta 90 dB con ponderación dB(A), que es la que se corresponde con la percepción de nuestro oído. Nuestra elección, por relación coste-rendimiento, ha sido el micrófono digital MEMS INMP441. Como segunda opción, el MEMS ICS-43434. Ambos trabajan con el interfaz I2S que encontramos en el ESP32.
Algunos prototipos habituales de semáforos de ruido utilizan micrófonos analógicos electret. Por lo general el resultado está más cerca de unas luces de fiesta que de un auténtico medidor de intensidad del sonido.
Placa controladora
Si necesitamos disponer de interfaz I2S, hay que verificar que esté disponible en nuestra controladora. Nuestro prototipo utiliza una ESP32-S3 Supermini. También ha funcionado con la AZ-Delivery Lolin32 y con la ESP32 D1 R32.
Visualización
Para visualizar los dB medidos utilizamos una tira Neopixel. El número de LED iluminados corresponde al nivel de dB(A) medido, y el color va variando: los primeros LED en verde, después ámbar y los niveles máximos en rojo. Es un híbrido de semáforo y vúmetro: un vúmetro semafórico.
El prototipo
Plano general y detalle del montaje: ESP32-S3 Supermini, micrófono MEMS I2S y tira WS2812B.
1. Micrófono I2S al ESP32
| Micrófono I2S | ESP32 |
|---|---|
| VDD (3.3 V) | 3.3V |
| GND | GND |
| SD (DATA) | GPIO 1 |
| SCK (BCLK) | GPIO 2 |
| WS (LRCLK) | GPIO 7 |
| L/R | GND (para canal izquierdo) |
2. Tira LED WS2812B al ESP32
| WS2812B | ESP32 | Fuente externa |
|---|---|---|
| DIN (Data) | GPIO 8 | — |
| 5V | — | 5V |
| GND | GND | GND |
- Con pocos LED, como en este caso, puede usarse la salida de 5 V del propio ESP32.
- A partir de 8-10 LED, usar una fuente externa de 5 V y conectar la masa (GND) común.
- Condensador de filtrado de 1000 μF entre 5 V y GND, cerca de la tira: estabiliza la alimentación y previene picos de corriente.
- Resistencia de 330-470 Ω entre el GPIO 8 y la entrada de datos de la tira: protege el primer LED y el GPIO del microcontrolador.
Test de medición
Para la prueba hemos añadido una pantalla OLED que muestra los dB medidos, y así poder comparar con la lectura de un sonómetro comercial. Nuestro visualizador mide entre 40 y 90 dB.
Comparación en directo entre la lectura de LedB y la de un sonómetro comercial.
Los micrófonos MEMS tienen una limitación: no miden por debajo de 30 dB. En nuestro caso es irrelevante, porque en un contexto de actividad escolar casi siempre se dan lecturas por encima de 50 dB.
Comprobación de precisión a 60, 70 y 80 dB. A la derecha, la versión funcional de mayor tamaño (40 × 10 cm), con cuatro tiras LED para asegurar la visualización con luz de día y a distancia.
En el prototipo trabajamos con una tira de 11 LED Neopixel, lo que equivale a 5 dB por LED. Vista la precisión, podemos incrementar el número de LED por tira hasta 25: equivaldría a 2 dB por LED.
Listo para trabajar la autorregulación de los hablantes en nuevos espacios de aprendizaje. También en comedores escolares acústicamente mejorados.
LedB mide lo que genera el grupo, no lo que devuelve la sala. No mide el tiempo de reverberación ni el ruido de las instalaciones, y no sustituye a una medición acústica del espacio: para eso está el protocolo de medición del blog.
Código Arduino
Estructura y componentes principales
Hardware utilizado: microcontrolador ESP32, micrófono digital I2S INMP441 y tira de LED WS2812B (11 LED configurados).
| Biblioteca | Función |
|---|---|
| Arduino.h | Framework base |
| driver/i2s.h | Interfaz de audio digital |
| FastLED.h | Control de LED |
| CircularBuffer.hpp | Gestión de buffer circular para datos |
| arduinoFFT.h | Análisis de frecuencias |
Flujo de funcionamiento
El sistema opera en un ciclo continuo con cuatro etapas.
- Inicialización de los LED, apagados
- Configuración del bus I2S para el micrófono
- Preparación de las estructuras de datos para la FFT
- Captura constante de audio a través de I2S
- Actualización de la visualización cada 50 ms, configurable
- Cálculo del RMS de la señal
- FFT para el análisis espectral
- División del espectro en 12 bandas de frecuencia
- Ponderación A, que simula la respuesta del oído humano
- Conversión a decibelios y almacenamiento en buffer circular
- Mapeo del nivel sonoro al número de LED activos
- Verde en niveles bajos, ámbar en medios, rojo en altos
Características técnicas
| Bloque | Parámetros |
|---|---|
| Muestreo de audio | 44,1 kHz (calidad CD) · resolución de 32 bits · buffer DMA de 8 buffers de 1024 muestras |
| Análisis espectral | FFT de 1024 puntos · ventana Hanning/Hamming · 12 bandas de frecuencia en escala logarítmica |
| Procesamiento acústico | RMS verdadero · ponderación A (dBA) · rango configurable de 40 a 90 dB |
Flujo de datos
→ análisis por bandas → ponderación A → conversión a dB
→ buffer circular → promediado → mapeo a LED → visualización
Optimizaciones implementadas
- DMA para captura de audio sin bloqueo
- Ventana FFT para reducir efectos de borde
- Buffer circular para estabilizar las lecturas
- Ponderación A para representar mejor la percepción humana
- Escala logarítmica para las bandas de frecuencia
- Promediado temporal para reducir fluctuaciones
/**
* ESP32 Sound Level Meter with LED Display
*
* Este sistema captura audio mediante un micrófono I2S digital,
* procesa la señal para calcular niveles de sonido en dB(A),
* y visualiza los resultados en una tira de LEDs WS2812B.
*
* Características:
* - Captura de audio digital mediante interfaz I2S
* - Análisis FFT para procesamiento en dominio de frecuencia
* - Ponderación A para simular la respuesta del oído humano
* - Visualización mediante LEDs con escala de colores según intensidad
*
* Hardware recomendado:
* - ESP32 (cualquier variante)
* - Micrófono digital I2S (INMP441, SPH0645, etc.)
* - Tira de LEDs WS2812B
*
* Conexiones:
* - I2S WS (Word Select/LRCLK): GPIO 7
* - I2S SD (Serial Data): GPIO 1
* - I2S SCK (Serial Clock/BCLK): GPIO 2
* - LED Data: GPIO 8
*
* Autor: Vicent Villena Serrano
* Herramienta de refinamiento: Claude AI
* Fecha: Mayo 2025
*/
#include <Arduino.h>
#include <driver/i2s.h>
#include <FastLED.h>
#include <CircularBuffer.hpp>
#include <arduinoFFT.h>
// ==================== CONFIGURACIÓN DE CONSTANTES ====================
// Configuración de LED
#define LED_PIN 8 // El pin GPIO conectado a la entrada de datos de la tira WS2812
#define NUM_LEDS 11 // Número de LEDs en la tira (ajustable según configuración)
#define LED_TYPE WS2812B // Tipo de LED (WS2812, WS2812B, WS2811, etc.)
#define COLOR_ORDER GRB // Orden de color (GRB para WS2812, puede variar según modelo)
#define BRIGHTNESS 150 // Brillo global (0-255)
#define STRIPS 1 // Número de tiras LED conectadas en zigzag (para configuraciones avanzadas)
#define STEP (254/NUM_LEDS/STRIPS) // Incremento de color entre LEDs sucesivos
// Configuración de I2S (protocolo de audio digital)
#define I2S_WS 7 // Word Select (LRCLK) - Selecciona canal I/D
#define I2S_SD 1 // Serial Data - Datos del micrófono
#define I2S_SCK 2 // Serial Clock (BCLK) - Reloj de bits
#define I2S_PORT I2S_NUM_0 // Puerto I2S del ESP32 (0 o 1)
// Parámetros de audio mejorados
#define SAMPLE_RATE 44100 // Frecuencia de muestreo en Hz (calidad CD)
#define SAMPLE_BITS 32 // Bits por muestra
#define DMA_BUFFER_COUNT 8 // Número de buffers DMA para I2S
#define DMA_BUFFER_LENGTH 1024 // Tamaño de cada buffer DMA en samples
#define UPDATE_INTERVAL 50 // Intervalo de actualización visual en ms
#define BUFFER_SIZE 50 // Tamaño del buffer circular para promediar lecturas
#define DB_MIN 40 // Nivel mínimo de dB para mapeo a LEDs
#define DB_MAX 90 // Nivel máximo de dB para mapeo a LEDs
// Configuración de FFT (Transformada Rápida de Fourier)
#define FFT_SAMPLES 1024 // Número de muestras para FFT (potencia de 2)
#define NUM_BANDS 12 // Número de bandas de frecuencia para el análisis espectral
// ==================== VARIABLES GLOBALES ====================
// Buffer circular para almacenar niveles de sonido y reducir fluctuaciones
CircularBuffer<float, BUFFER_SIZE> buffer;
unsigned long lastUpdateTime = 0; // Timestamp de la última actualización de LEDs
// Array de LEDs para control mediante FastLED
CRGB leds[NUM_LEDS];
// Variables para cálculo de FFT
ArduinoFFT<double> FFT; // Objeto FFT
double vReal[FFT_SAMPLES]; // Parte real de los datos FFT
double vImag[FFT_SAMPLES]; // Parte imaginaria de los datos FFT
float bandValues[NUM_BANDS]; // Valores de energía para cada banda de frecuencia
float aWeightedSum = 0; // Suma ponderada de energía (curva A)
// Task handle para procesamiento en segundo plano (no utilizado en esta versión)
TaskHandle_t audioProcessingTask;
// ==================== DECLARACIONES DE FUNCIONES ====================
void setupLEDs(); // Inicializa la tira de LEDs
void setupI2S(); // Configura el periférico I2S para captura de audio
void captureAudio(); // Captura muestras de audio desde el micrófono
void processAudio(int32_t* samples, int samplesRead); // Procesa muestras de audio capturadas
void updateLEDDisplay(float averageDB); // Actualiza visualización LED según nivel
float calculateAverageFromBuffer(); // Calcula promedio desde buffer circular
void performFFT(double *vReal, double *vImag, int samples); // Realiza análisis FFT
float applyAWeighting(float* bandValues, int numBands); // Aplica ponderación A
float calculateRMS(int32_t* samples, int samplesRead); // Calcula valor RMS
float freqToAWeight(float freq); // Calcula factor de ponderación A para frecuencia
// ==================== FUNCIONES PRINCIPALES ====================
/**
* Configuración inicial del sistema
*/
void setup() {
Serial.begin(115200);
Serial.println("Inicializando sonómetro ESP32...");
setupLEDs();
setupI2S();
lastUpdateTime = millis();
// Inicializa el array de imaginarios para la FFT
for (int i = 0; i < FFT_SAMPLES; i++) {
vImag[i] = 0;
}
Serial.println("Sistema inicializado correctamente");
}
/**
* Bucle principal del programa
*/
void loop() {
// Captura continua de audio
captureAudio();
// Actualiza la visualización LED cada UPDATE_INTERVAL ms
if (millis() - lastUpdateTime >= UPDATE_INTERVAL) {
lastUpdateTime = millis();
// Obtiene el promedio de nivel sonoro desde el buffer circular
float avgDB = calculateAverageFromBuffer();
// Actualiza visualización de LEDs con el valor promediado
updateLEDDisplay(avgDB);
}
}
// ==================== IMPLEMENTACIÓN DE FUNCIONES ====================
/**
* Configura la tira de LEDs con los parámetros definidos
*/
void setupLEDs() {
Serial.println("Configurando LEDs...");
// Inicializar la tira de LEDs con corrección de color típica
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
// Apagar todos los LEDs al inicio
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
Serial.printf("LEDs configurados: %d LEDs en pin %d\n", NUM_LEDS, LED_PIN);
}
/**
* Configura el periférico I2S para la adquisición de audio digital
*/
void setupI2S() {
Serial.println("Configurando interfaz I2S...");
// Estructura de configuración I2S
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), // Modo maestro, solo recepción
.sample_rate = SAMPLE_RATE, // Frecuencia de muestreo (44.1 kHz)
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // Resolución de 32 bits
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // Solo canal izquierdo
.communication_format = I2S_COMM_FORMAT_I2S, // Formato estándar I2S
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // Prioridad de interrupción
.dma_buf_count = DMA_BUFFER_COUNT, // Número de buffers DMA
.dma_buf_len = DMA_BUFFER_LENGTH, // Longitud de cada buffer
.use_apll = true, // Usar APLL para mayor precisión
.tx_desc_auto_clear = false, // No auto-limpiar descriptores TX
.fixed_mclk = 0 // No usar MCLK fijo
};
// Configuración de pines I2S
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK, // Bit clock
.ws_io_num = I2S_WS, // Word select
.data_out_num = I2S_PIN_NO_CHANGE, // No usamos salida de datos
.data_in_num = I2S_SD // Entrada de datos desde micrófono
};
// Instalación del driver I2S
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
i2s_set_pin(I2S_PORT, &pin_config);
Serial.printf("I2S configurado: %d Hz, %d bits en pines WS:%d, SD:%d, SCK:%d\n",
SAMPLE_RATE, SAMPLE_BITS, I2S_WS, I2S_SD, I2S_SCK);
}
/**
* Captura muestras de audio desde el micrófono I2S
*/
void captureAudio() {
static int32_t samples[DMA_BUFFER_LENGTH]; // Buffer estático para muestras de audio
size_t bytes_read;
// Lee muestras de audio desde I2S con espera indefinida
i2s_read(I2S_PORT, samples, sizeof(samples), &bytes_read, portMAX_DELAY);
// Convierte bytes leídos a número de muestras
int samples_read = bytes_read / sizeof(int32_t);
// Procesa las muestras capturadas
processAudio(samples, samples_read);
}
/**
* Procesa las muestras de audio capturadas mediante FFT y cálculos acústicos
*
* @param samples Puntero al array de muestras capturadas
* @param samplesRead Número de muestras disponibles
*/
void processAudio(int32_t* samples, int samplesRead) {
// Calcular RMS verdadero (medida de la amplitud de la señal)
float rms = calculateRMS(samples, samplesRead);
// Preparar datos para FFT aplicando ventana de Hanning
for (int i = 0; i < FFT_SAMPLES && i < samplesRead; i++) {
// Aplicar ventana de Hanning para reducir fugas espectrales
float hann = 0.5 * (1 - cos(2 * PI * i / (FFT_SAMPLES - 1)));
vReal[i] = (double)samples[i] * hann;
vImag[i] = 0.0; // Parte imaginaria inicializada a 0
}
// Realizar la transformada rápida de Fourier (FFT)
performFFT(vReal, vImag, FFT_SAMPLES);
// Dividir el espectro en bandas de frecuencia (escala logarítmica)
for (int i = 0; i < NUM_BANDS; i++) {
// Cálculo de límites de cada banda usando escala logarítmica
int lowerBin = 2 + pow(2, i * 10.0 / NUM_BANDS);
int upperBin = 2 + pow(2, (i + 1) * 10.0 / NUM_BANDS);
// Limitar los índices al rango válido de la FFT
lowerBin = constrain(lowerBin, 2, FFT_SAMPLES / 2 - 1);
upperBin = constrain(upperBin, 2, FFT_SAMPLES / 2 - 1);
// Calcular el promedio de energía en esta banda
float sum = 0;
for (int j = lowerBin; j <= upperBin; j++) {
sum += vReal[j];
}
bandValues[i] = sum / (upperBin - lowerBin + 1);
}
// Aplicar ponderación A (simula respuesta del oído humano)
float dbA = applyAWeighting(bandValues, NUM_BANDS);
// Convertir a decibelios con ponderación A (dBA)
// Referencia estándar: 32768 es punto medio de int16 para normalización
float dbLevel = 20 * log10(dbA / 32768.0) + 0;
// Almacena el nivel en el buffer circular para suavizado temporal
buffer.push(dbLevel);
// Mostrar nivel de sonido en la consola serial
Serial.printf("Sound level: %.1f dB(A)\n", dbLevel);
}
/**
* Calcula el valor RMS verdadero (Root Mean Square) de la señal
* RMS es una medida estadística de la magnitud de una cantidad variable
*
* @param samples Puntero al array de muestras
* @param samplesRead Número de muestras disponibles
* @return Valor RMS calculado
*/
float calculateRMS(int32_t* samples, int samplesRead) {
double sum = 0;
for (int i = 0; i < samplesRead; i++) {
// Elevar al cuadrado cada muestra y acumular
sum += (double)samples[i] * samples[i];
}
// Dividir por el número de muestras y obtener la raíz cuadrada
return sqrt(sum / samplesRead);
}
/**
* Realizar FFT en los datos de audio usando la biblioteca ArduinoFFT
*
* @param vReal Puntero al array con la parte real de los datos
* @param vImag Puntero al array con la parte imaginaria de los datos
* @param samples Número de muestras a procesar
*/
void performFFT(double *vReal, double *vImag, int samples) {
// Crear objeto FFT con los arrays proporcionados
FFT = ArduinoFFT<double>(vReal, vImag, samples, SAMPLE_RATE);
// Aplicar ventana Hamming para mejorar precisión espectral
FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
// Calcular la FFT
FFT.compute(FFT_FORWARD);
// Convertir valores complejos a magnitudes
FFT.complexToMagnitude();
}
/**
* Aplica la ponderación A a las bandas de frecuencia para simular
* la respuesta del oído humano a diferentes frecuencias
*
* @param bandValues Array con valores de energía por banda
* @param numBands Número de bandas disponibles
* @return Valor ponderado según curva A
*/
float applyAWeighting(float* bandValues, int numBands) {
float weightedSum = 0;
float totalWeight = 0;
for (int i = 0; i < numBands; i++) {
// Calcular la frecuencia central aproximada de cada banda (Hz)
float freq = SAMPLE_RATE * (pow(2, i * 10.0 / numBands) + pow(2, (i + 1) * 10.0 / numBands)) / (4 * FFT_SAMPLES);
// Obtener el factor de ponderación A para esta frecuencia
float aWeight = freqToAWeight(freq);
// Aplicar el peso al valor de energía de la banda
weightedSum += bandValues[i] * aWeight;
totalWeight += aWeight;
}
// Normalizar por el total de pesos para mantener escala correcta
if (totalWeight > 0) {
return weightedSum / totalWeight;
}
return weightedSum;
}
/**
* Calcula el factor de ponderación A para una frecuencia dada
* La curva de ponderación A simula la sensibilidad del oído humano
* a diferentes frecuencias (menos sensible a frecuencias muy bajas o muy altas)
*
* @param freq Frecuencia en Hz para la que se calcula el factor
* @return Factor de ponderación A (0-1)
*/
float freqToAWeight(float freq) {
// Fórmula de aproximación para la curva de ponderación A
float f2 = freq * freq;
float f4 = f2 * f2;
// Constantes para la fórmula estándar de ponderación A
const float c1 = 12200 * 12200; // Constante relacionada con la frecuencia de resonancia del oído
const float c2 = 20.6 * 20.6; // Constante relacionada con respuesta a bajas frecuencias
const float c3 = 107.7 * 107.7; // Constante de ajuste de respuesta de medias frecuencias
const float c4 = 737.9 * 737.9; // Constante de ajuste de respuesta de altas frecuencias
// Calculamos la ponderación A según la fórmula estándar IEC 61672:2003
float num = c1 * f4;
float denom = (f2 + c2) * sqrt((f2 + c3) * (f2 + c4)) * (f2 + c1);
float A = num / denom;
return A;
}
/**
* Calcula el promedio de los niveles de sonido almacenados en el buffer
* para estabilizar la visualización y reducir fluctuaciones rápidas
*
* @return Nivel promedio en dB(A)
*/
float calculateAverageFromBuffer() {
if (buffer.isEmpty()) {
return 0.0; // Evitar cálculos innecesarios si el buffer está vacío
}
float avg = 0.0;
// Calcula el promedio de todos los valores en el buffer circular
using index_t = decltype(buffer)::index_t;
for (index_t i = 0; i < buffer.size(); i++) {
avg += buffer[i];
}
avg /= buffer.size();
Serial.print("Average dB(A): ");
Serial.println(avg);
return avg;
}
/**
* Actualiza la visualización LED según el nivel de sonido promedio
* Utiliza un esquema de colores que va de verde (bajo) a rojo (alto)
*
* @param averageDB Nivel de sonido promedio en dB(A)
*/
void updateLEDDisplay(float averageDB) {
// Mapea el nivel de audio a la cantidad de LEDs a encender
// DB_MIN y DB_MAX definen el rango de trabajo del sonómetro
int max_led = map(averageDB, DB_MIN, DB_MAX, 1, NUM_LEDS/STRIPS);
max_led = constrain(max_led, 0, NUM_LEDS/STRIPS);
Serial.print("LEDs activos: ");
Serial.println(max_led);
// Limpia la pantalla LED (apaga todos los LEDs)
FastLED.clear();
// Configura los LEDs con un gradiente de color según la intensidad
for(int i = 0; i < max_led; i++) {
// Colores basados en niveles de dB(A)
CRGB color;
if (i < NUM_LEDS / (3 * STRIPS)) {
// Verde para niveles bajos (0-33%)
color = CRGB(0, 255 - i * STEP, 0);
} else if (i < 2 * NUM_LEDS / (3 * STRIPS)) {
// Amarillo para niveles medios (33-66%)
color = CRGB(i * STEP, 255 - i * STEP, 0);
} else {
// Rojo para niveles altos (66-100%)
color = CRGB(255, 0, 0);
}
// Asigna el color calculado al LED actual
leds[i] = color;
// Código para múltiples tiras conectadas en zigzag (deshabilitado por defecto)
// Descomentar y ajustar para usar múltiples tiras conectadas en zigzag
/*
// Tira 2: orden inverso (para conexión en zigzag)
int i2 = 2 * NUM_LEDS/STRIPS - i - 1;
leds[i2] = color;
// Tira 3: orden normal
int i3 = i + 2 * NUM_LEDS/STRIPS;
leds[i3] = color;
// Tira 4: orden inverso
int i4 = 4 * NUM_LEDS/STRIPS - i - 1;
leds[i4] = color;
*/
}
// Actualiza físicamente los LEDs
FastLED.show();
}
Código completo del prototipo. Autor: Vicent Villena Serrano · Herramienta de refinamiento: Claude AI · Mayo de 2025.
Referencias
- Marzano, R. J. y Kendall, J. S. (2007). The New Taxonomy of Educational Objectives (2.ª ed.). Corwin Press.
- atomic14. ESP32 Audio Input. atomic14.com/2020/09/12/esp32-audio-input
No hay comentarios:
Publicar un comentario
Nota: solo los miembros de este blog pueden publicar comentarios.