Saturday, February 2, 2013

Arduino clapper Update

I've updated and improved the code for better readability and added some enhancements. It's now possible to change the number of claps in the variable declaration. It's also easier to alter the offset value for clap detection and manipulate the time allowed between each clap.

I modified the diagram as well by removing the enable button.

/*
* Clapper project
* Author: Manoj Kunthu
* Update: 2/2/13
*/

/*-----------------------------
*   Method Prototypes
*-----------------------------*/

void initialize();
void runDetector();
boolean clapDetected();

int detectClaps(int numClaps);
void indicateClaps();
void readMic();

void printStats();

/*-----------------------------
*   Variable Declarations
*-----------------------------*/

int TOTAL_CLAPS_TO_DETECT = 2; //The number of claps detected before output is toggled
int offset = 80;    // The point above average that the clap is detected
int CLAP_TIME=4000; // The time allowed between each clap


int sensorValue = 0; //the value read through mic 

int toggleOutput = -1;

int SIZE = 3;
int buffer[3];
int loopIteration = 0;
int average = 0;
int total = 0;



//BOARD INPUT MIC
const int inPin0 = A0; 

//BOARD OUTPUT SIGNALS
const int clapLed1 = 12, clapLed2 = 11, out = 10, readyPin = 13;

//CLAP STATE CONSTANTS
const int FINAL_DETECTED = 0, LOST_CONTINUITY = 1, CLAP_NOT_DETECTED = 2;

void setup() {
  Serial.begin(9600);
  
  //direct representation of the light bulb that toggles on/off  
  pinMode(out, OUTPUT);
  
  //once initialize() runs the ready pin turns on
  pinMode(readyPin, OUTPUT);
  
  //respective clap LEDs, more can be added
  pinMode(clapLed1, OUTPUT);
  pinMode(clapLed2, OUTPUT);
}


void loop() {
  initialize();
  runDetector();
}

/**
* Purpose: Prepares the buffer to recognize ambient noise levels in room.
*/
void initialize()
{
  loopIteration = 0; 
  total = 0;
  average =0;
  
  digitalWrite(clapLed1, LOW);
  digitalWrite(clapLed2, LOW);
  digitalWrite(out, LOW);
  
  for(int i = 0; i < SIZE; i++)
  {
    readMic();
    
    buffer[i] = sensorValue;
    total = total + sensorValue;
    average = (total/(i+1));
    
    Serial.print("INIT - AVE: ");
    Serial.print(average);
    Serial.print("    Total: ");
    Serial.print(total); 
    Serial.print("    Sensor: ");
    Serial.print(sensorValue); 
    Serial.print("    Change: ");
    Serial.println(sensorValue-average); 
      
    delay(50);
  }
  digitalWrite(readyPin, HIGH);
}

/**
* Purpose: Runs the detector algorithm. Developers can change the number of claps by adjusting TOTAL_CLAPS_TO_DETECT variable up at the top.
*/
void runDetector()
{
  while(true)
  {
    int clapState = detectClaps(TOTAL_CLAPS_TO_DETECT);
    
    if(clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY)
    {
       Serial.println("--done--");
       indicateClap(0);//turn off any clap indicating lights
    }
  }
}

/**
* Purpose:  Detects the number of claps specified. This method is recursive
*/
int detectClaps(int numClaps)
{
  int clapNum = numClaps;
  
  //Base Case - if clapNum is 0, then all claps have been accounted.
  if(clapNum == 0)
  {
    //the output can now be toggled.
    toggleOutput *= -1;
    indicateClap(clapNum);
    
    Serial.println("-----  Clap Limit Reached - Output Toggled -----");
    
    return FINAL_DETECTED;
  }
  
  //Read from mic and update ambient noise levels.
  readMic();

  total = (total - buffer[loopIteration]) + sensorValue; 
  average = (total/SIZE);
  buffer[loopIteration] = sensorValue;
  
  loopIteration = (loopIteration+1)%SIZE;
  
  if(clapDetected())
  { 
    Serial.print("detectClaps - Claps:");
    Serial.println(TOTAL_CLAPS_TO_DETECT + 1 - numClaps); 
    
    printStats();
    indicateClap(clapNum);
    
    delay(100);
    for(int i = 0; i < CLAP_TIME; i++)
    {
      int clapState = detectClaps(clapNum - 1);   
      
      if(clapState == FINAL_DETECTED || clapState == LOST_CONTINUITY)
      {
         return clapState;
      }
    }
    return LOST_CONTINUITY;
  }
  return CLAP_NOT_DETECTED;
}

