Sensor de som KY-038 com Arduino: interruptor por palmas e nível sonoro
Como funciona o sensor de som KY-038/KY-037 com Arduino? Ajuste do potenciômetro, nível sonoro pico a pico, lâmpada com duas palmas, barra de LEDs, código para ESP32 e Pico e a verdade sobre os decibéis.
Quando se fala em sensor de som para Arduino, quase sempre é o KY-038: um módulo barato que reúne em uma única placa um pequeno microfone de eletreto, um comparador LM393 e um potenciômetro azul de sensibilidade. O irmão de microfone grande, o KY-037, funciona do mesmo jeito. Você não precisa de biblioteca: o pino DO muda de estado quando o som passa de um limiar e é lido com digitalRead(), enquanto o pino AO entrega o sinal bruto do microfone e é lido com analogRead(). Lâmpadas que acendem com palmas, alarmes de ruído e luzes que reagem ao som são feitos com esse módulo.
Só que esse sensor tem um limite importante que muitos tutoriais pulam: o KY-038 é um detector de som / sem som. Ele não grava áudio, não reconhece fala e não mede decibéis. Neste artigo você vai ver como funciona o circuito do módulo, como ajustar o potenciômetro do jeito certo, por que a leitura analógica muitas vezes parece não mudar nada e como medir a intensidade do som corretamente com o método pico a pico. Depois você vai montar uma lâmpada que liga e desliga com duas palmas e uma barra de nível sonoro com 8 LEDs, fazer as mesmas tarefas com um ESP32 e um Raspberry Pi Pico e descobrir para quais módulos migrar quando precisar de uma medição de som de verdade.

