Componentes · 19 min de lectura

Sensor de sonido Arduino (KY-038): aplausos y nivel de ruido

¿Cómo funciona el sensor de sonido KY-038/KY-037 con Arduino? Ajuste del potenciómetro, nivel pico a pico, lámpara con dos aplausos, vúmetro LED, ESP32 y Pico.

Cuando se habla de un sensor de sonido para Arduino, casi siempre se trata del KY-038: un módulo barato que reúne en una placa un pequeño micrófono electret, un comparador LM393 y un potenciómetro azul para ajustar la sensibilidad. Su hermano con micrófono grande, el KY-037, funciona igual. No necesitas ninguna librería: el pin DO cambia de estado cuando el sonido supera un umbral y se lee con digitalRead(), mientras que el pin AO entrega la señal en bruto del micrófono y se lee con analogRead(). Con este módulo se construyen lámparas que se encienden con aplausos, alarmas de ruido y luces que reaccionan a la música.

Pero este sensor tiene un límite importante que muchos tutoriales se saltan: el KY-038 es un detector de hay sonido o no hay sonido. No graba audio, no reconoce la voz y no puede medir decibelios. En este artículo aprenderás cómo funciona el circuito del módulo, cómo ajustar bien el potenciómetro, por qué la lectura analógica a menudo parece no cambiar nada y cómo medir correctamente la intensidad del sonido con el método pico a pico. Después montarás una lámpara que se enciende y se apaga con dos aplausos y un indicador de nivel con 8 LED, harás lo mismo con un ESP32 y una Raspberry Pi Pico y verás a qué módulos pasar cuando necesites medir sonido de verdad.

Módulo sensor de sonido KY-038 (micrófono electret y LM393)
Sensor de sonido KY-038: a la derecha el micrófono electret, en el centro el comparador LM393 y el potenciómetro azul de sensibilidad, y a la izquierda los pines AO, G, + y DO.

¿Qué es un sensor de sonido y cómo funciona?

El cilindro plateado del extremo de la placa es un micrófono de condensador electret. Dentro, una membrana fina queda frente a una placa con carga eléctrica permanente y juntas forman un pequeño condensador. El sonido es una variación de presión en el aire; al mover la membrana adelante y atrás, la capacidad cambia y aparece una variación de tensión muy pequeña. Un diminuto JFET dentro de la cápsula hace de búfer para esta señal; por eso el micrófono electret se alimenta a través de una resistencia y tiene polaridad. El resultado es una onda sonora de solo unos pocos milivoltios montada sobre una tensión continua fija.

El chip LM393 de 8 patas del centro de la placa contiene dos comparadores y el módulo usa uno de ellos. Un comparador mira dos tensiones: la señal del micrófono y el umbral que fija el potenciómetro. En cuanto la señal cruza el umbral, la salida cambia de estado y reaccionan el pin DO y el segundo LED de la placa. Aquí hay un detalle muy importante: un comparador no es un amplificador. No hace más grande la señal; solo responde a la pregunta «¿está por encima o por debajo del umbral?». Al pin AO llega la señal en bruto del micrófono, sin amplificar, y por eso la lectura analógica es tan débil.

CaracterísticaValor
MicrófonoCápsula de condensador electret, omnidireccional
ComparadorLM393 (comparador doble, se usa uno)
Alimentación3,3–5 V
ConsumoUnos pocos mA (unos 5–10 mA con los LED)
SalidasAO: señal en bruto del micrófono, DO: salida de umbral
Ajuste de sensibilidadTrimmer azul multivuelta (normalmente tipo 3296)
LEDUno de alimentación y otro del estado de DO
Orden de pinesAO, G, +, DO

Diferencia entre KY-038 y KY-037

El KY-038 y el KY-037 usan el mismo circuito, el mismo LM393 y el mismo orden de pines, así que todos los códigos de este artículo funcionan en ambos sin cambios. La diferencia está en la cápsula del micrófono: el KY-037 lleva una cápsula más grande y se vende como «sensor de sonido de alta sensibilidad», mientras que el KY-038 tiene una cápsula más pequeña y es el modelo que más verás en los kits de sensores. En la práctica, los dos detectan bien los sonidos fuertes cercanos, pero ninguno oye una conversación al otro lado de la habitación. También existen módulos de sonido LM393 de 3 pines con solo salida digital; en la mayoría la salida pasa a LOW cuando hay sonido.

ModeloPinesMicrófonoNota
KY-038AO, G, +, DOCápsula pequeñaEl modelo más común en los kits de sensores
KY-037AO, G, +, DOCápsula grandeMismo circuito y mismo código; suele ser algo más sensible
Módulo de sonido LM393 de 3 pinesVCC, GND, OUTCápsula pequeñaSolo salida digital; OUT suele pasar a LOW con sonido

Conexión del sensor de sonido: Arduino Uno, ESP32 y Pico

Pin del móduloArduino UnoESP32Raspberry Pi Pico
+5V3V33V3(OUT), pin 36
GGNDGNDGND, pin 38
AOA0GPIO 34 (ADC1)GP26 (ADC0), pin 31
DOD2GPIO 27GP15, pin 20
Los pines del ESP32 y de la Pico están diseñados para 3,3 V. En estas placas, alimenta el sensor de sonido desde el pin 3V3, no desde 5V, VIN ni VBUS; si no, la salida DO sube a 5 V y puede dañar el pin de entrada. En el ESP32 usa para AO uno de los pines ADC1 (GPIO 32–39): los pines ADC2 no se pueden leer con analogRead() mientras el Wi-Fi está activo.

Salida digital (DO) y ajuste del potenciómetro

