Capteur de son Arduino KY-038 : lampe au clap et niveau sonore
Comment fonctionne le capteur de son KY-038/KY-037 avec Arduino ? Réglage du potentiomètre, niveau crête à crête, lampe à double clap, vumètre LED, ESP32, Pico.
Quand on parle de capteur de son Arduino, il s'agit presque toujours du KY-038 : un module bon marché qui réunit sur une même carte un petit microphone électret, un comparateur LM393 et un potentiomètre bleu pour régler la sensibilité. Son grand frère à gros micro, le KY-037, fonctionne de la même façon. Aucune bibliothèque n'est nécessaire : la broche DO change d'état quand le son dépasse un seuil et se lit avec digitalRead(), tandis que la broche AO fournit le signal brut du micro et se lit avec analogRead(). Lampes qui s'allument quand on tape dans les mains, alarmes de bruit et lumières qui réagissent à la musique se construisent avec ce module.
Ce capteur a pourtant une limite importante que beaucoup de tutoriels passent sous silence : le KY-038 est un détecteur son ou pas de son. Il n'enregistre pas, ne reconnaît pas la voix et ne peut pas mesurer de décibels. Dans cet article, tu vas apprendre comment fonctionne le circuit du module, comment bien régler le potentiomètre, pourquoi la lecture analogique semble souvent ne pas bouger du tout et comment mesurer correctement l'intensité du son avec la méthode crête à crête. Tu construiras ensuite une lampe qui s'allume et s'éteint quand tu tapes deux fois dans tes mains et un indicateur de niveau à 8 LED, tu feras la même chose avec un ESP32 et un Raspberry Pi Pico, et tu verras vers quels modules passer quand tu as besoin d'une vraie mesure du son.