/**
* Purpose: Turns the LED on appropriately to signal a clap detection.
*/
void indicateClap(int clapNum)
{
  if(clapNum == 0)
  {
    if(toggleOutput == 1)
    {
      digitalWrite(out, HIGH);
    }
    else
    {
      digitalWrite(out, LOW);
    }
    digitalWrite(clapLed1, LOW);
    digitalWrite(clapLed2, LOW);
  }
  else if(clapNum == 1)
  {
     digitalWrite(clapLed1, HIGH);
  }
  else if(clapNum == 2)
  {
     digitalWrite(clapLed2, HIGH);
  }
  delay(110);
}

/**
* Purpose: Prints basic statistics data for more info with sensor readouts and data points.
*/
void printStats()
{
  Serial.print("--- AVE: ");
  Serial.print(average);
  Serial.print("    Total: ");
  Serial.print(total); 
  //Serial.print("    iterNum: ");
  //Serial.print(loopIteration); 
  Serial.print("    Sensor: ");
  Serial.print(sensorValue); 
  Serial.print("    Change: ");
  Serial.println(sensorValue-average); //This is what I used to determine the 'offset' value
}

/**
* Purpose:  A clap is detected when the sensor value is greater than the average plus 
*     an offset.  The offset might need to be fine tuned for different sound sensors.
*/
boolean clapDetected()
{
    return sensorValue > average + offset;
}

/**
* Purpose: Reads mic input and stores it in a global variable.
*/
void readMic()
{
  sensorValue = analogRead(inPin0);  
}