O que é um sensor de som e como ele funciona?
O cilindro prateado na ponta da placa é um microfone de condensador de eletreto. Dentro dele, um diafragma fino fica de frente para uma placa que carrega uma carga elétrica permanente, formando um capacitor minúsculo. O som é uma onda de pressão no ar; enquanto ela empurra o diafragma para a frente e para trás, a capacitância muda e aparece uma variação de tensão muito pequena. Um JFET minúsculo dentro da cápsula faz o buffer desse sinal, e é por isso que o microfone de eletreto é alimentado por um resistor e tem polaridade. O resultado no microfone é uma onda sonora de apenas alguns milivolts sobreposta a uma tensão DC fixa.
O chip LM393 de 8 pinos no meio da placa tem dois comparadores, e o módulo usa um deles. Um comparador olha para duas tensões: o sinal que vem do microfone e o limiar definido pelo potenciômetro. No instante em que o sinal cruza o limiar, a saída muda de estado, e o pino DO e o segundo LED da placa respondem. Aqui vai um detalhe muito importante: um comparador não é um amplificador. Ele não aumenta o sinal; só responde à pergunta “está acima ou abaixo do limiar?”. O pino AO leva o sinal bruto do microfone, sem amplificação, e é por isso que a leitura analógica é tão fraca.
| Característica | Valor |
|---|---|
| Microfone | Cápsula de condensador de eletreto, omnidirecional |
| Comparador | LM393 (comparador duplo, um deles é usado) |
| Alimentação | 3,3–5 V |
| Corrente | Alguns mA (cerca de 5–10 mA contando os LEDs) |
| Saídas | AO: sinal bruto do microfone, DO: saída de limiar |
| Ajuste de sensibilidade | Trimpot azul multivoltas (geralmente do tipo 3296) |
| LEDs | Um de alimentação, um do estado do DO |
| Ordem dos pinos | AO, G, +, DO |
KY-038 ou KY-037
O KY-038 e o KY-037 usam o mesmo circuito, o mesmo LM393 e a mesma ordem de pinos, então todos os sketches deste artigo rodam nos dois sem alterações. A diferença está na cápsula do microfone: o KY-037 tem uma cápsula maior e é vendido como “sensor de som de alta sensibilidade”, enquanto o KY-038 tem uma cápsula menor e é o modelo que você mais encontra em kits de sensores. Na prática, os dois captam bem sons altos por perto, mas nenhum vai ouvir alguém falando do outro lado da sala. Você também encontra módulos de som LM393 de 3 pinos com apenas saída digital; na maioria deles a saída vai para LOW quando há som.
| Modelo | Pinos | Microfone | Observação |
|---|---|---|---|
| KY-038 | AO, G, +, DO | Cápsula pequena | O modelo mais comum nos kits de sensores |
| KY-037 | AO, G, +, DO | Cápsula grande | Mesmo circuito e mesmo código; geralmente um pouco mais sensível |
| Módulo de som LM393 de 3 pinos | VCC, GND, OUT | Cápsula pequena | Só saída digital; OUT geralmente vai para LOW com som |
Ligação do sensor de som: Arduino Uno, ESP32 e Pico
| Pino do módulo | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| + | 5V | 3V3 | 3V3(OUT), pino 36 |
| G | GND | GND | GND, pino 38 |
| AO | A0 | GPIO 34 (ADC1) | GP26 (ADC0), pino 31 |
| DO | D2 | GPIO 27 | GP15, pino 20 |
Saída digital (DO) e ajuste do potenciômetro
O pino DO é uma resposta de sim ou não. Em muitas placas KY-038, o DO vai para HIGH e o segundo LED acende quando o som passa do limiar; em algumas placas clone e nos módulos de 3 pinos é o contrário. Por isso os sketches guardam o nível que significa “som” em uma constante chamada SOUND_ACTIVE. O segundo ponto-chave: o DO não dá um pulso longo por palma. Como a onda sonora sobe acima do limiar e desce abaixo dele centenas de vezes por segundo, a saída liga e desliga na mesma velocidade; uma única palma produz uma rajada de pulsos curtos que dura algumas dezenas de milissegundos. A maioria das placas não tem histerese no comparador, então a saída também oscila com sons próximos do limiar. Por isso, leia o DO com um laço rápido, sem delay(), ou com uma interrupção, e trate pulsos muito próximos como um único evento.
- Ligue o módulo e coloque o sensor no lugar onde ele vai ser usado, em um momento com ruído de fundo normal; faça o ajuste sempre no ambiente real.
- Observe o LED do DO na placa. Se ele fica aceso em silêncio, o limiar está sensível demais; gire o potenciômetro com uma chave de fenda pequena até o LED apagar.
- Se o LED nunca acende, gire para o outro lado até achar o ponto em que ele começa a acender.
- A partir desse ponto, volte de meia volta a uma volta inteira para o lado em que o LED fica apagado. Assim, ruídos constantes como os de uma geladeira ou de uma ventoinha não vão disparar o sensor.
- Bata palmas a cerca de um metro de distância: o LED deve piscar rapidamente. Se ele também acende com fala normal, gire um pouco para o lado menos sensível; se não acende com a palma, gire um pouco para o lado mais sensível.
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}O sketch lê o pino DO a cada ciclo, sem delay(). Toda vez que o DO está ativo, o instante lastSound é atualizado; um novo evento só é contado depois de 200 ms de silêncio, de modo que a rajada de pulsos de uma palma aparece como uma única linha no Monitor Serial. O LED embutido também fica aceso por pelo menos 200 ms; senão você não conseguiria ver pulsos de milissegundos a olho nu. Se o contador continua subindo em silêncio, ou o limiar está sensível demais ou a saída DO da sua placa é invertida; no segundo caso, defina SOUND_ACTIVE como LOW.
Por que a leitura analógica (AO) é tão fraca?
A maioria dos iniciantes liga o AO no A0, imprime o valor de analogRead() e vê um número em torno de 500 que quase não muda com o som. O sensor não está com defeito; o problema é de escala. O ADC de 10 bits do Arduino Uno divide 0–5 V em 1024 passos, então um passo vale cerca de 4,9 mV. Com sons normais, o sinal que o microfone produz é bem menor que esse passo:
| Som | Nível aproximado | Saída do microfone (pico a pico) | Passos do ADC no Uno |
|---|---|---|---|
| Sussurro | 30 dB SPL | ~0,01 mV | 0 |
| Fala normal (1 m) | 60 dB SPL | ~0,4 mV | 0 (invisível) |
| TV alta, trânsito | 80 dB SPL | ~3,6 mV | 0–1 |
| Som muito alto (1 Pa) | 94 dB SPL | ~18 mV | 3–4 |
| Palma forte ou buzina de carro de perto | 110 dB SPL | ~110 mV | ~23 |
A tabela foi calculada com −44 dBV/Pa, a sensibilidade de uma cápsula de eletreto típica, supondo um som senoidal. Dependendo do resistor de polarização do microfone na sua placa, os valores reais podem ser algumas vezes maiores, mas a conclusão não muda: o AO só enxerga com clareza sons próximos e altos, enquanto a fala normal e o sussurro ficam abaixo da resolução do Uno. Você encontra mais sobre como o ADC funciona em O que é um ADC?.
O segundo motivo é a própria natureza do som. O som é uma onda que oscila para cima e para baixo em torno de um nível DC. Um único analogRead() pega um instante aleatório dessa onda: pode cair em um pico, em um vale ou bem no meio. Por isso o tamanho de uma leitura isolada não diz nada sobre a intensidade do som. O terceiro motivo é a velocidade: o Uno leva cerca de 100 microssegundos por leitura analógica, então consegue no máximo umas 10.000 amostras por segundo. Isso basta para acompanhar o nível sonoro, mas não para gravar áudio nem analisar frequências. Por fim, o ruído da alimentação de 5 V que vem do USB vaza direto para o AO. Os dois primeiros problemas você resolve com o método de medição certo.
Medindo a amplitude pico a pico: como ler a intensidade do som corretamente
O método certo é pegar o maior número possível de amostras durante uma janela de tempo curta e encontrar o maior e o menor valor. A diferença entre eles é a amplitude pico a pico, que mostra a força do som independentemente do nível DC. 50 ms é uma boa janela: um período de 20 Hz, a frequência mais baixa que o ouvido humano consegue ouvir, dura exatamente 50 ms, então até o som mais grave cabe com uma onda completa na janela. O Uno faz cerca de 450–500 amostras nesse tempo.
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}Depois de carregar o sketch, abra o Plotter Serial pelo menu Ferramentas e ajuste a velocidade para 115200. Em uma sala silenciosa o p2p costuma ficar entre 0 e 3; ele sobe algumas unidades quando você fala perto do microfone e dezenas de unidades quando você bate palmas de perto. O valor ortalama_avg é o nível DC do AO e, como ele estica a escala do gráfico, você pode apagar as duas linhas de ortalama_avg se quiser acompanhar o p2p com conforto. Em algumas placas o potenciômetro também desloca esse nível DC; se a média estiver travada em 0 ou 1023, o sinal está saturando (clipping), então gire o potenciômetro até o valor ficar perto do meio. Se você nunca usou o Plotter Serial, dê uma olhada em Monitor Serial do Arduino.
Passo a passo: ligando e desligando uma lâmpada com duas palmas
A lâmpada acionada por palmas é o projeto mais conhecido com sensor de som, mas um circuito que funciona com uma palma só também dispara com uma porta batendo, um livro caindo ou uma tosse, e a lâmpada fica acendendo e apagando sem parar. A solução é procurar um ritmo: o sketch abaixo só reage a exatamente duas palmas separadas por 0,12 a 0,7 segundo. Um som isolado, ou três ou mais sons (música, aplausos, um cachorro latindo), é ignorado.
- Ligue o pino + do KY-038 no 5V, o G no GND e o DO no D2.
- Ligue o pino VCC do módulo relé no 5V, o GND no GND e o IN no D7. Como um relé funciona e como ligar o lado da carga você encontra em O que é um módulo relé?; faça os primeiros testes com o próprio LED do relé em vez de uma lâmpada.
- Carregue o sketch e abra o Monitor Serial a 9600 baud.
- Bata duas palmas a um ou dois metros de distância. Você deve ver só uma linha “Alkis / Clap” (palma) por palma; se uma única palma for contada mais de uma vez, gire o potenciômetro um pouco para o lado menos sensível.
- Veja a lâmpada mudar de estado cerca de 0,7 segundo depois da segunda palma.
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}| Constante | Valor | Função |
|---|---|---|
| SOUND_ACTIVE | HIGH | O nível que o DO assume quando há som; defina como LOW se a sua placa for invertida |
| QUIET_GAP_MS | 120 ms | O silêncio necessário antes de contar uma nova palma; a rajada de pulsos e o eco de uma palma contam como uma só |
| CLAP_WINDOW_MS | 700 ms | Depois desse tempo de silêncio desde o último som, a sequência é considerada encerrada e as palmas são avaliadas |
| LOCKOUT_MS | 1000 ms | Depois que a lâmpada muda, os sons são ignorados para que o clique do relé não seja confundido com uma nova palma |
| RELAY_ON / RELAY_OFF | LOW / HIGH | Para um módulo relé ativo em LOW; inverta os dois em uma placa ativa em HIGH |
O sketch não usa delay(); ele mede tudo com millis(), então o tempo entre as palmas nunca se perde. Explicamos essa abordagem em detalhes em millis ou delay. A lâmpada mudar 0,7 segundo depois da segunda palma, e não na hora, é uma escolha proposital: o sketch espera para ver se vem uma terceira palma. Se quiser uma resposta mais rápida, você pode baixar CLAP_WINDOW_MS para 400–500 ms, mas aí vai precisar bater palmas mais rápido. Se o seu cômodo tem muito eco e uma única palma é contada duas vezes, aumente QUIET_GAP_MS para 150–200 ms.
Barra de nível sonoro: um VU meter com 8 LEDs
Mandar o valor pico a pico direto para os LEDs funciona, mas não parece natural, porque nossos ouvidos percebem o som de forma logarítmica: um som com o dobro da amplitude não parece duas vezes mais alto. É por isso que o som é medido em decibéis (dB). Para amplitude, a fórmula é dB = 20 × log10(p2p / referência); o dobro da amplitude dá +6 dB e dez vezes dá +20 dB. O sketch abaixo mede o piso de ruído da sala durante um segundo na inicialização e usa esse valor como referência; cada LED representa 3 dB acima desse piso. Ligue os LEDs nos pinos D3–D10, cada um com um resistor de 220 Ω; para LEDs de outras cores, você encontra o resistor certo com a calculadora de resistor para LED.
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}Fique em silêncio por um segundo na inicialização; se você falar nesse momento, o piso é medido alto demais e a barra reage menos. A barra sobe na hora, mas desce devagar, um LED a cada 80 ms; é também por isso que os VU meters de verdade parecem suaves, e não trêmulos. Como o sinal analógico do KY-038 é fraco, 2–3 dB por LED combina com ele; se você usar o mesmo sketch com um microfone amplificado como o MAX4466, pode aumentar DB_PER_LED para 4–6 dB. Para um display colorido, você pode usar um anel NeoPixel em vez de LEDs; os detalhes estão em LED WS2812B NeoPixel.
Sensor de som com ESP32: detecção de palmas com interrupção
O ADC do ESP32 é de 12 bits e dá valores de 0 a 4095; em uma faixa de 3,3 V, um passo vale cerca de 0,8 mV, umas 6 vezes mais fino que no Uno. Por outro lado, o ADC do ESP32 é mais ruidoso, então o p2p em uma sala silenciosa também sai mais alto; o cálculo de dB relativo compensa isso sozinho. No sketch abaixo, o pino DO é ligado a uma interrupção: os pulsos das palmas não se perdem nem enquanto o loop() está ocupado medindo o nível sonoro do AO por 50 ms. A função de interrupção é colocada na RAM com IRAM_ATTR e mantida curta, e as variáveis usadas tanto pela interrupção quanto pelo loop() são declaradas como volatile e protegidas por uma seção crítica.
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}O sketch roda a mesma lógica de duas palmas do Uno, só que dentro da interrupção, e imprime o nível sonoro em dB mais ou menos a cada 50 ms. Ligue o pino IN do módulo relé no GPIO 26; alguns módulos relé ativos em LOW alimentados com 5 V não desligam totalmente com o nível HIGH de 3,3 V do ESP32, então, nesse caso, escolha um módulo que possa ser acionado com 3,3 V. O ponto forte de verdade do ESP32 é o Wi-Fi: se o nível sonoro ficar acima de um limite por alguns segundos (digamos, um bebê chorando ou um cachorro latindo), você pode mandar uma notificação para o seu celular. Para isso, use o método de Bot do Telegram com ESP32 e, para integrar a um sistema de automação residencial, ESP32 com MQTT e Home Assistant.
Sensor de som com Raspberry Pi Pico e MicroPython
No Raspberry Pi Pico, alimente o módulo pelo pino 3V3(OUT) e ligue o AO no GP26 e o DO no GP15; em vez de uma lâmpada, coloque um LED com resistor de 220 Ω no GP14. O ADC do Pico é de 12 bits, mas no MicroPython o read_u16() escala o valor para 0–65535; por isso os números de p2p parecem bem maiores que no Uno, enquanto o cálculo de dB relativo continua o mesmo. Uma interrupção é configurada no pino DO com Pin.irq().
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 = 0Ao rodar o código no Thonny, você vê os valores de p2p e dB no Shell; abra o Plotter pelo menu View para acompanhá-los em gráfico. Se a saída DO da sua placa vai para LOW com som, escreva IRQ_FALLING no lugar de IRQ_RISING. Para o programa iniciar sozinho quando o Pico for ligado, salve o arquivo no Pico com o nome main.py. Se você está começando no MicroPython, Fundamentos de MicroPython é um bom ponto de partida.
Um sensor de som consegue medir decibéis?
Resposta curta: não. Na internet você encontra muitos sketches que usam map() para transformar o valor pico a pico do KY-038 em uma faixa como 49–90 dB; isso é chute, não medição. Para medir um nível de pressão sonora real (dB SPL), você precisa de um microfone com sensibilidade conhecida e de um sistema calibrado com um calibrador de 94 dB, de amplificação linear do sinal, de um valor RMS calculado em um tempo definido (125 ms no modo rápido, 1 s no lento) e de um filtro de ponderação A que imita a sensibilidade do ouvido. É por isso que os decibelímetros são fabricados segundo a norma IEC 61672.
O KY-038 não atende a nenhuma dessas condições: o ganho da placa é desconhecido, a sensibilidade das cápsulas de microfone varia alguns dB de uma para outra, o potenciômetro e a tensão de alimentação mudam o nível do sinal e, no Uno, todos os sons normais ficam espremidos em poucos passos do ADC. O mais honesto que você pode fazer é uma medição relativa: dizer “agora está 12 dB mais alto que a sala em silêncio”. Mesmo isso já é mais que suficiente para um alarme de ruído, um semáforo de barulho para a sala de aula ou um VU meter. Dá para fazer uma calibração grosseira comparando com um app de celular em um ponto, mas essa calibração perde o sentido em outros níveis sonoros e em outra placa.
Alternativas: MAX4466, MAX9814 e INMP441
| Módulo | Saída | Ganho | Medição de decibéis | Placas compatíveis |
|---|---|---|---|---|
| KY-038 / KY-037 | AO (bruto) + DO (limiar) | Nenhum | Não | Todas |
| MAX4466 | Analógica, centrada em VCC/2 | 25–125×, ajustável | Só relativa | Todas |
| MAX9814 | Analógica, centrada em 1,25 V, máx. 2 Vpp | 40 / 50 / 60 dB + controle automático de ganho (AGC) | Não, o AGC comprime o nível | Todas |
| INMP441 | Digital I2S, 24 bits | Não é necessário | dB SPL aproximado | ESP32, Pico (não o Uno) |
| Módulo pronto de nível sonoro (ex.: DFRobot SEN0232) | Analógica, direto em dBA | Calibrado de fábrica | Sim, 30–130 dBA, ±1,5 dB | Todas |
O MAX4466 combina o mesmo tipo de microfone de eletreto com um amplificador operacional de ganho ajustável. Em silêncio, a saída fica em metade da tensão de alimentação e, com fala normal por perto, entrega um sinal de centenas de milivolts; ou seja, o sinal de poucos passos do ADC do KY-038 vira dezenas ou até centenas de passos. Os sketches de pico a pico e de VU meter deste artigo funcionam com o MAX4466 sem nenhuma alteração. Se tiver curiosidade sobre como o ganho é calculado, veja a calculadora de ganho de amplificador operacional e O que é um amplificador operacional?. Alimentar o módulo pelo pino 3.3V do Uno, que é mais limpo, reduz o ruído. Já o MAX9814 usa controle automático de ganho para trazer até a fala distante para um nível utilizável; ele é ótimo para gravação e detecção de voz, mas, como aproxima ambientes silenciosos e barulhentos, não serve para medir nível.
O INMP441 não é analógico: é um microfone MEMS digital. Ele converte o som em números de 24 bits internamente e os envia por um barramento I2S, então o ruído nos fios não entra na medição. A principal vantagem é que o fabricante especifica a sensibilidade com uma tolerância estreita: um som de 94 dB SPL é lido como −26 dBFS. Assim, se você converter o valor RMS medido para dBFS e somar 120, obtém um valor aproximado de dB SPL. O I2S precisa de um ESP32 ou de um Pico; o Arduino Uno não tem hardware I2S. Módulos hobby com INMP441 são baratos e fáceis de achar, e o ICS-43434 e o SPH0645 são microfones I2S parecidos. Se você realmente precisa de uma medição de ruído precisa, o caminho mais fácil é um módulo pronto de nível sonoro com saída calibrada e ponderação A; por exemplo, multiplicando a tensão de saída do DFRobot SEN0232 por 50 você obtém direto o valor em dBA.
Ideias de projetos com sensor de som
- Lâmpada por palmas: acrescente um módulo relé ao sketch de duas palmas acima para controlar sua luminária de mesa ou uma fita de LED, e atribua três palmas a um segundo aparelho.
- Semáforo de barulho para a sala de aula: um indicador de ruído que acende LEDs verde, amarelo e vermelho conforme o valor de dB relativo; os professores adoram.
- Monitor de bebê e de pet: se o som continuar alto por mais de 5 segundos, faça o ESP32 mandar uma mensagem no Telegram para o seu celular.
- Luzes que reagem ao som: um anel ou uma fita NeoPixel que pulsa no ritmo da música.
- Detector de batidas na porta: um sistema que avisa com buzzer ou LED quando alguém bate na porta; para captar a batida como vibração em vez de som, o sensor de vibração SW-420 também é uma boa opção.
- Cenários de casa inteligente: combine o som com sensores de movimento e de luz para apagar as luzes quando não houver ninguém no cômodo; para ideias, veja Projeto de casa inteligente com Arduino.
Erros comuns e como resolver
| Sintoma | Causa provável | Solução |
|---|---|---|
| O LED do DO fica aceso o tempo todo | O limiar está sensível demais ou há ruído constante (uma ventoinha, uma geladeira) | Gire o potenciômetro em silêncio até o LED apagar e afaste o sensor da fonte de ruído |
| Nada acontece quando você bate palmas | O limiar está alto demais ou o DO está no pino errado | Primeiro confira se o LED da placa pisca com a palma; depois verifique o fio e o número do pino no código |
| O contador sobe em silêncio e para com som | A saída DO da placa é ativa em LOW | Defina SOUND_ACTIVE como LOW; no Pico, use IRQ_FALLING |
| O analogRead fica em torno de 500 e muda 1–2 com som | O AO não é amplificado e só são feitas leituras isoladas | Use o método pico a pico, aproxime o som ou troque por um MAX4466 |
| O AO fica sempre em 0 ou 1023 | AO e DO foram trocados ou o nível DC foi parar na borda | Confira a ligação e use o potenciômetro para trazer a média para o meio |
| Uma única palma é contada duas vezes | O cômodo tem eco ou o QUIET_GAP_MS está curto demais | Ajuste QUIET_GAP_MS para 150–200 ms e deixe o limiar um pouco menos sensível |
| A lâmpada liga e desliga sozinha | Clique do relé, portas batendo ou música | Aumente LOCKOUT_MS, afaste o sensor do relé e mantenha a regra das duas palmas |
| No ESP32, o AO para de ler quando o Wi-Fi está ligado | O AO está em um pino ADC2 | Passe o AO para um pino ADC1 entre GPIO 32 e 39 |
Com alguns fios e um código bem escrito, o KY-038 ensina vários fundamentos da eletrônica de uma vez: comparadores, conversão analógico-digital, interrupções, temporização e a matemática dos decibéis. Comece detectando palmas com o DO, meça o nível sonoro com o método pico a pico e passe para um MAX4466 ou INMP441 quando precisar de uma medição de som de verdade. No app BlueGrays você encontra projetos de lâmpada com relé, LED sequencial, iluminação inteligente com ESP32 e fita NeoPixel, com esquemas do circuito e código passo a passo; acrescentar um sensor de som a eles é o jeito mais fácil de transformá-los em sistemas que respondem a palmas ou ao som.
Perguntas frequentes
Como funciona um sensor de som para Arduino?
O sensor de som usa um comparador LM393 para comparar a pequena tensão do microfone de eletreto com um limiar definido pelo potenciômetro. Quando o som passa do limiar, o pino DO muda de estado e o LED da placa acende. O pino AO entrega o sinal bruto do microfone, sem amplificação, que você lê com analogRead().
Qual é a diferença entre o KY-038 e o KY-037?
Os dois usam o mesmo circuito com LM393 e a mesma ordem de pinos AO, G, +, DO, e o código é idêntico. O KY-037 tem uma cápsula de microfone maior e geralmente é um pouco mais sensível; o KY-038 é menor e mais comum nos kits de sensores.
Como ajustar a sensibilidade de um sensor de som?
Em silêncio, gire o potenciômetro azul até o ponto em que o LED do DO pisca e depois volte de meia volta a uma volta inteira para o lado em que o LED fica apagado. Como é um potenciômetro multivoltas, talvez você precise girar várias voltas antes de ver alguma mudança. Faça o ajuste sempre no lugar onde o sensor vai ser usado.
Um sensor de som consegue medir decibéis?
O KY-038 e o KY-037 não medem decibéis reais (dB SPL): o ganho da placa e a sensibilidade do microfone são desconhecidos, e não há calibração nem ponderação A. Só dá para calcular dB relativo em comparação com uma sala silenciosa. Para medições reais, use um microfone I2S com sensibilidade conhecida, como o INMP441, ou um módulo de nível sonoro calibrado.
Por que o valor analógico do meu sensor de som não muda?
A saída AO é o sinal do microfone sem amplificação e, com sons normais, é menor que um passo de 4,9 mV do ADC do Uno. Além disso, um único analogRead() lê um instante aleatório da onda sonora. Faça amostras durante 50 ms e calcule a diferença entre o maior e o menor valor (pico a pico): assim você vê a mudança com clareza.
O sensor de som funciona com o ESP32 e o Raspberry Pi Pico?
Sim, o módulo também funciona com 3,3 V; no ESP32 e no Pico, alimente-o pelo pino 3V3 para que a saída DO nunca passe de 3,3 V. No ESP32, ligue o AO em um pino ADC1 (GPIO 32–39), que não conflita com o Wi-Fi, e no Pico em GP26, GP27 ou GP28.
Projetos para montar depois desta leitura
Ver todos os projetos
Ligar e desligar um LED com botão
Pressione o botão uma vez para acender a luz e outra vez para apagar, como o interruptor do seu quarto. O Arduino detecta cada toque e inverte o estado do LED, aguardando um breve instante para que as

