Composants · 19 min de lecture

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.

Module capteur de son KY-038 (microphone électret et LM393)
Capteur de son KY-038 : à droite le microphone électret, au centre le comparateur LM393 et le potentiomètre bleu de sensibilité, à gauche les broches AO, G, + et DO.

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éristiqueValeur
MicrophoneCapsule électret à condensateur, omnidirectionnelle
ComparateurLM393 (double comparateur, un seul est utilisé)
Alimentation3,3–5 V
CourantQuelques mA (environ 5–10 mA avec les LED)
SortiesAO : signal brut du micro, DO : sortie à seuil
Réglage de sensibilitéTrimmer bleu multitour (généralement de type 3296)
LEDUne pour l'alimentation, une pour l'état de DO
Ordre des brochesAO, 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èleBrochesMicroRemarque
KY-038AO, G, +, DOPetite capsuleLe modèle le plus courant dans les kits de capteurs
KY-037AO, G, +, DOGrande capsuleMême circuit et même code ; généralement un peu plus sensible
Module sonore LM393 à 3 brochesVCC, GND, OUTPetite capsuleSortie numérique seulement ; OUT passe généralement à LOW avec le son

Branchement du capteur de son : Arduino Uno, ESP32 et Pico

Broche du moduleArduino UnoESP32Raspberry Pi Pico
+5V3V33V3(OUT), broche 36
GGNDGNDGND, broche 38
AOA0GPIO 34 (ADC1)GP26 (ADC0), broche 31
DOD2GPIO 27GP15, broche 20
Les broches de l'ESP32 et du Pico sont prévues pour 3,3 V. Sur ces cartes, alimente le capteur de son par la broche 3V3, pas par 5V, VIN ou VBUS ; sinon la sortie DO monte à 5 V et peut endommager la broche d'entrée. Sur l'ESP32, utilise pour AO une broche ADC1 (GPIO 32–39) : les broches ADC2 ne peuvent pas être lues avec analogRead() quand le Wi-Fi est actif.

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.

  1. 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.
  2. 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.
  3. Si la LED ne s'allume jamais, tourne dans l'autre sens pour trouver le point où elle commence à s'allumer.
  4. À 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.
  5. 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.
Le potentiomètre bleu de ces cartes est généralement un trimmer multitour de type 3296 qui demande environ 25 tours d'une butée à l'autre. Si tu le tournes plusieurs fois sans voir de changement sur la LED, il n'est pas cassé : il faut simplement continuer à tourner. En fin de course, la vis se met à patiner, inutile de forcer.
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}

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 :

SonNiveau approximatifSortie du micro (crête à crête)Pas du CAN sur l'Uno
Chuchotement30 dB SPL~0,01 mV0
Conversation normale (1 m)60 dB SPL~0,4 mV0 (invisible)
Télé forte, circulation80 dB SPL~3,6 mV0–1
Son très fort (1 Pa)94 dB SPL~18 mV3–4
Clap sec ou klaxon tout près110 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.

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}

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é.

  1. Relie la broche + du KY-038 au 5V, G au GND et DO à D2.
  2. 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.
  3. Téléverse le programme et ouvre le moniteur série à 9600 bauds.
  4. 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.
  5. Observe la lampe changer d'état environ 0,7 seconde après le deuxième clap.
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}
ConstanteValeurRôle
SOUND_ACTIVEHIGHNiveau que prend DO quand il y a du son ; mets LOW si ta carte est inversée
QUIET_GAP_MS120 msSilence nécessaire avant de compter un nouveau clap ; la rafale d'impulsions et l'écho d'un clap comptent pour un
CLAP_WINDOW_MS700 msAprès ce silence depuis le dernier son, la série est considérée comme terminée et les claps sont évalués
LOCKOUT_MS1000 msAprè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_OFFLOW / HIGHPour 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.

Commuter la tension secteur (230 V) avec un relais peut être mortel. Fais les branchements prise débranchée, ne laisse aucun bout de fil dénudé et place le circuit dans un boîtier isolant et fermé ; si tu n'es pas sûr de toi, essaie d'abord avec un ruban LED 12 V. Place aussi le capteur loin du relais : si le clic du relais est tout près du micro, il peut poser problème malgré le temps de blocage.

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.

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}

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.

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}

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().

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

Quand 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

ModuleSortieGainMesure en décibelsCartes compatibles
KY-038 / KY-037AO (brut) + DO (seuil)AucunNonToutes
MAX4466Analogique, centrée sur VCC/225 à 125 fois, réglableRelative seulementToutes
MAX9814Analogique, centrée sur 1,25 V, 2 Vcc max.40 / 50 / 60 dB + contrôle automatique de gain (AGC)Non, l'AGC comprime le niveauToutes
INMP441Numérique I2S, 24 bitsInutiledB SPL approximatifsESP32, Pico (pas l'Uno)
Module sonomètre prêt à l'emploi (ex. DFRobot SEN0232)Analogique, directement en dBAÉtalonné en usineOui, 30–130 dBA, ±1,5 dBToutes

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ômeCause probableSolution
La LED DO reste allumée en permanenceLe 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 mainsLe seuil est trop haut ou DO est sur la mauvaise brocheVé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 sonLa sortie DO de la carte est active à l'état basMets SOUND_ACTIVE à LOW ; sur le Pico, utilise IRQ_FALLING
analogRead reste vers 500 et bouge de 1–2 avec le sonAO n'est pas amplifiée et on ne fait que des lectures isoléesUtilise la méthode crête à crête, rapproche la source ou passe à un MAX4466
AO vaut toujours 0 ou 1023AO et DO sont inversés ou le niveau continu est parti en bord d'échelleVérifie le câblage et ramène la moyenne au milieu avec le potentiomètre
Un seul clap est compté deux foisLa pièce résonne ou QUIET_GAP_MS est trop courtPasse QUIET_GAP_MS à 150–200 ms et rends le seuil un peu moins sensible
La lampe s'allume et s'éteint toute seuleClic du relais, portes qui claquent ou musiqueAugmente 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 actifAO est sur une broche ADC2Déplace AO sur une broche ADC1 entre GPIO 32 et 39
Un moyen pratique de tester le capteur de son est une application de générateur de tonalité sur ton téléphone. Joue une tonalité stable de 1 kHz et tiens le téléphone à 10, 20 puis 40 cm du micro : en champ libre, chaque fois que la distance double, la pression acoustique est divisée par deux, donc p2p doit tomber à peu près de moitié et la valeur en dB baisser d'environ 6 dB. Cette expérience simple vérifie à la fois ton câblage et ton code.

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.

Voir tous les projets
Allumer et éteindre une LED avec un bouton
#10Débutant

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

4.8(100)
162
ESP32 Contrôle de LED avec bouton (Toggle)
#105Débutant

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.

4.6(39)
57
Chenillard à LED
#5Intermédiaire

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

4.6(85)
201
Allumer et éteindre une ampoule 220 V avec un bouton
#20Avancé
Premium

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

4.5(33)
44
Raspberry Pi Pico Bouton Toggle LED (GP14 + GP2)
#156Débutant
Premium

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.

0.0(0)
9
Éclairage Intelligent ESP32 (PIR + LDR + Relais + OLED)
#141Avancé
Premium

É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

4.3(6)
11
Capteur de stationnement ESP32 (HC-SR04 + barre à 5 LED + buzzer + écran OLED)
#142Avancé
Premium

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

0.0(0)
14
Contrôle d'une bande NeoPixel WS2812B avec l'ESP32
#126Intermédiaire
Premium

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

4.9(19)
30