El pin DO es una respuesta de sí o no. En muchas placas KY-038, DO pasa a HIGH y se enciende el segundo LED cuando el sonido supera el umbral; en algunos clones y en los módulos de 3 pines ocurre justo lo contrario. Por eso los códigos guardan el nivel que significa «hay sonido» en una constante llamada SOUND_ACTIVE. El segundo punto clave: DO no da un único pulso largo por cada aplauso. Como la onda sonora sube por encima del umbral y baja de él cientos de veces por segundo, la salida también se enciende y se apaga igual de rápido; un solo aplauso produce una ráfaga de pulsos cortos que dura unas decenas de milisegundos. La mayoría de las placas no tiene histéresis en el comparador, así que con sonidos cercanos al umbral la salida además vibra. Por tanto, lee DO con un bucle rápido sin delay() o con una interrupción, y cuenta como un solo evento los pulsos que llegan muy juntos.

  1. Conecta el módulo y coloca el sensor donde lo vas a usar, en un momento con el ruido ambiente normal; ajústalo siempre en el entorno real.
  2. Mira el LED de DO de la placa. Si está encendido de forma continua en silencio, el umbral es demasiado sensible; gira el potenciómetro con un destornillador pequeño hasta que el LED se apague.
  3. Si el LED no se enciende nunca, gíralo en el sentido contrario hasta encontrar el punto en el que empieza a encenderse.
  4. Desde ese punto, retrocede media vuelta o una vuelta hacia el lado en el que el LED se queda apagado. Así los ruidos constantes, como una nevera o un ventilador, no lo dispararán.
  5. Aplaude a un metro más o menos: el LED debería parpadear un instante. Si también se enciende al hablar normalmente, gíralo un poco hacia menos sensible; si no se enciende con un aplauso, un poco hacia más sensible.
El potenciómetro azul de estas placas suele ser un trimmer multivuelta tipo 3296 que necesita unas 25 vueltas de un extremo a otro. Si lo giras varias veces y el LED no cambia, no está roto; solo tienes que seguir girando. Al llegar al final del recorrido el tornillo empieza a patinar, así que no hace falta forzarlo.
Arduino (C++)
1// KY-038 DO testi: sesi algıla ve dahili LED'i yak / KY-038 DO test: detect sound and light the built-in LED
2const int SOUND_DO = 2;               // modülün DO pini / module DO pin
3const int SOUND_ACTIVE = HIGH;        // ses gelince HIGH; kartın tersse LOW / HIGH on sound; LOW if your board is inverted
4const unsigned long HOLD_MS = 200;    // yeni olay için gereken sessizlik / silence needed for a new event
5
6unsigned long lastSound = 0;
7unsigned long events = 0;
8
9void setup() {
10  Serial.begin(9600);
11  pinMode(SOUND_DO, INPUT);
12  pinMode(LED_BUILTIN, OUTPUT);
13}
14
15void loop() {
16  unsigned long now = millis();
17  if (digitalRead(SOUND_DO) == SOUND_ACTIVE) {
18    if (now - lastSound > HOLD_MS) {  // sessizlikten sonra ilk darbe / first pulse after silence
19      events++;
20      Serial.print(F("Ses algilandi / Sound detected #"));
21      Serial.println(events);
22    }
23    lastSound = now;                  // darbe yağmuru süreyi uzatır / the pulse burst extends the time
24  }
25  digitalWrite(LED_BUILTIN, now - lastSound < HOLD_MS ? HIGH : LOW);  // LED en az 200 ms yanar / LED stays on at least 200 ms
26}

El código lee el pin DO en cada vuelta del bucle sin delay(). Cada vez que DO está activo se renueva el tiempo lastSound; un nuevo evento solo se cuenta tras 200 ms de silencio, así que la ráfaga de pulsos de un aplauso aparece como una sola línea en el Monitor Serie. El LED integrado también se mantiene encendido al menos 200 ms; si no, no podrías ver a simple vista pulsos de milisegundos. Si el contador no para de subir en silencio, o el umbral es demasiado sensible o la salida DO de tu placa está invertida; en el segundo caso, pon SOUND_ACTIVE a LOW.

¿Por qué es tan débil la lectura analógica (AO)?

La mayoría de los principiantes conecta AO a A0, imprime el valor de analogRead() y ve un número cercano a 500 que apenas cambia con el sonido. El sensor no está roto; el problema es la escala. El ADC de 10 bits del Arduino Uno divide 0–5 V en 1024 pasos, así que un paso equivale a unos 4,9 mV. Con sonidos normales, la señal que genera el micrófono es mucho más pequeña que ese paso:

SonidoNivel aproximadoSalida del micrófono (pico a pico)Pasos del ADC en el Uno
Susurro30 dB SPL~0,01 mV0
Conversación normal (1 m)60 dB SPL~0,4 mV0 (invisible)
Televisión alta, tráfico80 dB SPL~3,6 mV0–1
Sonido muy fuerte (1 Pa)94 dB SPL~18 mV3–4
Aplauso fuerte o claxon de cerca110 dB SPL~110 mV~23

La tabla se calculó con −44 dBV/Pa, la sensibilidad de una cápsula electret típica, suponiendo un sonido senoidal. Según la resistencia de polarización del micrófono de tu placa, los valores reales pueden ser varias veces mayores, pero la conclusión no cambia: AO solo ve con claridad los sonidos fuertes y cercanos, mientras que la conversación normal y los susurros quedan por debajo de la resolución del Uno. Encontrarás más detalles sobre cómo funciona el ADC en ¿Qué es un ADC?.

La segunda razón es la propia naturaleza del sonido. El sonido es una onda que oscila arriba y abajo alrededor de un nivel de continua. Un solo analogRead() captura un instante aleatorio de esa onda: puede caer en una cresta, en un valle o justo en el centro. Por eso el tamaño de una única lectura no dice nada sobre la intensidad del sonido. La tercera razón es la velocidad: el Uno tarda unos 100 microsegundos en cada lectura analógica, así que toma como mucho unas 10.000 muestras por segundo. Eso basta para seguir el nivel de sonido, pero no para grabar audio ni analizar frecuencias. Por último, el ruido de la alimentación de 5 V del USB se cuela directamente en AO. Las dos primeras causas se resuelven con el método de medida adecuado.

Medir la amplitud pico a pico: leer bien la intensidad del sonido