26 comments:

  1. hi.. can i use different type of amp mic ?
    i live in Malaysia, it not available here
    thanks a lot.. really need you help

    ReplyDelete
    Replies
    1. Hi. You can definitely use a different type of mic or a sound sensor. I used one that was available off the shelf, but you can certainly build your own if needed. There are smart people that have posted instructions to build mic amps online using an op amp, an electret mic, and some resistors. One thing you might need to change in this code is the "offset" variable in the very beginning since that depends on the sound sensor you have. Hope it helps!

      Delete
  2. Hello!, i really liked your video demo in youtube, was very funny!

    hey, please consider to upload your code in github!, is by far the best way to share code, you only need to learn git (probably you already know, is very common these days)

    Actually, I've take your code and uploaded to a repository in github, here is the link[1]

    the nice part of github, is that you only need to post a single post per project, the repository link will always show the last version of the project code, this way you can avoid reposting in your blog things like: "this code is old, chek this new version here", and stuff

    in other news.... i've tested your code, but i could not make your project work the way you show in video..., the main difference, is that I have this microphone[2], maybe i am too newbie in electronics, and i am connecting the mic wrong... can you show me how to connect a electret mic like this using your project?

    and last... where can i contact you?, bye!

    [1] https://github.com/joecabezas/ArduinoClapper/
    [2] https://www.adafruit.com/products/1064

    ReplyDelete
    Replies
    1. Thanks Joe! Good thinking on the Github repo.

      For your mic, the Arduino cannot pick up the signal because it is not amplified. If you build an amplifier for it or if you get a mic w/ built-in amp circuit (http://www.adafruit.com/products/1063), it should work as shown. Once amplified, you might have to tweak the "offset" depending on your mic sensitivity.

      Delete
    2. Thank for your reply!

      I have flattred your youtube video[1], so claim it!

      Second... how exactly amplify this electrect mic?, do you have any link that shows the schematic or something else?, i tried a darlington pair, but... did not work, or ... again, did make the right connections in order to make it work :/

      Third... when you create your github repo, fork my project, is the fastest way to make the project yours, need to learn git?, the best book for it is this[2], but is available online!, here[3]

      good bye!, i will waiting for your reply, i really want to make this work!

      [1] https://flattr.com/thing/1389393
      [2] http://www.amazon.com/Pro-Experts-Voice-Software-Development/dp/1430218339/ref=sr_1_2?ie=UTF8&qid=1369785169&sr=8-2
      [3] http://git-scm.com/book/en

      Delete
    3. I just used an off the shelf mic with a build in amp. But to do it yourself, try these 2 videos for help (http://www.youtube.com/watch?v=TQB1VlLBgJE , http://www.youtube.com/watch?v=y0Q0ERSP24A )...at 3:15 of the second vid, it'll show a circuit that could help with the clap detection.

      Delete
  3. Nice jobs, works like a charm... I use a low cost chinees HEX module with DO en AO. You have too play with the offset but then it works great.

    ReplyDelete
  4. hye i just wanna ask u about the power circuit....the schematic diagram shows you are using one MOC3010 and one TRIAC BTA08-400b but in the video i saw you are using two pieces of both component...can u explain further?thanks :)

    ReplyDelete
    Replies
    1. nice catch! and good question. Both circuits are independent from one another. I used one power circuit per outlet...as in one for the top and one for the bottom(which i'm using in the video). This way, if I want a different logic to turn on one of the outlets, I just have to hook in the signal wire at (0:34 sec).

      Delete
  5. emmm..thanks for the reply..but i did not understand much..if i just build the circuit that u gave is it give harmful tu me?what i mean is i just use one pieces of each triac and moc.. :)

    ReplyDelete
    Replies
    1. well, anything with electricity can be harmful. :)

      yes, I just used 1 triac and 1 moc for the connection to the lamp.

      I'm not using the second triac and moc you see.

      Delete
    2. ok i get uour point!haha i misswatch the outlet..you are using each component 2 pieces for two outlets socket for the lamp...hahaha..what a mistake..im sory..thanks! ;)

      Delete
  6. and what is meant by one for the top and one for for the bottom and one power per outlet?can u draw a full schematic diagram for the project in the video? ;)

    ReplyDelete
  7. hi I feel some confusing right here..about the power circuit...is it Line in(HOT) refer to the Life Wire and Common refer to the Neutral Wire?thanks :)

    ReplyDelete
  8. Thanks for sharing works perfect!

    ReplyDelete
  9. hi how to interface with arduino robot?

    ReplyDelete
  10. Hi! I really want to do this project! Could you please give me all the components I need for the project? I'll apreciate it. Thank you.

    ReplyDelete
    Replies
    1. Hi! I labeled all the parts in the diagram. You can get them at digikey or sparkfun

      Delete
  11. Hi ! Thank you for you script, it's pretty usefull, but I have a problem with him, when I do a dubble clap, the final led is on but, one or two second after, the software detect new two clap when in reality there is nothing, how can I solve this problem because it's pretty boring
    Two clap for just one second humm
    Here is a screen of the serial http://puu.sh/8V62K.png

    ReplyDelete
  12. Hey Manoj, very nice project!

    I would like do this, but i have this mic to arduino
    Microphone Sound Sensor Module for arduino KY-038

    URL
    http://www.aliexpress.com/snapshot/6042940573.html

    it will works well or need some modify?

    ty for help
    cya!

    ReplyDelete
    Replies
    1. Hi thanks! This mic is interesting. I'm curious what the digital out will give. If u use the analog output, u may need to adjust the "offset" variable

      Delete
    2. Ty for reply Manoj!
      I too have a Channel in youtube and a blog about arduino and electronic.
      I share project about robot and automation, it is in portuguese.
      If you want check it
      http://tecnologiaeciencia.com.br/
      https://www.youtube.com/user/vcaput

      Sorry for my english!
      Gratefull

      Delete
  13. Great blog about Clapperboards thanks for sharing this blog with us.

    ReplyDelete
  14. Wasn't about line 148 supposed to be "void readMic();" ?

    ReplyDelete