Go Down

Topic: clap detect (Read 11099 times) previous topic - next topic

mitko290

Hi all I have arduino uno now , and currently I have one small electret microphone amplifier is there a way to determinate voice and clapping by analog value from arduino ?

The code I am using to detect single,double clapping is :
Code: [Select]
int potPin = 2;   
int ledPin = 13; 
int val = 0; 
int amp = 0; 
int go = 0; 

unsigned long lastClap = 0;
unsigned long nowClap = 0;
unsigned int claps = 0;
#define DOUBLECLAPTHRESHOLD 700

void setup()

  pinMode(ledPin, OUTPUT);  // declare the ledPin as an OUTPUT 
  Serial.begin(9600);


void loop()
{
  val = analogRead(potPin); 
  amp = (val >= 512) ? val - 512 : 512 - val; 
 
  if (amp > 200) // threshold
  {
    nowClap = millis();
    claps = 1;
    if (nowClap - lastClap < DOUBLECLAPTHRESHOLD) claps = 2;
    lastClap = nowClap;
  }
delay(30);
switch(claps)
  {
  case 0:
    digitalWrite(ledPin, LOW);
    break;
  case 1:
    digitalWrite(ledPin, LOW);
    break;
  case 2:
    digitalWrite(ledPin, HIGH);
    break;
  default:
  digitalWrite(ledPin, LOW);
    break;
  }

}

robtillaart

Think it is very difficult, impossible if you want 100%,

You could make a "volume-o-gram"

if sound comes above a threshold, start timing, and log values in an array
if sounds drops under the threshold, stop timing

if it was short and has a high peakvolume => clap
if it was longer and "flatter" => voice

might be a nice casus for a neural network approach?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

mitko290

#2
Aug 28, 2011, 11:20 pm Last Edit: Aug 28, 2011, 11:24 pm by mitko290 Reason: 1
Ok,my amplifier give me analog values from 0 to 1024,how should I understand when I am clapping and when I am talking , if I am talking louder then normal then the amplifier will detect it as clapping and vice versa.
Maybe I need some algorithm to do this,and I will be very thankfull if someone can give to me ...

retrolefty


Ok,my amplifier give me analog values from 0 to 1024,how should I understand when I am clapping and when I am talking , if I am talking louder then normal then the amplifier will detect it as clapping and vice versa.
Maybe I need some algorithm to do this,and I will be very thankfull if someone can give to me ...



What you are asking for, to be able to distinguish between a loud voice and a loud clap is something beyond the capabilities of an Arduino, at least in my opinion. By the way are you applying pure audio AC voltages to the analog input pin? I ask because arduino pins cannot safety handle negative voltages and you risk damage to the pin.

Lefty

mitko290

Yes I am sure...
I just want to activate the the whole system only if clap was heard

robtillaart

Quote
Maybe I need some algorithm to do this, and I will be very thankfull if someone can give to me ...


try this, it is a first coded version of the base algorithm I posted before, might need some tweaking or so

(not compiled or tested...)
Code: [Select]

#define LOW_THRESHOLD 50
#define HIGH_THRESHOLD 200

#define MAXCLAPSAMPLES 400

int i = 0;
uint8_t array[MAXCLAPSAMPLES+1];

void setup()
{
 Serial.begin(115200);
 Serial.println("Clap detector 0.1");
}

void loop()
{
 // MAKE MEASUREMENT
 int volume = analogRead(A0)/4;   //  gives a range from 0..255, fits in a byte
 int maxVol = 0;
 while (volume > LOW_THRESHOLD && i < MAXCLAPSAMPLES)
 {
    maxVol = max(maxVol, volume);
    array[i++] = volume;
    volume = analogRead(A0)/4;
    // delay(5);
 }

 // ANALYZE SAMPLES IN ARRAY  (can be extended to much more complex rules)
 if (i > 0)
 {
   Serial.println("analyzing samples...");
   for (int j=0; j < i; j++)   // dumping samples so you can copy them into Excel
   {
     Serial.print(array[i]);
     Serial.print(", ");
   }
   Serial.println();

   if (i <= MAXCLAPSAMPLES && maxVol >= HIGH_THRESHOLD) Serial.println("hard clap");
   if (i <= MAXCLAPSAMPLES && maxVol < HIGH_THRESHOLD) Serial.println("soft clap or short voice");
   if (i > MAXCLAPSAMPLES && maxVol >= HIGH_THRESHOLD) Serial.println("hard voice or multi clap");
   if (i > MAXCLAPSAMPLES && maxVol < HIGH_THRESHOLD) Serial.println("soft voice");
 }

 // RESET VARS
 i = 0;
 maxVol = 0;
}



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

amacmullen14

#6
Aug 29, 2011, 01:27 am Last Edit: Aug 29, 2011, 01:30 am by sciguy Reason: 1
Does it need to distinguish between a clap and a short shout, or just between a clap and normal talking?