Controle de LED com botão no ESP32 (alternância)
Cada vez que o botão é pressionado, o estado do LED muda: se estiver aceso, apaga; se estiver apagado, acende. É o padrão clássico de alternância. Com debounce, eliminamos o ruído mecânico dos contatos do botão para garantir uma única mudança a cada pressionamento.

Sequencial de LEDs
Luzes que acendem uma após a outra, como se estivessem correndo. O Arduino acende seis LEDs, um de cada vez; cada um brilha por um instante e apaga, fazendo a luz percorrer a sequência do início ao fi

Ligar e desligar uma lâmpada de 220V com botão
Quer ligar e desligar uma lâmpada de casa com um pequeno botão? Ao pressionar o botão, o Arduino aciona um relé e a lâmpada acende; ao pressionar novamente, ela apaga. O relé funciona como intermediár

Raspberry Pi Pico: ligar e desligar LED com botão
Botão + LED — próximo nível! Ao contrário do projeto básico de botão, não é preciso manter o botão pressionado. Pressione e solte → LED aceso. De novo → LED apagado (alternância). O circuito é o mesmo (LED no GP14, botão no GP2), mas o código muda bastante. Aprenda detecção de borda (o instante da queda 1→0), rastreamento de estado e debounce (filtro de repique). led.toggle() alterna o estado em uma linha. Base para projetos interativos com botões (seletor de modo, IRQ, clique duplo).