El método correcto es tomar tantas muestras como puedas durante una ventana de tiempo corta y buscar el valor más alto y el más bajo. Su diferencia es la amplitud pico a pico y muestra lo fuerte que es el sonido sin importar el nivel de continua. 50 ms es una buena ventana: un periodo de 20 Hz, la frecuencia más baja que oye el oído humano, dura exactamente 50 ms, así que incluso el sonido más grave cabe con una onda completa. El Uno toma unas 450–500 muestras en ese tiempo.

Arduino (C++)
1// Tepe-tepe genlik ölçümü (Seri Çizici için) / Peak-to-peak amplitude (for the Serial Plotter)
2const int SOUND_AO = A0;                 // modülün AO pini / module AO pin
3const unsigned long WINDOW_MS = 50;      // 50 ms = 20 Hz'in bir periyodu / one period of 20 Hz
4
5void setup() {
6  Serial.begin(115200);
7}
8
9void loop() {
10  int minV = 1023, maxV = 0;
11  long sum = 0;
12  int count = 0;
13  unsigned long start = millis();
14  while (millis() - start < WINDOW_MS) { // yaklaşık 450-500 örnek / about 450-500 samples
15    int v = analogRead(SOUND_AO);
16    if (v < minV) minV = v;
17    if (v > maxV) maxV = v;
18    sum += v;
19    count++;
20  }
21  int p2p = maxV - minV;                 // tepe-tepe genlik / peak-to-peak amplitude
22  float mv = p2p * 5000.0 / 1024.0;      // milivolt karşılığı / in millivolts
23
24  Serial.print(F("p2p:"));
25  Serial.print(p2p);
26  Serial.print(F(" ortalama_avg:"));     // AO'nun DC seviyesi; istemezsen bu iki satırı sil / DC level of AO; delete these two lines if not needed
27  Serial.print(sum / count);
28  Serial.print(F(" mV:"));
29  Serial.println(mv, 1);
30}

Después de cargar el código, abre el Serial Plotter desde el menú Herramientas y pon la velocidad en 115200. En una habitación silenciosa p2p suele quedarse entre 0 y 3; sube unas pocas unidades si hablas junto al micrófono y decenas de unidades si aplaudes de cerca. El valor ortalama_avg es el nivel de continua de AO y, como estira la escala de la gráfica, puedes borrar las dos líneas de ortalama_avg si quieres seguir p2p con comodidad. En algunas placas el potenciómetro también desplaza ese nivel; si la media se queda pegada en 0 o en 1023, la señal se está recortando, así que gira el potenciómetro hasta que el valor quede hacia el centro. Si es la primera vez que usas el Serial Plotter, echa un vistazo a Monitor Serie de Arduino.

Paso a paso: encender y apagar una lámpara con dos aplausos

La lámpara que se enciende con aplausos es el proyecto más conocido con un sensor de sonido, pero un circuito que reacciona a un solo aplauso también se activa con un portazo, un libro que cae o una tos, y la lámpara no para de encenderse y apagarse. La solución es buscar un ritmo: el siguiente código solo responde a exactamente dos aplausos separados entre 0,12 y 0,7 segundos. Un sonido aislado, o tres o más sonidos (música, una ovación, un perro ladrando), se ignoran.

  1. Conecta el pin + del KY-038 a 5V, G a GND y DO a D2.
  2. Conecta el pin VCC del módulo de relé a 5V, GND a GND e IN a D7. Encontrarás cómo funciona un relé y cómo cablear el lado de la carga en ¿Qué es un módulo de relé?; haz las primeras pruebas con el LED del propio relé en lugar de una lámpara.
  3. Carga el código y abre el Monitor Serie a 9600 baudios.
  4. Aplaude dos veces a uno o dos metros del sensor. Deberías ver una sola línea «Alkis / Clap» por aplauso; si un aplauso se cuenta más de una vez, gira el potenciómetro un poco hacia menos sensible.
  5. Comprueba que la lámpara cambia de estado unos 0,7 segundos después del segundo aplauso.
Arduino (C++)
1// Çift alkışla lamba (röle) / Double-clap lamp (relay)
2const int SOUND_DO = 2;                     // KY-038 DO pini / KY-038 DO pin
3const int RELAY = 7;                        // röle modülü IN / relay module IN
4const int SOUND_ACTIVE = HIGH;              // kartın tersse LOW / LOW if your board is inverted
5const int RELAY_ON = LOW;                   // aktif LOW röle modülü / active-LOW relay module
6const int RELAY_OFF = HIGH;
7const unsigned long QUIET_GAP_MS = 120;     // yeni alkış için gereken sessizlik / silence needed before a new clap
8const unsigned long CLAP_WINDOW_MS = 700;   // dizinin bittiğine karar verme süresi / time to decide the series is over
9const unsigned long LOCKOUT_MS = 1000;      // röle tıkırtısını yok say / ignore the relay click
10
11int clapCount = 0;
12unsigned long lastPulse = 0;                // DO'nun son aktif olduğu an / last time DO was active
13unsigned long lastToggle = 0;               // lambanın son değiştiği an / last time the lamp changed
14bool lampOn = false;
15
16void setup() {
17  Serial.begin(9600);
18  pinMode(SOUND_DO, INPUT);
19  pinMode(RELAY, OUTPUT);
20  digitalWrite(RELAY, RELAY_OFF);           // lamba kapalı başlar / lamp starts off
21}
22
23void loop() {
24  unsigned long now = millis();
25
26  if (digitalRead(SOUND_DO) == SOUND_ACTIVE) {
27    bool locked = now - lastToggle < LOCKOUT_MS;
28    if (!locked && now - lastPulse >= QUIET_GAP_MS) {  // sessizlikten sonra ilk darbe = yeni alkış / first pulse after silence = new clap
29      clapCount++;
30      Serial.print(F("Alkis / Clap: "));
31      Serial.println(clapCount);
32    }
33    lastPulse = now;                        // aynı alkışın darbeleri süreyi uzatır / pulses of the same clap extend the time
34  }
35
36  if (clapCount > 0 && now - lastPulse > CLAP_WINDOW_MS) {  // dizi bitti / the series is over
37    if (clapCount == 2) {                   // yalnız tam iki alkış / exactly two claps only
38      lampOn = !lampOn;
39      digitalWrite(RELAY, lampOn ? RELAY_ON : RELAY_OFF);
40      lastToggle = now;
41      if (lampOn) Serial.println(F("Lamba ACIK / Lamp ON"));
42      else Serial.println(F("Lamba KAPALI / Lamp OFF"));
43    }
44    clapCount = 0;                          // 1, 3 ve fazlası yok sayılır / 1, 3 or more are ignored
45  }
46}
ConstanteValorFunción
SOUND_ACTIVEHIGHNivel que toma DO cuando hay sonido; ponlo a LOW si tu placa está invertida
QUIET_GAP_MS120 msSilencio necesario antes de contar un nuevo aplauso; la ráfaga de pulsos y el eco de un aplauso cuentan como uno
CLAP_WINDOW_MS700 msTras este silencio desde el último sonido, la serie se da por terminada y se evalúan los aplausos
LOCKOUT_MS1000 msTras cambiar la lámpara se ignoran los sonidos para que el clic del relé no se confunda con un aplauso
RELAY_ON / RELAY_OFFLOW / HIGHPara un módulo de relé activo a nivel bajo; intercámbialos en uno activo a nivel alto