Qu'est-ce qu'un capteur de son et comment fonctionne-t-il ?
Le cylindre argenté au bout de la carte est un microphone électret à condensateur. À l'intérieur, une fine membrane fait face à une plaque qui porte une charge électrique permanente, et l'ensemble forme un minuscule condensateur. Le son est une variation de pression dans l'air ; en faisant bouger la membrane d'avant en arrière, elle modifie la capacité et crée une très petite variation de tension. Un minuscule JFET dans la capsule sert de tampon à ce signal : c'est pourquoi un micro électret s'alimente à travers une résistance et possède une polarité. Au final, on obtient sur le micro une onde sonore de seulement quelques millivolts, posée sur une tension continue fixe.
La puce LM393 à 8 broches au centre de la carte contient deux comparateurs, et le module en utilise un. Un comparateur regarde deux tensions : le signal du micro et le seuil fixé par le potentiomètre. Dès que le signal franchit le seuil, la sortie bascule et la broche DO ainsi que la deuxième LED de la carte réagissent. Un détail très important : un comparateur n'est pas un amplificateur. Il ne grossit pas le signal, il répond seulement à la question « au-dessus ou en dessous du seuil ? ». La broche AO reçoit le signal brut, non amplifié, du micro, et c'est pour cela que la lecture analogique est si faible.
| Caractéristique | Valeur |
|---|---|
| Microphone | Capsule électret à condensateur, omnidirectionnelle |
| Comparateur | LM393 (double comparateur, un seul est utilisé) |
| Alimentation | 3,3–5 V |
| Courant | Quelques mA (environ 5–10 mA avec les LED) |
| Sorties | AO : signal brut du micro, DO : sortie à seuil |
| Réglage de sensibilité | Trimmer bleu multitour (généralement de type 3296) |
| LED | Une pour l'alimentation, une pour l'état de DO |
| Ordre des broches | AO, G, +, DO |
Différence entre KY-038 et KY-037
Le KY-038 et le KY-037 utilisent le même circuit, le même LM393 et le même ordre de broches : tous les programmes de cet article fonctionnent sur les deux sans modification. La différence vient de la capsule du micro : le KY-037 porte une capsule plus grande et est vendu comme « capteur de son haute sensibilité », tandis que le KY-038 a une capsule plus petite et c'est le modèle que tu trouveras le plus souvent dans les kits de capteurs. En pratique, les deux détectent bien les sons forts proches, mais aucun n'entend une conversation à l'autre bout de la pièce. Il existe aussi des modules sonores LM393 à 3 broches avec une seule sortie numérique ; sur la plupart, la sortie passe à LOW quand il y a du son.
| Modèle | Broches | Micro | Remarque |
|---|---|---|---|
| KY-038 | AO, G, +, DO | Petite capsule | Le modèle le plus courant dans les kits de capteurs |
| KY-037 | AO, G, +, DO | Grande capsule | Même circuit et même code ; généralement un peu plus sensible |
| Module sonore LM393 à 3 broches | VCC, GND, OUT | Petite capsule | Sortie numérique seulement ; OUT passe généralement à LOW avec le son |
Branchement du capteur de son : Arduino Uno, ESP32 et Pico
| Broche du module | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| + | 5V | 3V3 | 3V3(OUT), broche 36 |
| G | GND | GND | GND, broche 38 |
| AO | A0 | GPIO 34 (ADC1) | GP26 (ADC0), broche 31 |
| DO | D2 | GPIO 27 | GP15, broche 20 |
Sortie numérique (DO) et réglage du potentiomètre
La broche DO donne une réponse oui/non. Sur beaucoup de cartes KY-038, DO passe à HIGH et la deuxième LED s'allume quand le son dépasse le seuil ; sur certains clones et sur les modules à 3 broches, c'est exactement l'inverse. C'est pourquoi les programmes gardent le niveau qui signifie « son » dans une constante appelée SOUND_ACTIVE. Deuxième point clé : DO ne donne pas une seule longue impulsion par clap. Comme l'onde sonore passe au-dessus et en dessous du seuil des centaines de fois par seconde, la sortie s'allume et s'éteint tout aussi vite ; un seul clap produit une rafale d'impulsions courtes qui dure quelques dizaines de millisecondes. La plupart des cartes n'ont pas d'hystérésis sur le comparateur, donc avec des sons proches du seuil la sortie oscille en plus. Lis donc DO avec une boucle rapide sans delay() ou avec une interruption, et compte comme un seul événement les impulsions très rapprochées.
- Branche le module et place le capteur là où il servira, à un moment où règne le bruit ambiant habituel ; fais toujours le réglage dans l'environnement réel.
- Observe la LED DO sur la carte. Si elle reste allumée dans le silence, le seuil est trop sensible ; tourne le potentiomètre avec un petit tournevis jusqu'à ce que la LED s'éteigne.
- Si la LED ne s'allume jamais, tourne dans l'autre sens pour trouver le point où elle commence à s'allumer.
- À partir de ce point, reviens d'un demi-tour à un tour vers le côté où la LED reste éteinte. Ainsi, les bruits continus comme un réfrigérateur ou un ventilateur ne la déclencheront pas.
- Tape dans tes mains à environ un mètre : la LED doit clignoter brièvement. Si elle s'allume aussi quand tu parles normalement, tourne un peu vers moins sensible ; si elle ne s'allume pas avec un clap, un peu vers plus sensible.
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}Le programme lit la broche DO à chaque tour de boucle, sans delay(). Chaque fois que DO est actif, le temps lastSound est mis à jour ; un nouvel événement n'est compté qu'après 200 ms de silence, si bien que la rafale d'impulsions d'un clap apparaît sur une seule ligne dans le moniteur série. La LED intégrée reste aussi allumée au moins 200 ms, sinon tu ne pourrais pas voir à l'œil nu des impulsions d'une milliseconde. Si le compteur augmente sans arrêt dans le silence, soit le seuil est trop sensible, soit la sortie DO de ta carte est inversée ; dans le second cas, mets SOUND_ACTIVE à LOW.
Pourquoi la lecture analogique (AO) est-elle si faible ?
La plupart des débutants branchent AO sur A0, affichent la valeur de analogRead() et voient un nombre autour de 500 qui bouge à peine avec le son. Le capteur n'est pas en panne : le problème, c'est l'échelle. Le CAN 10 bits de l'Arduino Uno découpe 0–5 V en 1024 pas, donc un pas vaut environ 4,9 mV. Avec des sons normaux, le signal produit par le micro est bien plus petit que ce pas :
| Son | Niveau approximatif | Sortie du micro (crête à crête) | Pas du CAN sur l'Uno |
|---|---|---|---|
| Chuchotement | 30 dB SPL | ~0,01 mV | 0 |
| Conversation normale (1 m) | 60 dB SPL | ~0,4 mV | 0 (invisible) |
| Télé forte, circulation | 80 dB SPL | ~3,6 mV | 0–1 |
| Son très fort (1 Pa) | 94 dB SPL | ~18 mV | 3–4 |
| Clap sec ou klaxon tout près | 110 dB SPL | ~110 mV | ~23 |
Le tableau a été calculé avec −44 dBV/Pa, la sensibilité d'une capsule électret typique, en supposant un son sinusoïdal. Selon la résistance de polarisation du micro sur ta carte, les valeurs réelles peuvent être plusieurs fois plus grandes, mais la conclusion reste la même : AO ne voit nettement que les sons forts et proches, alors que la conversation normale et le chuchotement restent sous la résolution de l'Uno. Tu trouveras plus de détails sur le fonctionnement du CAN dans Qu'est-ce qu'un CAN (ADC) ?.
La deuxième raison tient à la nature du son. Le son est une onde qui oscille de haut en bas autour d'un niveau continu. Un seul analogRead() capture un instant aléatoire de cette onde : il peut tomber sur une crête, un creux ou pile au milieu. La taille d'une seule mesure ne dit donc rien sur l'intensité du son. La troisième raison, c'est la vitesse : l'Uno met environ 100 microsecondes par lecture analogique, il prend donc au maximum environ 10 000 échantillons par seconde. C'est suffisant pour suivre le niveau sonore, mais pas pour enregistrer du son ni analyser des fréquences. Enfin, le bruit de l'alimentation 5 V venant de l'USB se retrouve directement sur AO. Tu peux régler les deux premiers problèmes avec la bonne méthode de mesure.
Mesurer l'amplitude crête à crête : lire correctement l'intensité du son
La bonne méthode consiste à prendre autant d'échantillons que possible pendant une courte fenêtre de temps et à chercher la valeur la plus haute et la plus basse. Leur différence est l'amplitude crête à crête (peak-to-peak) et elle indique la force du son quel que soit le niveau continu. 50 ms est une bonne fenêtre : une période de 20 Hz, la fréquence la plus basse que l'oreille humaine entend, dure exactement 50 ms, donc même le son le plus grave y fait tenir une onde complète. L'Uno prend environ 450–500 échantillons pendant ce temps.
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}Après avoir téléversé le programme, ouvre le traceur série depuis le menu Outils et règle la vitesse sur 115200. Dans une pièce calme, p2p reste en général entre 0 et 3 ; il monte de quelques unités quand tu parles à côté du micro et de plusieurs dizaines quand tu tapes dans tes mains tout près. La valeur ortalama_avg est le niveau continu de AO et, comme elle étire l'échelle du graphique, tu peux supprimer les deux lignes ortalama_avg si tu veux suivre p2p confortablement. Sur certaines cartes, le potentiomètre décale aussi ce niveau ; si la moyenne reste collée à 0 ou à 1023, le signal est écrêté : tourne le potentiomètre jusqu'à ce que la valeur revienne vers le milieu. Si tu utilises le traceur série pour la première fois, jette un œil à Moniteur série Arduino.
Pas à pas : allumer et éteindre une lampe en tapant deux fois dans les mains
La lampe qui s'allume quand on tape dans les mains est le projet le plus connu avec un capteur de son, mais un circuit qui réagit à un seul clap se déclenche aussi avec une porte qui claque, un livre qui tombe ou une toux, et la lampe n'arrête pas de s'allumer et de s'éteindre. La solution est de chercher un rythme : le programme ci-dessous ne réagit qu'à exactement deux claps espacés de 0,12 à 0,7 seconde. Un son isolé, ou trois sons et plus (musique, applaudissements, chien qui aboie), est ignoré.
- Relie la broche + du KY-038 au 5V, G au GND et DO à D2.
- Relie la broche VCC du module relais au 5V, GND au GND et IN à D7. Tu trouveras comment fonctionne un relais et comment câbler le côté charge dans Qu'est-ce qu'un module relais ? ; fais les premiers essais avec la LED du relais plutôt qu'avec une lampe.
- Téléverse le programme et ouvre le moniteur série à 9600 bauds.
- Tape deux fois dans tes mains à un ou deux mètres du capteur. Tu dois voir une seule ligne « Alkis / Clap » par clap ; si un clap est compté plusieurs fois, tourne le potentiomètre un peu vers moins sensible.
- Observe la lampe changer d'état environ 0,7 seconde après le deuxième clap.
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 | Valeur | Rôle |
|---|---|---|
| SOUND_ACTIVE | HIGH | Niveau que prend DO quand il y a du son ; mets LOW si ta carte est inversée |
| QUIET_GAP_MS | 120 ms | Silence nécessaire avant de compter un nouveau clap ; la rafale d'impulsions et l'écho d'un clap comptent pour un |
| CLAP_WINDOW_MS | 700 ms | Après ce silence depuis le dernier son, la série est considérée comme terminée et les claps sont évalués |
| LOCKOUT_MS | 1000 ms | Après le changement de la lampe, les sons sont ignorés pour que le clic du relais ne passe pas pour un clap |
| RELAY_ON / RELAY_OFF | LOW / HIGH | Pour un module relais actif à l'état bas ; inverse-les sur un module actif à l'état haut |
Le programme n'utilise pas delay() : il mesure tout avec millis(), si bien qu'aucun clap n'est manqué. Nous expliquons cette approche en détail dans millis ou delay. Le fait que la lampe change 0,7 seconde après le deuxième clap, et pas tout de suite, est voulu : le programme attend de voir si un troisième clap arrive. Si tu veux une réaction plus rapide, tu peux baisser CLAP_WINDOW_MS à 400–500 ms, mais il faudra alors enchaîner tes deux claps plus vite. Si ta pièce résonne beaucoup et qu'un seul clap est compté deux fois, monte QUIET_GAP_MS à 150–200 ms.
Indicateur de niveau sonore : un vumètre à 8 LED
Envoyer directement la valeur crête à crête aux LED fonctionne, mais le résultat ne paraît pas naturel, car notre oreille perçoit le son de façon logarithmique : un son d'amplitude double ne nous semble pas deux fois plus fort. C'est pour cela qu'on mesure le son en décibels (dB). Pour une amplitude, la formule est dB = 20 × log10(p2p / référence) ; une amplitude doublée fait +6 dB, une amplitude multipliée par dix +20 dB. Le programme ci-dessous mesure pendant une seconde, au démarrage, le bruit de fond de la pièce et le prend comme référence ; chaque LED représente 3 dB au-dessus de ce fond. Branche les LED sur D3–D10, chacune avec une résistance de 220 Ω ; pour des LED d'autres couleurs, tu trouveras la bonne résistance avec le calculateur de résistance de 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}Pense à rester silencieux une seconde au démarrage ; si tu parles à ce moment-là, le fond est mesuré trop haut et l'indicateur réagit moins. L'indicateur monte instantanément mais redescend lentement, une LED toutes les 80 ms ; c'est aussi pour cela que les vrais vumètres paraissent fluides et non nerveux. Comme le signal analogique du KY-038 est faible, 2–3 dB par LED conviennent ; si tu utilises le même programme avec un micro amplifié comme le MAX4466, tu peux monter DB_PER_LED à 4–6 dB. Pour un affichage en couleurs, tu peux remplacer les LED par un anneau NeoPixel ; les détails sont dans LED NeoPixel WS2812B.
Capteur de son avec l'ESP32 : détecter les claps par interruption
Le CAN de l'ESP32 est sur 12 bits et donne des valeurs de 0 à 4095 ; sur une plage de 3,3 V, un pas vaut environ 0,8 mV, soit une résolution environ 6 fois plus fine que l'Uno. En revanche, le CAN de l'ESP32 est plus bruité, si bien que la valeur p2p dans une pièce calme est aussi plus élevée ; le calcul en dB relatifs compense cette différence tout seul. Dans le programme ci-dessous, la broche DO est reliée à une interruption : aucune impulsion de clap n'est perdue, même pendant que loop() mesure le niveau sonore sur AO pendant 50 ms. La fonction d'interruption est placée en RAM avec IRAM_ATTR et reste courte ; les variables utilisées à la fois par l'interruption et par loop() sont déclarées volatile et protégées par une section critique.
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}Le programme exécute la même logique de double clap que sur l'Uno, mais dans l'interruption, et affiche le niveau sonore en dB environ toutes les 50 ms. Relie la broche IN du module relais au GPIO 26 ; certains modules relais actifs à l'état bas alimentés en 5 V ne retombent pas complètement avec le niveau HIGH de 3,3 V de l'ESP32 : choisis alors un module pilotable en 3,3 V. Le vrai atout de l'ESP32, c'est le Wi-Fi : si le niveau sonore reste au-dessus d'un seuil pendant quelques secondes (un bébé qui pleure ou un chien qui aboie, par exemple), tu peux envoyer une notification sur ton téléphone. Utilise pour cela la méthode de bot Telegram avec ESP32 et, pour le relier à un système domotique, ESP32 avec MQTT et Home Assistant.
Capteur de son avec le Raspberry Pi Pico et MicroPython
Sur le Raspberry Pi Pico, alimente le module par la broche 3V3(OUT), relie AO à GP26 et DO à GP15 et, à la place d'une lampe, mets une LED avec une résistance de 220 Ω sur GP14. Le CAN du Pico est sur 12 bits, mais en MicroPython read_u16() ramène la valeur sur 0–65535 ; c'est pourquoi les nombres p2p paraissent bien plus grands que sur l'Uno, alors que le calcul en dB relatifs reste le même. Une interruption est définie sur la broche DO avec 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 = 0Quand tu lances le code dans Thonny, tu vois les valeurs p2p et dB dans la console (Shell) ; ouvre le traceur (Plotter) depuis le menu Affichage pour les suivre sous forme de graphique. Si la sortie DO de ta carte passe à LOW avec le son, écris IRQ_FALLING au lieu de IRQ_RISING. Pour que le programme démarre tout seul à la mise sous tension du Pico, enregistre le fichier sur le Pico sous le nom main.py. Si tu découvres MicroPython, les bases de MicroPython sont un bon point de départ.
Un capteur de son peut-il mesurer des décibels ?
Réponse courte : non. Sur internet, tu trouveras beaucoup de programmes qui convertissent avec map() la valeur crête à crête du KY-038 en une plage comme 49–90 dB ; ce sont des estimations, pas des mesures. Pour mesurer un vrai niveau de pression acoustique (dB SPL), il faut un micro dont la sensibilité est connue et un système étalonné avec un calibreur de 94 dB, une amplification linéaire du signal, une valeur efficace (RMS) calculée sur une durée fixe (125 ms en mode rapide, 1 s en mode lent) et un filtre de pondération A qui imite la sensibilité de l'oreille. C'est pour cela que les sonomètres sont construits selon la norme IEC 61672.
Le KY-038 ne remplit aucune de ces conditions : le gain de la carte est inconnu, la sensibilité des capsules varie de quelques dB d'un exemplaire à l'autre, le potentiomètre et la tension d'alimentation modifient le niveau du signal, et sur l'Uno tous les sons normaux sont tassés sur quelques pas du CAN. Le plus honnête est de faire une mesure relative : dire « en ce moment, c'est 12 dB plus bruyant que la pièce au calme ». Même cela suffit largement pour une alarme de bruit, un feu tricolore anti-bruit en classe ou un vumètre. Tu peux faire un étalonnage grossier en comparant avec une application de téléphone en un point, mais cet étalonnage ne vaut plus à d'autres niveaux sonores ni sur une autre carte.
Alternatives : MAX4466, MAX9814 et INMP441
| Module | Sortie | Gain | Mesure en décibels | Cartes compatibles |
|---|---|---|---|---|
| KY-038 / KY-037 | AO (brut) + DO (seuil) | Aucun | Non | Toutes |
| MAX4466 | Analogique, centrée sur VCC/2 | 25 à 125 fois, réglable | Relative seulement | Toutes |
| MAX9814 | Analogique, centrée sur 1,25 V, 2 Vcc max. | 40 / 50 / 60 dB + contrôle automatique de gain (AGC) | Non, l'AGC comprime le niveau | Toutes |
| INMP441 | Numérique I2S, 24 bits | Inutile | dB SPL approximatifs | ESP32, Pico (pas l'Uno) |
| Module sonomètre prêt à l'emploi (ex. DFRobot SEN0232) | Analogique, directement en dBA | Étalonné en usine | Oui, 30–130 dBA, ±1,5 dB | Toutes |
Le MAX4466 associe le même type de micro électret à un amplificateur opérationnel à gain réglable. Sa sortie se place à la moitié de la tension d'alimentation dans le silence et fournit un signal de plusieurs centaines de millivolts avec une conversation normale à proximité ; autrement dit, le signal de quelques pas de CAN du KY-038 passe à des dizaines, voire des centaines de pas. Les programmes crête à crête et vumètre de cet article fonctionnent avec le MAX4466 sans aucune modification. Pour savoir comment se calcule le gain, consulte le calculateur de gain d'ampli-op et Qu'est-ce qu'un amplificateur opérationnel ?. Alimenter le module par la broche 3.3V de l'Uno, plus propre, réduit le bruit. Le MAX9814, lui, ramène même une voix lointaine à un niveau exploitable grâce à son contrôle automatique de gain ; il est excellent pour l'enregistrement et la détection de voix, mais il ne convient pas à la mesure de niveau, car il rapproche les ambiances calmes et bruyantes.
L'INMP441 n'est même pas analogique : c'est un micro MEMS numérique qui convertit le son en nombres de 24 bits en interne et les envoie sur un bus I2S, si bien que le bruit des fils n'entre pas dans la mesure. Son principal avantage est que le fabricant indique sa sensibilité avec une tolérance serrée : un son de 94 dB SPL se lit −26 dBFS. Si tu convertis en dBFS la valeur efficace mesurée et que tu ajoutes 120, tu obtiens donc une valeur approximative en dB SPL. L'I2S demande un ESP32 ou un Pico ; l'Arduino Uno n'a pas de matériel I2S. Les modules INMP441 pour amateurs sont bon marché et faciles à trouver, et l'ICS-43434 et le SPH0645 sont des micros I2S similaires. Si tu as vraiment besoin d'une mesure de bruit précise, le plus simple est un module sonomètre prêt à l'emploi avec une sortie étalonnée et pondérée A ; par exemple, en multipliant par 50 la tension de sortie du DFRobot SEN0232, tu obtiens directement la valeur en dBA.
Idées de projets avec un capteur de son
- Lampe à clap : Ajoute un module relais au programme de double clap ci-dessus pour commander ta lampe de bureau ou un ruban LED, et attribue trois claps à un deuxième appareil.
- Feu tricolore anti-bruit en classe : Un indicateur qui allume des LED verte, jaune et rouge selon la valeur relative en dB ; les enseignants l'adorent.
- Babyphone et alerte animaux : Si le son reste fort plus de 5 secondes, l'ESP32 envoie un message Telegram sur ton téléphone.
- Lumières réactives au son : Un anneau ou un ruban NeoPixel qui pulse au rythme de la musique.
- Détecteur de coups à la porte : Un montage qui te prévient avec un buzzer ou une LED quand on frappe ; pour capter le coup comme une vibration plutôt qu'un son, le capteur de vibration SW-420 est aussi un bon choix.
- Scénarios de maison connectée : Combine le son avec des capteurs de mouvement et de lumière pour éteindre les lumières quand personne n'est dans la pièce ; pour des idées, regarde le projet de maison connectée Arduino.
Erreurs fréquentes et solutions
| Symptôme | Cause probable | Solution |
|---|---|---|
| La LED DO reste allumée en permanence | Le seuil est trop sensible ou il y a un bruit continu (ventilateur, réfrigérateur) | Tourne le potentiomètre dans le silence jusqu'à ce que la LED s'éteigne et éloigne le capteur de la source de bruit |
| Rien ne se passe quand tu tapes dans tes mains | Le seuil est trop haut ou DO est sur la mauvaise broche | Vérifie d'abord que la LED de la carte clignote au clap, puis contrôle le fil et le numéro de broche dans le code |
| Le compteur monte dans le silence et s'arrête avec le son | La sortie DO de la carte est active à l'état bas | Mets SOUND_ACTIVE à LOW ; sur le Pico, utilise IRQ_FALLING |
| analogRead reste vers 500 et bouge de 1–2 avec le son | AO n'est pas amplifiée et on ne fait que des lectures isolées | Utilise la méthode crête à crête, rapproche la source ou passe à un MAX4466 |
| AO vaut toujours 0 ou 1023 | AO et DO sont inversés ou le niveau continu est parti en bord d'échelle | Vérifie le câblage et ramène la moyenne au milieu avec le potentiomètre |
| Un seul clap est compté deux fois | La pièce résonne ou QUIET_GAP_MS est trop court | Passe QUIET_GAP_MS à 150–200 ms et rends le seuil un peu moins sensible |
| La lampe s'allume et s'éteint toute seule | Clic du relais, portes qui claquent ou musique | Augmente LOCKOUT_MS, éloigne le capteur du relais et garde la règle du double clap |
| Sur l'ESP32, AO ne lit plus rien dès que le Wi-Fi est actif | AO est sur une broche ADC2 | Déplace AO sur une broche ADC1 entre GPIO 32 et 39 |
Avec quelques fils et un code bien écrit, le KY-038 enseigne d'un coup de nombreuses bases de l'électronique : comparateurs, conversion analogique-numérique, interruptions, gestion du temps et calcul en décibels. Commence par détecter les claps avec DO, mesure le niveau sonore avec la méthode crête à crête et passe à un MAX4466 ou à un INMP441 quand tu as besoin d'une vraie mesure du son. Dans l'application BlueGrays, tu trouveras des projets de lampe avec relais, de chenillard à LED, d'éclairage intelligent avec ESP32 et de ruban NeoPixel, avec schémas de câblage et code pas à pas ; y ajouter un capteur de son est le moyen le plus simple de les transformer en systèmes qui réagissent aux claps ou au bruit.
Questions fréquentes
Comment fonctionne un capteur de son Arduino ?
Le capteur de son compare, grâce à un comparateur LM393, la petite tension de son micro électret à un seuil fixé par le potentiomètre. Quand le son dépasse le seuil, la broche DO change d'état et la LED de la carte s'allume. La broche AO fournit le signal brut, non amplifié, du micro, que l'on lit avec analogRead().
Quelle est la différence entre le KY-038 et le KY-037 ?
Les deux utilisent le même circuit LM393 et le même ordre de broches AO, G, +, DO, et le code est identique. Le KY-037 porte une capsule de micro plus grande et est généralement un peu plus sensible ; le KY-038 est plus petit et plus courant dans les kits de capteurs.
Comment régler la sensibilité d'un capteur de son ?
Dans le silence, tourne le potentiomètre bleu jusqu'au point où la LED DO clignote, puis reviens d'un demi-tour à un tour vers le côté où la LED reste éteinte. Comme c'est un potentiomètre multitour, il faut parfois plusieurs tours avant de voir un changement. Fais toujours le réglage à l'endroit où le capteur sera utilisé.
Peut-on mesurer des décibels avec un capteur de son ?
Le KY-038 et le KY-037 ne peuvent pas mesurer de vrais décibels (dB SPL) : le gain de la carte et la sensibilité du micro sont inconnus, et il n'y a ni étalonnage ni pondération A. On peut seulement calculer des dB relatifs par rapport à une pièce calme. Pour une vraie mesure, utilise un micro I2S de sensibilité connue comme l'INMP441 ou un module sonomètre étalonné.
Pourquoi la valeur analogique de mon capteur de son ne change-t-elle pas ?
La sortie AO est le signal du micro non amplifié et, avec des sons normaux, elle est plus petite qu'un pas de 4,9 mV du CAN de l'Uno. De plus, un seul analogRead() lit un instant aléatoire de l'onde sonore. Échantillonne pendant 50 ms et calcule l'écart entre la valeur la plus haute et la plus basse (crête à crête) : tu verras nettement la variation.
Le capteur de son fonctionne-t-il avec l'ESP32 et le Raspberry Pi Pico ?
Oui, le module fonctionne aussi en 3,3 V ; sur l'ESP32 et le Pico, alimente-le par la broche 3V3 pour que la sortie DO ne dépasse jamais 3,3 V. Sur l'ESP32, relie AO à une broche ADC1 (GPIO 32–39), qui n'entre pas en conflit avec le Wi-Fi, et sur le Pico à GP26, GP27 ou GP28.
Projets à réaliser après cet article
Voir tous les projets
Allumer et éteindre une LED avec un bouton
Un appui et la lumière s'allume, un deuxième et elle s'éteint, exactement comme l'interrupteur de ta chambre. L'Arduino remarque chaque appui et fait passer la LED à l'état inverse, en attendant un co

ESP32 Contrôle de LED avec bouton (Toggle)
Chaque fois que l'on appuie sur le bouton, la LED change d'état : si elle est allumée, elle s'éteint, si elle est éteinte, elle s'allume. Modèle classique de basculement. Avec le debounce, nous nettoyons le bruit mécanique du bouton-poussoir pour garantir un seul basculement avec une seule pression.

Chenillard à LED
Des lumières qui s'allument l'une après l'autre, comme si elles couraient. L'Arduino allume six LED une par une ; chacune brille un court instant puis s'éteint, et la lumière parcourt la rangée du déb

Allumer et éteindre une ampoule 220 V avec un bouton
Envie d'allumer et d'éteindre une vraie ampoule de la maison avec un petit bouton ? À chaque appui, l'Arduino bascule un relais et l'ampoule s'allume ; un nouvel appui l'éteint. Le relais est un inter

Raspberry Pi Pico Bouton Toggle LED (GP14 + GP2)
Bouton + LED — niveau supérieur ! 🔁 Contrairement à #155, pas besoin de maintenir le bouton. Appuie et relâche → LED allumée. Réappuie → LED éteinte (toggle). Même circuit que #155, mais grande différence de code. Apprends edge detection, state tracking et debounce.

Éclairage Intelligent ESP32 (PIR + LDR + Relais + OLED)
Transformez votre couloir, votre salle de bain ou votre garde-manger en éclairage intelligent avec l'ESP32 ! En utilisant un capteur de mouvement PIR, un capteur de lumière LDR et un module relais, nous construisons le scénario classique "la lumière s'allume lorsqu'un mouvement est détecté dans l'obscurité" — si l'environnement est déjà lumineux, le mouvement N'ACTIVE PAS la lumière, économisant ainsi de l'énergie pendant la journée. La lumière reste allumée pendant 30 secondes ; si le mouvement

Capteur de stationnement ESP32 (HC-SR04 + barre à 5 LED + buzzer + écran OLED)
La version ESP32 du capteur de stationnement pour voiture ! Grâce au capteur à ultrasons HC-SR04, nous mesurons la distance par rapport à l'objet situé devant. À mesure que la distance diminue, la barre composée de 5 LED se remplit (vert → jaune → rouge) et l'intervalle entre les bips du buzzer se raccourcit. Lorsque l'objet est très proche (moins de 10 cm), l'alarme retentit en continu et toutes les LED s'allument. L'écran OLED SSD1306 affiche en gros caractères la valeur instantanée en cm, un

Contrôle d'une bande NeoPixel WS2812B avec l'ESP32
Les LED adressables WS2812B (NeoPixel) sont des LED RGB intelligentes pouvant être contrôlées en série via une seule broche de données. Dans ce projet, nous allons contrôler une bande WS2812B de 8 LED à l'aide de la bibliothèque Adafruit_NeoPixel afin de créer une animation fluide représentant un arc-en-ciel. Bien que le niveau logique 3,3 V de l'ESP32 fonctionne sans problème avec la plupart des composants WS2812B, nous présenterons une solution comprenant une résistance en série de 470 Ω et un
Autres articles
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 160 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