Iluminação inteligente com ESP32 (PIR + LDR + relé + OLED)
Transforme a iluminação do corredor, banheiro ou despensa em iluminação inteligente com ESP32! Com um sensor de movimento PIR, um sensor de luz LDR e um módulo relé, montamos o cenário clássico de "acender a luz ao detectar movimento no escuro" — se o ambiente já estiver claro, o movimento NÃO aciona a luz, economizando energia durante o dia. A luz fica acesa por 30 segundos; se o movimento continuar, o temporizador reinicia e a luz permanece acesa por mais tempo.

Sensor de estacionamento com ESP32 (HC-SR04 + barra de 5 LEDs + buzzer + OLED)
A versão com ESP32 do sensor de estacionamento de carro! Usamos o sensor ultrassônico HC-SR04 para medir a distância até o objeto à sua frente. Conforme a distância diminui, a barra de 5 LEDs vai se preenchendo (verde → amarelo → vermelho) e o intervalo entre os bipes do buzzer diminui. Quando o objeto chega muito perto (menos de 10 cm), o alarme soa continuamente e todos os LEDs acendem.

Controle de fita WS2812B NeoPixel com ESP32
Os LEDs endereçáveis WS2812B (NeoPixel) são LEDs RGB inteligentes que podem ser controlados em cadeia por um único pino de dados. Neste projeto, vamos controlar uma fita WS2812B de 8 LEDs com a biblioteca Adafruit_NeoPixel para criar uma animação suave de arco-íris. Embora o nível lógico de 3,3V do ESP32 funcione sem problemas na maioria dos lotes de WS2812B, vamos mostrar uma solução com um resistor de 470Ω em série e um capacitor de 1.000µF para casos de instabilidade.
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