El código no usa delay(): lo mide todo con millis(), así que no se pierde el momento de ningún aplauso. Explicamos este enfoque en detalle en millis vs delay. Que la lámpara cambie 0,7 segundos después del segundo aplauso y no al instante es una decisión intencionada: el código espera a ver si llega un tercer aplauso. Si quieres una respuesta más rápida, puedes bajar CLAP_WINDOW_MS a 400–500 ms, pero entonces tendrás que aplaudir más rápido. Si tu habitación tiene mucho eco y un solo aplauso se cuenta dos veces, sube QUIET_GAP_MS a 150–200 ms.

Conmutar la tensión de red (110–230 V) con un relé puede ser mortal. Haz las conexiones con el enchufe desconectado, no dejes extremos de cable al aire y mete el circuito en una caja aislante y cerrada; si no estás seguro, prueba primero con una tira LED de 12 V. Coloca además el sensor lejos del relé: si el clic del relé queda muy cerca del micrófono, puede dar problemas pese al tiempo de bloqueo.

Indicador de nivel de sonido: vúmetro con 8 LED

Llevar el valor pico a pico directamente a los LED funciona, pero no parece natural, porque nuestro oído percibe el sonido de forma logarítmica: un sonido con el doble de amplitud no nos parece el doble de fuerte. Por eso el sonido se mide en decibelios (dB). Para la amplitud, la fórmula es dB = 20 × log10(p2p / referencia); el doble de amplitud son +6 dB y diez veces más son +20 dB. El siguiente código mide durante un segundo al arrancar el ruido de fondo de la habitación y lo toma como referencia; cada LED representa 3 dB por encima de ese fondo. Conecta los LED a los pines D3–D10, cada uno con una resistencia de 220 Ω; para LED de otros colores puedes calcular la resistencia adecuada con la calculadora de resistencia para LED.

Arduino (C++)
1// 8 LED'li ses seviyesi göstergesi (VU metre) / 8-LED sound level bar (VU meter)
2const int SOUND_AO = A0;                    // modülün AO pini / module AO pin
3const int LED_PINS[8] = {3, 4, 5, 6, 7, 8, 9, 10};  // her LED 220 Ω ile / each LED with 220 Ω
4const float DB_PER_LED = 3.0;               // her LED 3 dB / each LED is 3 dB
5const unsigned long FALL_MS = 80;           // LED'ler bu aralıkla birer birer söner / LEDs drop one by one at this rate
6
7float noiseFloor = 1.0;                     // sessiz ortamın p2p değeri / quiet-room p2p
8int shown = 0;                              // yanan LED sayısı / number of lit LEDs
9unsigned long lastFall = 0;
10
11int readPeakToPeak() {
12  int minV = 1023, maxV = 0;
13  unsigned long start = millis();
14  while (millis() - start < 50) {           // 50 ms pencere / 50 ms window
15    int v = analogRead(SOUND_AO);
16    if (v < minV) minV = v;
17    if (v > maxV) maxV = v;
18  }
19  return maxV - minV;
20}
21
22void setup() {
23  Serial.begin(115200);
24  for (int i = 0; i < 8; i++) pinMode(LED_PINS[i], OUTPUT);
25  long sum = 0;
26  for (int i = 0; i < 20; i++) sum += readPeakToPeak();  // 1 sn sessizlik ölç / measure 1 s of silence
27  noiseFloor = sum / 20.0;
28  if (noiseFloor < 1.0) noiseFloor = 1.0;
29}
30
31void loop() {
32  int p2p = readPeakToPeak();
33  if (p2p < 1) p2p = 1;
34  float db = 20.0 * log10(p2p / noiseFloor);  // tabana göre göreceli dB / relative dB above the floor
35  int level = constrain((int)(db / DB_PER_LED), 0, 8);
36
37  unsigned long now = millis();
38  if (level >= shown) {                     // yükselişte anında / rise instantly
39    shown = level;
40    lastFall = now;
41  } else if (now - lastFall >= FALL_MS) {   // inişte yavaşça / fall slowly
42    shown--;
43    lastFall = now;
44  }
45  for (int i = 0; i < 8; i++) digitalWrite(LED_PINS[i], i < shown ? HIGH : LOW);
46
47  Serial.print(F("dB:"));
48  Serial.println(db, 1);
49}

Asegúrate de guardar silencio un segundo al arrancar; si hablas en ese momento, el fondo se mide demasiado alto y el indicador reacciona menos. El indicador sube al instante pero baja despacio, un LED cada 80 ms; por eso los vúmetros reales se ven fluidos y no nerviosos. Como la señal analógica del KY-038 es débil, 2–3 dB por LED es lo adecuado; si usas el mismo código con un micrófono amplificado como el MAX4466, puedes subir DB_PER_LED a 4–6 dB. Para un indicador de colores puedes usar un anillo NeoPixel en lugar de los LED; los detalles están en LED NeoPixel WS2812B.

