This is actually a lot harder than you might at first think.
Your "sound sensor" is little more than a microphone and amplifier. It gives you an audio waveform - whereas what you are interested in is the peak power.
An audio waveform goes both positive and negative:

The "peak" of the waveform can both be positive (above the line) or negative (below the line).
To get that peak you have to rapidly sample over a short period and find both the maximum and minimum values, and get the difference between them.
However, the Arduino can't see negative values on the ADC - so you only get the upper portion of the waveform, which is less than ideal. Really you should add a DC offset to the output of the sound sensor to bring the signal up to the middle of the ADC range (adding a 10kΩ + 10kΩ voltage divider across the input pin to +5V/GND would do the job).
If you don't add a DC offset then you can rapidly sample for a short period of time and work out the maximum value:
uint16_t getMaximum(uint8_t pin, uint32_t t) {
uint16_t maximum = 0;
uint32_t ts = millis();
while (millis() - ts < t) {
uint16_t sample = analogRead(pin);
if (sample > maximum) {
maximum = sample;
}
}
return maximum;
}
Now to get the maximum over, say, a 10ms period, you can:
uint16_t maximum = getMaximum(A0, 10);
However, if you add a DC offset it gets a little more tricky, but the results will be better:
uint16_t getMaximum(uint8_t pin, uint32_t t) {
int16_t maximum = 0;
int16_t minimum = 0;
uint32_t ts = millis()
while (millis() - ts < t) {
// The -512 here removes the DC offset from the reading. 512 is half
// the ADC range.
int16_t sample = analogRead(pin) - 512;
if (sample > maximum) {
maximum = sample;
}
if (sample < minimum) {
minimum = sample;
}
}
// We now have a positive value as the maximum and a negative
// as the minimum - or zero if none went into the max or min
// region of the waveform. Subtract a negative from a positive
// is like adding a positive to a positive. But we only want
// a positive result, so we'll get the absolute value.
return abs(maximum - minimum);
}
Now that you actually have your peak-peak value of your waveform over a short period you can use it to work out when the sound goes above a threshold and when it goes below, and how long it's been above that threshold. The basic method is:
- Is the sound above the threshold?
- Yes: Was it above the threshold before?
- No: Set a timestamp and a flag to say it's above the threshold.
- Yes: Has it been above > 2 minutes?
- No: Was it above the threshold before?
- Yes: Has it been above > 2 minutes?
The thing here is to know that you are looking for changes in the "above the threshold" state to start your timing. A simple implementation may look like:
static uint32_t wentAbove = 0;
static bool isAbove = false;
const uint16_t threshold = 300;
uint16_t maxval = getMaximum(A0, 10);
if (maxval > threshold) {
if (!isAbove) {
isAbove = true;
wentAbove = millis();
} else {
if (millis() - wentAbove > 120000) {
digitalWrite(13, HIGH);
}
}
} else {
if (isAbove) {
isAbove = false;
digitalWrite(13, LOW);
}
}
Note: all code untested.