La taxonomía de objetivos de aprendizaje de Marzano y Kendall (2007) incorpora, en el máximo nivel, el Sistema de Conciencia del Ser (autorregulación)
Modificar los hábitos de habla en un espacio mejorado acústicamente no es automático, requiere facilitar la autorregulación (evaluando la importancia, la eficacia, las emociones y la motivación)
Objetivo: facilitar a los hablantes que se autorregulen con la toma de conciencia del nivel de logro en la mejora.
Para ello crearemos un dispositivo colectivo que mide y muestra visualmente el nivel de intensidad sonora.
🎯 Autoregulación Escolar: El Semáforo Acústico Inteligente
🚦 Transformando Espacios Educativos a través de la Conciencia Sonora
Más allá de ser una herramienta de aprendizaje STEM, este sonómetro visual se convierte en un agente de cambio conductual que promueve ambientes escolares más saludables y productivos.
🟢 ZONA VERDE (40-55 dB) → 📚 CONCENTRACIÓN ÓPTIMA
├── Lectura individual fluida
├── Trabajo en grupos pequeños
└── Explicaciones del profesorado claras
🟡 ZONA AMARILLA (55-70 dB) → ⚠️ ALERTA PREVENTIVA
├── Actividades colaborativas moderadas
├── Discusiones dirigidas
└── Transiciones entre actividades
🔴 ZONA ROJA (+70 dB) → 🚨 ACCIÓN NECESARIA
├── Ruido excesivo que interfiere
├── Pérdida de concentración
└── Necesidad de intervención inmediata
💡 Beneficios Observados:
- ✅ Autorregulación inmediata: Los estudiantes ajustan su volumen al ver los LEDs
- ✅ Reducción del estrés docente: Menos necesidad de intervenciones verbales
- ✅ Mejora del rendimiento: Ambiente más propicio para el aprendizaje
- ✅ Desarrollo de la conciencia social: Respeto por el espacio compartido
🍽️ COMEDORES: Ambiente Alimentario Saludable
🎨 Estrategia Visual del "Termómetro del Comedor"
🟢 COMIDA TRANQUILA (50-65 dB) └── 😌 Digestión óptima + Conversación relajada └── 🗣️ Socialización saludable └── ✨ Experiencia gastronómica positiva 🟡 SOCIALIZACIÓN ACTIVA (65-75 dB) └── 👥 Interacción social normal └── 🎉 Celebraciones moderadas └── ⚖️ Balance entre social y salud 🔴 SOBRECARGA SENSORIAL (+75 dB) └── 😰 Estrés alimentario └── 🔊 Comunicación dificultada └── 💢 Ambiente poco saludable
🎯 Principios Pedagógicos Aplicados
🟢 Refuerzo Positivo Inmediato
- Verde = Aprobación: Los estudiantes sienten satisfacción inmediata
- Gamificación natural: "Mantener el verde" se convierte en un juego
- Reconocimiento social: El grupo se autorregula colectivamente
🟡 Zona de Atención Sin Castigo
- Amarillo = Prevención: Alerta temprana sin consecuencias negativas
- Oportunidad de corrección: Tiempo para autoajuste antes del problema
- Aprendizaje gradual: Desarrollo de la conciencia acústica
🔴 Indicador de Acción Necesaria
- Rojo = Llamada de atención: Señal clara pero no punitiva
- Responsabilidad compartida: Todo el grupo participa en la solución
- Reflexión sobre consecuencias: Conexión entre ruido y bienestar
🧠 Psicología de la Autoregulación Visual
⚡ Feedback Inmediato vs Intervención Tardía
SISTEMA TRADICIONAL:
Ruido → Molestia → Intervención Adulta → Corrección
🔊 😤 👨🏫 📉
(Reactivo - Genera conflicto)
SISTEMA SONÓMETRO LED:
Ruido → Visualización → Autorregulación → Mantenimiento
🔊 🌈 😊 ✅
(Proactivo - Genera conciencia)
SISTEMA TRADICIONAL:
Ruido → Molestia → Intervención Adulta → Corrección
🔊 😤 👨🏫 📉
(Reactivo - Genera conflicto)
SISTEMA SONÓMETRO LED:
Ruido → Visualización → Autorregulación → Mantenimiento
🔊 🌈 😊 ✅
(Proactivo - Genera conciencia)
📈 Impacto en la Convivencia Escolar
🎓 Competencias de Ciudadanía Desarrolladas
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 pares |
📊 Conciencia Ambiental | Comprensión causa-efecto | Correlación ruido-bienestar |
🧠 Impacto Neurológico
- Reducción del cortisol: Menos estrés por ruido excesivo
- Mejora de la concentración: Ambiente más propicio para el focus
- Calidad del sueño: Menos fatiga auditiva acumulada
👂 Protección Auditiva
- Prevención de daños: Exposición controlada a niveles seguros
- Educación en salud auditiva: Conciencia sobre límites saludables
- Hábitos de por vida: Desarrollo de sensibilidad acústica permanente
🌱 Desarrollo Social
- Comunicación efectiva: Mejor calidad en las conversaciones
- Resolución de conflictos: Menos tensiones por ruido excesivo
- Inclusión: Ambiente más cómodo para estudiantes sensibles
🔧 Componentes STEM Integrados
STEM | Componente | Aplicación |
---|---|---|
🧪 Science | Análisis FFT + Ponderación A | Física del sonido y psicoacústica |
💻 Technology | Micrófono I2S + ESP32 | Procesamiento digital de señales |
⚙️ Engineering | Diseño de circuitos + LEDs | Sistemas embebidos y visualización |
📊 Mathematics | Algoritmos DSP + Estadística | Transformadas, promedios y mapeo |
📈 Medir el sonido
No es sencillo por varios motivos que podéis consultar en este enlace
Queremos una sensibilidad y una banda de frecuencia suficiente 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 oido.
Nuestra elección, por coste rendimiento, ha sido el micrófono digital MEMS INP441
Como segunda opción, el MEMS ICS-43434
Ambos trabajan con el interface I2S que encontramos en el ESP32.
Algunos prototipos comunes 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 interface I2S hay que verificar que está disponible en nuestra controladora.
Nuestro prototipo utiliza una ESP32-S3 supermini. Tambien ha funcionado con la azdelivery Lolin32 y ESP32 D1 R32
📊Visualización
Para visualizar los dB medidos utilizamos una tira Neopixel.
El número de leds iluminados de la tira corresponden al nivel de dB(A) medido.
El color va variando, los primeros leds verdes, después pasan a ámbar y los niveles máximos en rojo.
Es un híbrido de semáforo y vúmetro led (vúmetrro semafórico)
⚙️Prototipo
⚙️Conexiones
1. Micrófono I2S al ESP32
Micrófono I2S | ESP32 GPIO |
---|---|
VDD (3.3V) | 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 GPIO | Fuente Externa |
---|---|---|
DIN (Data) | GPIO 8 | - |
5V | - | 5V |
GND | GND | GND |
Nota importante: Para la alimentación de los LEDs:
- Si son pocos LEDs (como en este caso), se puede usar la salida 5V del ESP32
- Para más de 8-10 LEDs, usar una fuente externa de 5V y conectar GND común
3. Consideraciones adicionales
- Capacitor de filtrado
- Colocar un capacitor de 1000μF entre 5V y GND cerca de la tira LED. Ayuda a estabilizar la alimentación y previene picos de corriente
- Resistencia de protección
- Colocar una resistencia de 330-470Ω entre GPIO 8 y la entrada de datos de la tira LED
- Protege el primer LED y el GPIO del microcontrolador
📊Test de medición
Para la realización de la prueba hemos añadido una pantalla OLED que muestra los dB medidos para poder comparar con la medición del sonómetro comercial.
Nuestro visualizador mide entre 40 y 90 dB.
Los micrófonos MEMS tinen una limitación en la medición de intensidades de sonido. 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.
Vista la precisión, podemos incrementar el número de leds por tira hasta 25, equivaldria a 2 dB por led.
En las imágenes de comprobación de precisión, pueden verse las lecturas del prototipo y de una versión funcional de mayor tamaño (40 cm x 10 cm), con cuatro tiras led para asegurar la visualización con luz de dia y a distancia.
Listo para trabajar la autorregulación de los hablantes en nuevos espacios de aprendizaje.
También en comedores escolares acústicamente mejorados.
💻Código Arduino.
Estructura y componentes principales
- Hardware utilizado:
- Microcontrolador ESP32
- Micrófono digital I2S INMP441
- Tira de LEDs WS2812B (11 LEDs configurados)
- Bibliotecas clave:
Arduino.h
- Framework basedriver/i2s.h
- Interfaz de audio digitalFastLED.h
- Control de LEDsCircularBuffer.hpp
- Gestión de buffer circular para datosarduinoFFT.h
- Análisis de frecuencias
Flujo de funcionamiento
El sistema opera en un ciclo continuo con estas etapas:
- Configuración inicial (
setup()
):- Inicialización de LEDs (apagados)
- Configuración del bus I2S para comunicación con el micrófono
- Preparación de estructuras de datos para FFT
- Ciclo principal (
loop()
):- Captura constante de audio a través de I2S
- Actualización de visualización LED cada 50ms (configurable)
- Procesamiento de audio (
processAudio()
):- Cálculo de RMS (Root Mean Square) de la señal
- Aplicación de FFT para análisis espectral
- División del espectro en 12 bandas de frecuencia
- Aplicación de ponderación A (simula respuesta del oído humano)
- Conversión a decibelios (dBA)
- Almacenamiento en buffer circular
- Visualización (
updateLEDDisplay()
):- Mapeo de niveles de sonido a número de LEDs activos
- Asignación de colores según intensidad:
- Verde: niveles bajos
- Amarillo: niveles medios
- Rojo: niveles altos
Características técnicas clave
- Muestreo de audio:
- Frecuencia: 44.1 kHz (calidad CD)
- Resolución: 32 bits
- Buffer DMA: 8 buffers de 1024 muestras
- Análisis espectral:
- FFT de 1024 puntos
- Ventana Hanning/Hamming para mejor precisión
- 12 bandas de frecuencia en escala logarítmica
- Procesamiento acústico:
- Cálculo de RMS verdadero
- Ponderación A (dBA) para simular percepción humana
- Rango configurable: 40-90 dB
Diagrama de flujo de datos
Micrófono I2S → Captura muestras → Cálculo RMS → FFT →
Análisis por bandas → Ponderación A → Conversión a dB →
Buffer circular → Promediado → Mapeo a LEDs → Visualización
Optimizaciones implementadas
- Rendimiento:
- Uso de DMA para captura de audio sin bloqueo
- Ventana FFT para reducir efectos de borde
- Buffer circular para estabilizar lecturas
- Precisión acústica:
- Ponderación A para mejor representación de percepción humana
- Escala logarítmica para 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(); }
No hay comentarios:
Publicar un comentario