Sensor de sonido con ESP32: detectar aplausos con una interrupción

El ADC del ESP32 es de 12 bits y da valores de 0 a 4095; en un rango de 3,3 V un paso equivale a unos 0,8 mV, es decir, una resolución unas 6 veces más fina que la del Uno. A cambio, el ADC del ESP32 es más ruidoso, así que el valor p2p en una habitación silenciosa también sale más alto; el cálculo de dB relativos compensa esa diferencia por sí solo. En el siguiente código el pin DO se asocia a una interrupción: no se pierde ningún pulso de aplauso aunque loop() esté ocupado midiendo el nivel de sonido en AO durante 50 ms. La función de interrupción se coloca en la RAM con IRAM_ATTR y se mantiene corta; las variables que usan tanto la interrupción como loop() se declaran volatile y se protegen con una sección crítica.

Arduino (C++)
1// ESP32: kesmeyle çift alkış + ses seviyesi / ESP32: double clap via interrupt + sound level
2const int SOUND_AO = 34;                    // ADC1 pini, Wi-Fi açıkken de çalışır / ADC1 pin, works with Wi-Fi on
3const int SOUND_DO = 27;                    // modülün DO pini / module DO pin
4const int RELAY = 26;                       // röle modülü IN / relay module IN
5const int SOUND_ACTIVE = HIGH;              // kartın tersse LOW / LOW if your board is inverted
6const int RELAY_ON = LOW;                   // aktif LOW röle / active-LOW relay
7const int RELAY_OFF = HIGH;
8const unsigned long QUIET_GAP_MS = 120;     // yeni alkış için sessizlik / silence before a new clap
9const unsigned long CLAP_WINDOW_MS = 700;   // dizinin bitmesi / end of the series
10const unsigned long LOCKOUT_MS = 1000;      // röle tıkırtısını yok say / ignore the relay click
11
12portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;  // kesme ile loop arasında kilit / lock between ISR and loop
13volatile int clapCount = 0;
14volatile unsigned long lastPulse = 0;
15volatile unsigned long lastToggle = 0;
16bool lampOn = false;
17float noiseFloor = 1.0;
18
19void IRAM_ATTR onSound() {                  // kısa tutulur, RAM'den çalışır / kept short, runs from RAM
20  unsigned long now = millis();
21  portENTER_CRITICAL_ISR(&mux);
22  if (now - lastToggle >= LOCKOUT_MS && now - lastPulse >= QUIET_GAP_MS) clapCount++;
23  lastPulse = now;
24  portEXIT_CRITICAL_ISR(&mux);
25}
26
27int readPeakToPeak() {
28  int minV = 4095, maxV = 0;
29  unsigned long start = millis();
30  while (millis() - start < 50) {           // 50 ms pencere / 50 ms window
31    int v = analogRead(SOUND_AO);           // 0-4095 (12 bit)
32    if (v < minV) minV = v;
33    if (v > maxV) maxV = v;
34  }
35  return maxV - minV;
36}
37
38void setup() {
39  Serial.begin(115200);
40  pinMode(SOUND_DO, INPUT);
41  pinMode(RELAY, OUTPUT);
42  digitalWrite(RELAY, RELAY_OFF);
43  long sum = 0;
44  for (int i = 0; i < 20; i++) sum += readPeakToPeak();  // 1 sn sessiz ortam / 1 s of quiet room
45  noiseFloor = sum / 20.0;
46  if (noiseFloor < 1.0) noiseFloor = 1.0;
47  attachInterrupt(digitalPinToInterrupt(SOUND_DO), onSound, SOUND_ACTIVE == HIGH ? RISING : FALLING);
48}
49
50void loop() {
51  int p2p = readPeakToPeak();               // bu sırada alkışları kesme yakalar / the interrupt catches claps meanwhile
52  float db = 20.0 * log10((p2p < 1 ? 1 : p2p) / noiseFloor);
53  Serial.printf("p2p:%d dB:%.1f\n", p2p, db);
54
55  portENTER_CRITICAL(&mux);
56  unsigned long now = millis();
57  int claps = clapCount;
58  bool finished = claps > 0 && now - lastPulse > CLAP_WINDOW_MS;
59  if (finished) clapCount = 0;              // dizi bitti, sayacı sıfırla / series over, reset the counter
60  portEXIT_CRITICAL(&mux);
61
62  if (finished && claps == 2) {             // yalnız tam iki alkış / exactly two claps only
63    lampOn = !lampOn;
64    digitalWrite(RELAY, lampOn ? RELAY_ON : RELAY_OFF);
65    portENTER_CRITICAL(&mux);
66    lastToggle = millis();
67    portEXIT_CRITICAL(&mux);
68    Serial.println(lampOn ? "Lamba ACIK / Lamp ON" : "Lamba KAPALI / Lamp OFF");
69  }
70}

El código ejecuta la misma lógica de doble aplauso que en el Uno, pero dentro de la interrupción, e imprime el nivel de sonido en dB más o menos cada 50 ms. Conecta el pin IN del módulo de relé al GPIO 26; algunos módulos de relé activos a nivel bajo alimentados a 5 V no se desactivan del todo con el nivel HIGH de 3,3 V del ESP32, así que en ese caso elige un módulo que se pueda controlar a 3,3 V. La verdadera fuerza del ESP32 es el Wi-Fi: si el nivel de sonido se mantiene por encima de un umbral durante unos segundos (por ejemplo, si llora un bebé o ladra un perro), puedes enviar una notificación a tu móvil. Para ello usa el método de bot de Telegram con ESP32 y, para conectarlo a un sistema domótico, ESP32 con MQTT y Home Assistant.

Sensor de sonido con Raspberry Pi Pico y MicroPython

