2

I have this double clap sensor code written, it seems it would work but it seems to trigger the double clap even on a single clap, any ideas?

int soundSensor = A1;
int relay = A2;
int relay2 = A3;
int relay3 = A4;
int relay4 = A5;
int claps = 0;
long detectionSpanInitial = 0;
long detectionSpan = 0;
boolean clapState = false;
int doubleClap = 0;


//Light sensor 
int photocellPin = A0;     // the cell and 10K pulldown are connected to a0
int LEDbrightness;       

//int delayValue = 100;
int photoSensor = 0;

// sound sample
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

//other
boolean isRelaysOn = false;
void setup() {
  pinMode(soundSensor, INPUT);
  pinMode(relay, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  turnRelayOff();
  Serial.begin(9600);
}

boolean state = false;
boolean lastState = true;
boolean lightTurnedItOff = false;
void loop() {

  /////////////
  // photo sensor
  //////////////////// 

  photoSensor = analogRead(photocellPin) > 623;

  /////////////
  // clap sensor
  /////////////////////
  double sensorState = getSoundLevel();
  Serial.println(sensorState);
  double threshold = .2;


  if (sensorState > threshold)
  {
    if (claps == 0)
    {
      detectionSpanInitial = detectionSpan = millis();
      claps++;
    }
    else if (claps > 0 && millis()-detectionSpan >= 50)
    {
      detectionSpan = millis();
      claps++;
      Serial.println(" CLAP ADDED!!!!");
    }
  }



  if (millis()-detectionSpanInitial >= 400){

    if (claps == 2)
    {
      claps++;
      doubleClap = 1 - doubleClap;
      state = !state;
      Serial.println("TWO claps!");

      if(lastState == state ){
        relayControl(doubleClap);
        lastState = !lastState;
      }
    }
    claps = 0;
  }

  if(isRelaysOn == true && photoSensor == 1){
    turnRelayOff();
    lightTurnedItOff = true;
  }
  if(isRelaysOn == true && photoSensor == 0 && lightTurnedItOff == true){
    turnRelayOn();
    lightTurnedItOff = false;
  }

}

void relayControl(int doubleClap){
  /////////////
  // relay control
  /////////////////////

  if(doubleClap == 1){ 
    turnRelayOn();
    Serial.println("on");
    isRelaysOn = true;

  }
  else{ 
    turnRelayOff();
    Serial.println("off");
    isRelaysOn = false;
  }; 


}

void turnRelayOn(){
  int delayAmount = 100;
  digitalWrite(relay, LOW);
  delay(delayAmount);
  digitalWrite(relay2, LOW);
  delay(delayAmount);
  digitalWrite(relay3, LOW);
  delay(delayAmount);
  digitalWrite(relay4, LOW);
  delay(100);
  digitalWrite(relay4, HIGH);
  delay(100);
  digitalWrite(relay4, LOW);
}

void turnRelayOff(){
  digitalWrite(relay, HIGH);
  digitalWrite(relay2, HIGH);
  digitalWrite(relay3, HIGH);
  digitalWrite(relay4, HIGH);
}

double getSoundLevel(){

  unsigned long startMillis= millis();  // Start of sample window
  unsigned int peakToPeak = 0;   // peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  // collect data for 50 mS
  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(soundSensor);
    if (sample < 1024)  // toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin){
        signalMin = sample;  // save just the min levels
      }
    }
  }
  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
  double volts = (peakToPeak * 3.3) / 1024;  // convert to volts

  return volts;
}

Serial monitor:

0.02 0.02 0.02 0.02 0.01 0.01 2.20 0.30 CLAP ADDED!!!! 0.13 0.09 0.04 0.02 0.02 0.01 0.02 TWO claps! on 1.11 0.06 0.05 0.07 0.15 0.10 0.03 0.10 0.06 0.03 0.04 0.06

  • Other than this being a possible duplicate of your other question. Could you also give more info like a copy of the serial monitor for one loop when you have clapped. Also try moving else if (sample < signalMin){ signalMin = sample; } out of the if(sample <1024) as you will never enter that else if statement and peaktopeak will always be greater than your threshold. – RSM Feb 18 '16 at 7:19
  • It would help if you described your intended logic better. There are a bunch of state variables (state, lastState, doubleClap) and several timeouts; deciphering your intent from code which doesn't accomplish that intent is extra work and error prone. – Zeph Feb 26 '16 at 8:14
  • @RSM The else is not hard to enter; consider the first two samples 600, 500. Both are < 1024. The first will set signalMax=600, the second will set signalMin=500. There is a different logic error however, which could be fixed by removing "else" so there are two if statements, one setting signalMax and one setting signalMin; the thing is, the first value should trigger both if statements. Otherwise (with the else) consider what happens with samples 100,300,700,900 - each one sets signalMax, but signalMin is never set and retains the dummy 1024 value for a span of -124 instead of 800. – Zeph Feb 26 '16 at 8:21
  • @RSM I added the serial monitor. – lukasz May 14 '16 at 18:52
1

If your first clap rings for more than 50ms, the program counts it as a second clap. After detecting a clap, you need to wait for the sound to die down before you start listening for a second clap.

1

What you probably want to track is something more like:

  • high sound period of highMin to highMax ms
  • low sound period of lowMin to lowMax ms
  • high sound period of highMin to highMax ms
  • low sound period of at least lowDone ms (no max needed)

Anything not meeting those time bounds is not two claps, reset state and timers. If you get to the end of the fourth step, accept as two claps.

I have not tested timing of claps to estimate the periods needed; you need to tweak that with the hardware you are actually using; for example, different microphones may ring for different times after a sharp clap impulse.

States could be:

  • waiting for start of first clap (sample until > threshold)
  • waiting for end of first clap (sample until < threshold or timeout)
  • waiting for start of second clap (sample until > threshold or timeout)
  • waiting for end of second clap (sample until < threshold or timeout)
  • got second clap
0

I have noticed that you have used analogue inputs as your digital outputs by connecting relays to them.

I think this is wrong. You should connect your digital signals to the digital pins.

  • 1
    It really doesn't matter that much. – Avamander Feb 18 '16 at 15:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.