Here is a "stripped down version" of a sketch I used to replicate the Clap On, Clap Off lamp switch we had in the 1980's. It works with the KY-038 sound sensor module you currently have. You will need to install the VirtualDelay Library.
The sound sensor module is very sensitive. A quarter turn of the potentiometer around the "sweet spot" makes a huge difference. Too sensitive, and the digital output is constantly high. If it's not sensitive enough, then you have to physically "tap" the microphone to get a high/low transition out of it.
Please note: This sketch uses delay() which is "blocking code" and it's use is usually not recommended.
#include "avdweb_VirtualDelay.h"
byte clapCounter = 0;
const byte soundSensorPin = 2;
const unsigned long loopDelay = 1;
const unsigned long clapCounterDelay = 400;
unsigned long clapCounterTimerDuration = 1000;
unsigned long previousMillis = 0;
void setup(){
pinMode(LED_BUILTIN, OUTPUT);
}
void loop(){
// Timer object.
static VirtualDelay clapCounterTimer;
// Get the current time.
unsigned long currentMillis = millis();
// Check for a clapping sound (1 ms works good). If too much time
// elapses here, you could miss the "beginning" of the clap.
if(myTimer1(loopDelay, currentMillis) == 1){
// Clap detected.
if(digitalRead(soundSensorPin) == 1){
clapCounter += 1;
// When the first the clap is detected, start a timer
// to reset the clap counter to 0 after 1 second.
if(clapCounter == 1){
clapCounterTimer.start(clapCounterTimerDuration);
}
// Delay execution of the loop. 400 ms works good.
delay(clapCounterDelay);
// If a second clap is detected, toggle the LED ON/OFF.
if(clapCounter > 1){
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
}
// Reset the clap counter to 0 after 1 second. If
// you don't do this, you could clap once, wait a
// minute, then clap again and the LED will change state.
if(clapCounterTimer.elapsed()){
clapCounter = 0;
}
}
// Clap loop timer.
byte myTimer1(unsigned long loopDelay, unsigned long currentMillis){
if(currentMillis - previousMillis >= loopDelay){previousMillis += loopDelay;return 1;}
else{return 0;}
}
EDIT: To answer your question regarding the multiple High to Low transitions from the module's digital output, you can use a DSO to look at the relationship between the analog and digital signals it produces.
In the following image, the digital signal (yellow trace) and the analog signal (blue trace) are superimposed over each other. The white dashed line (E), is set to 2.8 VDC which is approximately the analog output pin's voltage with ambient room noise. Once you clap in front of the microphone, this wave form is generated.
The entire clap lasts about 5.6 ms and the module gives you 18 High to Low transitions on it's digital output pin. When the analog voltage drops below a certain voltage, the digital output goes High. When the analog voltage goes above that voltage, the digital output goes Low.
The problem is, the sound of a person clapping generates a noisy signal and the sound sensor module does not know the difference between noise and the sound you want to trigger it.
Instead of using delay()
like I did, you could increment a "clap counter" to equal "1" on the first Low to High transition of the digital output pin. Next, start a non-blocking millis()
timer that waits before you read the digital output pin again. If digital out is High after 400 ms, it's your second clap so change the LED state. A second millis()
timer could reset the "clap counter" to 0 after 1 second.