En la Raspberry Pi Pico, alimenta el módulo desde el pin 3V3(OUT), conecta AO a GP26 y DO a GP15, y en lugar de una lámpara pon un LED con una resistencia de 220 Ω en GP14. El ADC de la Pico es de 12 bits, pero en MicroPython read_u16() escala el valor a 0–65535; por eso los números de p2p parecen mucho mayores que en el Uno, mientras que el cálculo de dB relativos no cambia. Para el pin DO se define una interrupción con Pin.irq().

MicroPython
1# Raspberry Pi Pico: çift alkış + ses seviyesi / double clap + sound level
2from machine import Pin, ADC
3import time, math
4
5sound_ao = ADC(26)                  # GP26 = ADC0, modülün AO pini / module AO pin
6sound_do = Pin(15, Pin.IN)          # modülün DO pini / module DO pin
7lamp = Pin(14, Pin.OUT, value=0)    # LED (220 Ω ile) / LED (with 220 Ω)
8
9QUIET_GAP_MS = 120                  # yeni alkış için sessizlik / silence before a new clap
10CLAP_WINDOW_MS = 700                # dizinin bitmesi / end of the series
11LOCKOUT_MS = 1000                   # değişimden sonra sesleri yok say / ignore sounds after a toggle
12
13claps = 0
14last_pulse = time.ticks_ms()
15last_toggle = time.ticks_ms()
16
17def on_sound(pin):                  # kesme fonksiyonu / interrupt handler
18    global claps, last_pulse
19    now = time.ticks_ms()
20    if (time.ticks_diff(now, last_toggle) >= LOCKOUT_MS
21            and time.ticks_diff(now, last_pulse) >= QUIET_GAP_MS):
22        claps += 1
23    last_pulse = now
24
25# DO sesle LOW oluyorsa IRQ_FALLING yaz / use IRQ_FALLING if DO goes LOW on sound
26sound_do.irq(trigger=Pin.IRQ_RISING, handler=on_sound)
27
28def peak_to_peak(window_ms=50):     # 50 ms boyunca en büyük - en küçük / max - min over 50 ms
29    lo, hi = 65535, 0
30    start = time.ticks_ms()
31    while time.ticks_diff(time.ticks_ms(), start) < window_ms:
32        v = sound_ao.read_u16()     # 0-65535
33        if v < lo:
34            lo = v
35        if v > hi:
36            hi = v
37    return hi - lo
38
39noise_floor = max(1, sum(peak_to_peak() for _ in range(20)) / 20)  # 1 sn sessizlik / 1 s of silence
40
41while True:
42    p2p = peak_to_peak()
43    db = 20 * math.log10(max(p2p, 1) / noise_floor)   # göreceli dB / relative dB
44    print("p2p:", p2p, "dB:", round(db, 1))
45
46    now = time.ticks_ms()
47    if claps and time.ticks_diff(now, last_pulse) > CLAP_WINDOW_MS:
48        if claps == 2:              # yalnız tam iki alkış / exactly two claps only
49            lamp.toggle()
50            last_toggle = now
51            print("Lamba / Lamp:", "ON" if lamp.value() else "OFF")
52        claps = 0

Al ejecutar el código en Thonny verás los valores de p2p y dB en la consola (Shell); si abres el Plotter desde el menú Ver, podrás seguirlos como gráfica. Si la salida DO de tu placa pasa a LOW con el sonido, escribe IRQ_FALLING en lugar de IRQ_RISING. Para que el programa arranque solo al alimentar la Pico, guarda el archivo en la Pico con el nombre main.py. Si eres nuevo en MicroPython, fundamentos de MicroPython es un buen punto de partida.

¿Se pueden medir decibelios con un sensor de sonido?

Respuesta corta: no. En internet encontrarás muchos códigos que convierten con map() el valor pico a pico del KY-038 en un rango como 49–90 dB; son estimaciones, no mediciones. Para medir un nivel de presión sonora real (dB SPL) necesitas un micrófono de sensibilidad conocida y un sistema ajustado con un calibrador de 94 dB, una amplificación lineal de la señal, un valor eficaz (RMS) calculado durante un tiempo fijo (125 ms en modo rápido, 1 s en modo lento) y un filtro de ponderación A que imita la sensibilidad del oído. Por eso los sonómetros se fabrican según la norma IEC 61672.

El KY-038 no cumple ninguna de estas condiciones: la ganancia de la placa es desconocida, la sensibilidad de las cápsulas varía unos cuantos dB de una a otra, el potenciómetro y la tensión de alimentación cambian el nivel de la señal y, en el Uno, todos los sonidos normales se comprimen en unos pocos pasos del ADC. Lo más honesto que puedes hacer es una medición relativa: decir «ahora mismo hay 12 dB más de ruido que en la habitación en silencio». Incluso eso es más que suficiente para una alarma de ruido, un semáforo de ruido para el aula o un vúmetro. Puedes hacer una calibración aproximada comparando con una app del móvil en un punto, pero esa calibración deja de valer en otros niveles de sonido y en otra placa.

Alternativas: MAX4466, MAX9814 e INMP441

MóduloSalidaGananciaMedición en decibeliosPlacas compatibles
KY-038 / KY-037AO (en bruto) + DO (umbral)NingunaNoTodas
MAX4466Analógica, centrada en VCC/225–125 veces, ajustableSolo relativaTodas
MAX9814Analógica, centrada en 1,25 V, máx. 2 Vpp40 / 50 / 60 dB + control automático de ganancia (AGC)No, el AGC comprime el nivelTodas
INMP441Digital I2S, 24 bitsNo hace faltadB SPL aproximadosESP32, Pico (no el Uno)
Módulo medidor de nivel sonoro (p. ej. DFRobot SEN0232)Analógica, directamente en dBACalibrado de fábricaSí, 30–130 dBA, ±1,5 dBTodas