If it's the latter, then simply listening for 2 loud sounds wouldn't work, since loud talking could just be constant loud noise.

However, it might work to listen for a loud noise, then for a silence, then a loud noise, then a longer silence, all within a certain period of time from each other.  I have a Clapper that plugs into an outlet to control lamps, etc, and it appears to work in this way.  (i.e. if I clap, a light turns on at each clap, but if I just say "aaaaaaaaaaaaaaaaa", one light goes on, then turns off.)
This means you can still purposely trigger it by making 2 short shouts, but this probably would not end up being a problem.  (and a useful feature if both of your hands are broken)

stevenSwift

#7
Aug 29, 2011, 01:44 am Last Edit: Aug 29, 2011, 09:39 am by stevenSwift Reason: 1
Here is an idea for you: count zero crossings as well as volume.

Use the mike with an amp and connect to analog port.

Read port as fast as possible in a tight loop. You can get about 10K samples per second, which is enuf for this purpose. Every time the value goes from + to - (which you'll have to bias, so + is > 512, - is < 512), that is a "zero crossing". Count the number of them. Simultaneously track the average max value, ie, the sound volume.

I believe you will find, with some experimentation, that a clap will produce far higher zero crossings than any voice can do!

(Essentially, zero crossings per second are a very rough estimate of the major frequency of the sound. A clap is white noise, energy at all frequencies, lots of high frequencies, lots of zero crossings. A voice is closer to pure, less high frequencies.) Thus, at same volume level, here is a way to distinguish a clap from vocal sounds.)

Just a thought, idea for experimenting.... I built a simple voice recognition system using this method, actually got 90% recognition of digits and letters expressed as "alpha" "bravo" "charlie" etc. On a Z80 in 1990!


retrolefty

Quote
Yes I am sure...
I just want to activate the the whole system only if clap was heard


Again, you are risking damage to your analog input pin. You should wire the audio signal through a rectifier/filter circuit and then to the analog input pin.

http://en.wikipedia.org/wiki/Envelope_detector

mitko290

#9
Aug 29, 2011, 11:53 am Last Edit: Aug 29, 2011, 01:09 pm by mitko290 Reason: 1

Quote
Yes I am sure...
I just want to activate the the whole system only if clap was heard


Again, you are risking damage to your analog input pin. You should wire the audio signal through a rectifier/filter circuit and then to the analog input pin.

http://en.wikipedia.org/wiki/Envelope_detector

Ok when I measure with my volt meter the amplifier out pin and ground I am receive only positive values - now do I need this rectifier/filter circuit before connect to arduino ?
I am using this amplifier:
http://www.hobbykit.eu/hobbye/h1035.html
And the code I build until now:
Code: [Select]


// these constants won't change:
int amp = 0 ;
unsigned long lastClap = 0;
unsigned long nowClap = 0;
unsigned int claps = 0;

const int ledPin = 13;      // led connected to digital pin 13
const int electret = 0;  // the amplifier output is connected to analog pin 0


// these variables will change:
int sensorReading = 0;      // variable to store the value read from the sensor pin
int sensorMax = 0;
int sensorMin = 1023;
int threshold;
#define DOUBLECLAPTHRESHOLD 1000

void setup() {
 pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
 Serial.begin(57600);       // use the serial port
 pinMode(13, OUTPUT);
 digitalWrite(13, HIGH);
 while (millis() < 3000) {
   threshold = analogRead(electret);

   // record the maximum sensor value
   if (threshold > sensorMax) {
     sensorMax = threshold;
   }

 }

 // signal the end of the calibration period
 digitalWrite(13, LOW);
 threshold = sensorMax;

}

void loop() {
 // read the sensor and store it in the variable sensorReading:
 sensorReading = analogRead(electret);    

 if ((sensorReading >= threshold)) {
   Serial.println(sensorReading-threshold); //Will send only positive and absolute values of waveform        
   amp = (sensorReading-threshold);
 }
 if(amp > 200) {
  nowClap = millis();
  claps = 1;
 if (nowClap - lastClap < DOUBLECLAPTHRESHOLD) claps = 2;
 lastClap = nowClap;
 }
  delay(30);
switch(claps)
 {
 case 1:
   Serial.println("First clap");
   break;
 case 2:
   Serial.println("Second clap");
   break;
 default:
   break;
 }


 delay(5);
claps = 0;
}



but sometimes its showing first clap,sometimes is showing second claps I want to accurate it now ...

robtillaart


Have you checked with mtbiker - http://arduino.cc/forum/index.php/topic,64236.0.html - which also made a clap detector ?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

mitko290



Have you checked with mtbiker - http://arduino.cc/forum/index.php/topic,64236.0.html - which also made a clap detector ?


I already read that ...

robtillaart

BUt have you send him a message for his final code?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

mitko290


BUt have you send him a message for his final code?

off course I did , but he said the final code it is in the forum

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up