El MAX4466 combina el mismo tipo de micrófono electret con un amplificador operacional de ganancia ajustable. Su salida se queda en la mitad de la tensión de alimentación en silencio y, con una conversación normal cerca, da una señal de cientos de milivoltios; es decir, la señal de unos pocos pasos del ADC del KY-038 pasa a decenas o incluso cientos de pasos. Los códigos de pico a pico y del vúmetro de este artículo funcionan con el MAX4466 sin ningún cambio. Si te interesa cómo se calcula la ganancia, consulta la calculadora de ganancia de amplificador operacional y ¿Qué es un amplificador operacional?. Alimentar el módulo desde el pin 3.3V del Uno, que es más limpio, reduce el ruido. El MAX9814, en cambio, sube incluso la voz lejana a un nivel útil gracias a su control automático de ganancia; es genial para grabar y detectar voz, pero no sirve para medir niveles porque acerca entre sí los ambientes silenciosos y los ruidosos.

El INMP441 ni siquiera es analógico, sino un micrófono MEMS digital: convierte el sonido internamente en números de 24 bits y los envía por un bus I2S, así que el ruido de los cables no entra en la medición. Su gran ventaja es que el fabricante indica su sensibilidad con una tolerancia estrecha: un sonido de 94 dB SPL se lee como −26 dBFS. Así, si conviertes a dBFS el valor RMS que mides y le sumas 120, obtienes un valor aproximado en dB SPL. Para I2S necesitas un ESP32 o una Pico; el Arduino Uno no tiene hardware I2S. Los módulos INMP441 para aficionados son baratos y fáciles de encontrar, y el ICS-43434 y el SPH0645 son micrófonos I2S parecidos. Si de verdad necesitas una medición de ruido precisa, lo más sencillo es un módulo medidor de nivel sonoro con salida calibrada y ponderación A; por ejemplo, al multiplicar por 50 la tensión de salida del DFRobot SEN0232 obtienes directamente el valor en dBA.

Ideas de proyectos con sensor de sonido

  • Lámpara con aplausos: Añade un módulo de relé al código de doble aplauso para controlar la lámpara de tu escritorio o una tira LED, y asigna tres aplausos a un segundo aparato.
  • Semáforo de ruido para el aula: Un indicador que enciende LED verdes, amarillos y rojos según el valor relativo en dB; a los profesores les encanta.
  • Vigilabebés y aviso para mascotas: Si el sonido sigue alto más de 5 segundos, el ESP32 envía un mensaje de Telegram a tu móvil.
  • Luces que reaccionan al sonido: Un anillo o una tira NeoPixel que late al ritmo de la música.
  • Detector de golpes en la puerta: Un montaje que avisa con un zumbador o un LED cuando alguien llama; para captar el golpe como vibración en lugar de sonido, el sensor de vibración SW-420 también es una buena opción.
  • Escenarios de casa inteligente: Combina el sonido con sensores de movimiento y de luz para apagar las luces cuando no hay nadie en la habitación; encontrarás ideas en proyecto de casa inteligente con Arduino.

Errores frecuentes y cómo solucionarlos

SíntomaCausa probableSolución
El LED de DO está siempre encendidoEl umbral es demasiado sensible o hay un ruido constante (ventilador, nevera)Gira el potenciómetro en silencio hasta que el LED se apague y aleja el sensor de la fuente de ruido
No pasa nada al aplaudirEl umbral es demasiado alto o DO está en el pin equivocadoComprueba primero que el LED de la placa parpadea con el aplauso y luego revisa el cable y el número de pin del código
El contador sube en silencio y se para con el sonidoLa salida DO de la placa es activa a nivel bajoPon SOUND_ACTIVE a LOW; en la Pico usa IRQ_FALLING
analogRead se queda cerca de 500 y cambia 1–2 con el sonidoAO no está amplificada y solo se hacen lecturas sueltasUsa el método pico a pico, acerca el sonido o pásate a un MAX4466
AO siempre marca 0 o 1023AO y DO están intercambiados o el nivel de continua se ha ido al extremoRevisa el cableado y lleva la media al centro con el potenciómetro
Un aplauso se cuenta dos vecesLa habitación tiene eco o QUIET_GAP_MS es demasiado cortoPon QUIET_GAP_MS a 150–200 ms y haz el umbral algo menos sensible
La lámpara se enciende y se apaga solaClic del relé, portazos o músicaAumenta LOCKOUT_MS, aleja el sensor del relé y mantén la regla del doble aplauso
En el ESP32, AO deja de leer al activar el Wi-FiAO está en un pin ADC2Pasa AO a un pin ADC1 entre GPIO 32 y 39
Una forma práctica de probar el sensor de sonido es una app generadora de tonos en el móvil. Reproduce un tono constante de 1 kHz y coloca el móvil a 10, 20 y 40 cm del micrófono: en campo abierto, cada vez que la distancia se duplica la presión sonora se reduce a la mitad, así que p2p debería bajar más o menos a la mitad y el valor en dB unos 6 dB. Este sencillo experimento comprueba a la vez tu cableado y tu código.

Con unos pocos cables y un código bien escrito, el KY-038 enseña a la vez muchos fundamentos de la electrónica: comparadores, conversión analógico-digital, interrupciones, temporización y cálculo de decibelios. Empieza detectando aplausos con DO, mide el nivel de sonido con el método pico a pico y pasa a un MAX4466 o a un INMP441 cuando necesites medir sonido de verdad. En la app BlueGrays encontrarás proyectos de lámpara con relé, LED secuenciales, iluminación inteligente con ESP32 y tira NeoPixel con esquemas de circuito y código paso a paso; añadirles un sensor de sonido es la forma más fácil de convertirlos en sistemas que responden a aplausos o al ruido.

Preguntas frecuentes

¿Cómo funciona un sensor de sonido de Arduino?

El sensor de sonido compara, mediante un comparador LM393, la pequeña tensión de su micrófono electret con un umbral fijado por el potenciómetro. Cuando el sonido supera el umbral, el pin DO cambia de estado y se enciende el LED de la placa. El pin AO entrega la señal en bruto del micrófono, sin amplificar, que se lee con analogRead().

¿Qué diferencia hay entre el KY-038 y el KY-037?

Los dos usan el mismo circuito LM393 y el mismo orden de pines AO, G, +, DO, y el código es idéntico. El KY-037 lleva una cápsula de micrófono más grande y suele ser algo más sensible; el KY-038 es más pequeño y más habitual en los kits de sensores.

¿Cómo se ajusta la sensibilidad de un sensor de sonido?

En silencio, gira el potenciómetro azul hasta el punto en que el LED de DO parpadea y luego retrocede media vuelta o una vuelta hacia el lado en que el LED queda apagado. Como es un potenciómetro multivuelta, quizá necesites varias vueltas antes de ver algún cambio. Ajústalo siempre en el lugar donde se va a usar el sensor.

¿Se pueden medir decibelios con un sensor de sonido?

Con el KY-038 y el KY-037 no se pueden medir decibelios reales (dB SPL): la ganancia de la placa y la sensibilidad del micrófono son desconocidas y no hay calibración ni ponderación A. Solo se pueden calcular dB relativos respecto a una habitación en silencio. Para mediciones reales, usa un micrófono I2S de sensibilidad conocida como el INMP441 o un módulo medidor de nivel sonoro calibrado.

¿Por qué no cambia el valor analógico de mi sensor de sonido?

La salida AO es la señal del micrófono sin amplificar y, con sonidos normales, es menor que un paso del ADC del Uno, de 4,9 mV. Además, un solo analogRead() lee un instante aleatorio de la onda sonora. Si tomas muestras durante 50 ms y calculas la diferencia entre el valor más alto y el más bajo (pico a pico), verás el cambio con claridad.

¿Funciona el sensor de sonido con ESP32 y Raspberry Pi Pico?

Sí, el módulo también funciona a 3,3 V; en el ESP32 y en la Pico aliméntalo desde el pin 3V3 para que la salida DO nunca supere los 3,3 V. En el ESP32 conecta AO a un pin ADC1 (GPIO 32–39), que no choca con el Wi-Fi, y en la Pico a GP26, GP27 o GP28.

Ver todos los proyectos
Encender y apagar un LED con un botón
#10Principiante

Encender y apagar un LED con un botón

Pulsas el botón una vez y la luz se enciende, lo pulsas otra vez y se apaga, igual que el interruptor de tu habitación. El Arduino nota cada pulsación y cambia el LED al estado contrario, esperando un

4.8(100)
162
Control de LED con botón en ESP32 (Toggle)
#105Principiante

Control de LED con botón en ESP32 (Toggle)

Cada vez que se pulsa el botón, cambia el estado del LED: si está encendido se apaga, si está apagado se enciende. Patrón de conmutación clásico. Con debounce limpiamos el ruido mecánico del pulsador para garantizar una sola conmutación con una sola pulsación.

4.6(39)
57
Luz secuencial LED
#5Intermedio

Luz secuencial LED

Luces que se encienden una tras otra, como si corrieran. El Arduino enciende seis LED de uno en uno; cada uno brilla un instante y se apaga, así que la luz recorre la fila de principio a fin y vuelve

4.6(85)
201
Encender y apagar una bombilla de 220 V con un botón
#20Avanzado
Premium

Encender y apagar una bombilla de 220 V con un botón

¿Quieres encender y apagar una bombilla de verdad de casa con un pequeño botón? Cada vez que lo pulsas, el Arduino acciona un relé y la bombilla se enciende; si vuelves a pulsar, se apaga. El relé es

4.5(33)
44
Raspberry Pi Pico Botón Toggle LED (GP14 + GP2)
#156Principiante
Premium

Raspberry Pi Pico Botón Toggle LED (GP14 + GP2)

¡Botón + LED — siguiente nivel! 🔁 A diferencia de #155, no necesitas mantener el botón presionado. Presiona y suelta → LED encendido. Presiona de nuevo → LED apagado (toggle). Mismo circuito que #155, gran diferencia de código. Aprende edge detection, state tracking y debounce.

0.0(0)
9
Iluminación Inteligente ESP32 (PIR + LDR + Relé + OLED)
#141Avanzado
Premium

Iluminación Inteligente ESP32 (PIR + LDR + Relé + OLED)

¡Convierte tu pasillo, baño o despensa en iluminación inteligente con ESP32! Utilizando un sensor de movimiento PIR, un sensor de luz LDR y un módulo de relé, construimos el escenario clásico "la luz se enciende cuando se detecta movimiento en la oscuridad" — si el ambiente ya está iluminado, el movimiento NO activa la luz, ahorrando energía durante el día. La luz permanece encendida durante 30 segundos; si el movimiento continúa, el temporizador se reinicia y la luz permanece encendida más tiem

4.3(6)
11
Sensor de aparcamiento ESP32 (HC-SR04 + barra de 5 LED + zumbador + OLED)
#142Avanzado
Premium

Sensor de aparcamiento ESP32 (HC-SR04 + barra de 5 LED + zumbador + OLED)

¡La versión ESP32 del sensor de aparcamiento para coches! Medimos la distancia al objeto que hay delante mediante el sensor ultrasónico HC-SR04. A medida que la distancia disminuye, la barra de 5 LED se va llenando (verde → amarillo → rojo) y la frecuencia de los pitidos del zumbador se acorta. Cuando se acerca demasiado (menos de 10 cm), suena una alarma continua y se encienden todos los LED. En la pantalla OLED SSD1306 se muestra, en letra grande, el valor actual en centímetros, un mensaje de

0.0(0)
14
Control de la tira NeoPixel WS2812B con ESP32
#126Intermedio
Premium

Control de la tira NeoPixel WS2812B con ESP32

Los LED direccionables WS2812B (NeoPixel) son LED RGB inteligentes que se pueden controlar en cadena a través de un único pin de datos. En este proyecto, controlaremos una tira de 8 LED WS2812B con la biblioteca Adafruit_NeoPixel para crear una animación fluida de arcoíris. Aunque el nivel lógico de 3,3 V del ESP32 funciona sin problemas en la mayoría de los componentes WS2812B, mostraremos la solución de una resistencia en serie de 470 Ω y un condensador de 1000 µF en caso de inestabilidad. La

4.9(19)
30