Clapping counter for sound sensor

I recently got into this hobby. I just want to share with you guys my little project that counts the number of clapping made in a specified time.
I'm using an Arduino nano and just a sound sensor module for this project.
The circuit diagram might look like this (Let's just pretend that ir sensor is a sound sensor)
image
The code I'm using to turn on or off the led on pin 13 is the following
Where the CLAP_TIME is the time limit for the claps following the first clap.

#define SAMPLE_TIME 10
#define CLAP_TIME 2000
#define AUDIO 2
#define DELAY_TIME 100

unsigned long lastMillisec = 0;
unsigned long current_time = 0;
unsigned long elapsed_time = 0;
int sample = 0;

void setup()
{
    pinMode(2, INPUT);
    pinMode(13, OUTPUT);
}

void turnLed(boolean on)
{
    if (on)
    {
        digitalWrite(13, HIGH);
    }
    else
        digitalWrite(13, LOW);
}

int clap()
{
    int clapCnt;

    current_time = millis();
    elapsed_time = current_time - lastMillisec;
    if (digitalRead(AUDIO) == LOW)
        sample++;
    if (elapsed_time > SAMPLE_TIME)
    {
        if (sample >= 100)
        {
            delay(100);
            clapCnt = 1;
            sample = 0;
            unsigned long timeStamp = millis();
            lastMillisec = timeStamp;
            while (millis() - timeStamp < CLAP_TIME)
            {
                current_time = millis();
                elapsed_time = current_time - lastMillisec;
                if (digitalRead(AUDIO) == LOW)
                    sample++;
                if (elapsed_time > SAMPLE_TIME)
                    if (sample >= 100)
                    {
                        clapCnt++;
                        sample = 0;
                        lastMillisec = current_time;
                        delay(200);
                    }
            }
            return clapCnt;
        }
        sample = 0;
        lastMillisec = current_time;
    }
    return 0;
    
}

void loop()
{
    int i = clap();
    if (i == 2)
    {
        turnLed(true);
    }
    else if (i == 3)
    {
        turnLed(false);
    }
}

It works fine and I'm happy with it. Hope to hear everyone's comments about this small project.

Welcome to the forum
Good for you for getting something working which is always satisfying

A few comments

           lastMillisec = current_time;
            delay(200);

Mixing delay() and millis() timing in the same sketch does not sit well with me

To make it worse you have wrapped millis() timing in a while loop thus effectively stopping the execution of the loop() function. That may not matter in your current project but you should be aware of its effects

It is good that you have used a function to control the LED but it could be shorter because all you need to do is to write the value of the boolean passed to it to the LED pin using digitalWrite(). You do not need to test the value

1 Like

As far I see, this code shouldn't compile, SAMPLE_TIME is not defined anywhere

1 Like

Thank you I will note that

Oh I missed the fist define
#define SAMPLE_TIME 10

Hey, how can I do this so that it does not affect the program's execution?

You need to restructure your program so that loop() can run freely. One way to do this would be to use what is known as a state machine. It sounds scary but is really just a way of making sure that only the code for the current state of the program is run plus any other general purpose code that runs in loop()

It looks like your program has 3 states, so let's give them meaningful names

WAITING
COUNTING
RESULTS

My favourite way of implementing a state machine is to use switch/case. Something like this

switch (currentState)
{
  case WAITING:
    //code here to wait for first clap
    //then change to COUNTING STATE
    break;
  case COUNTING:
    //code here to count claps for a period
    //when the period ends change to state RESULTS
    break;
  case RESULTS:
    //code here to report and act on number of claps
    //reset variables etc and change to state WAITING
    break;
};

This code goes in loop() or a function called from it and it can call other functions to do what you need. It must not hold up the execution of loop() by using delay() or while()

Great, seems logical and easy enough to do. I'll have a go on this

Hey bob, I've done the state machine code and everything else for another project and made a board for It. It has some problems that I want to ask about, should I ask about it here or make another post?

I don’t see anything that says it is specific to clapping. I guess any loud noise will trigger it. I expected to see a FFT analysis of the frequency, a bit misleading tbh. Also this is not a question why is this marked solved? If you are asking for feedback, then this is not the right forum.

Ask on this topic so that the background information is easily available

I have moved it to the Programming category of the forum

The new code is in the new topic I just created https://forum.arduino.cc/t/issues-with-controlling-led-light-strip-with-mosfet/1034882/11
I'm using motfets to control a RGB led strip. And the clapping turn the light on and off. This is the code

#define ITERATION 15
#define DELAY 2
#define FAULT_DELAY 100
#define MAX_BVAL 255
#define rPin 3
#define gPin 5
#define bPin 6

int NumberSounds = 0;
int SoundPin = 2;
int RawValue = 0;
int NumberClaps = 0;
int LightOn = 0;
unsigned long SoundDetectedTime = 0;
unsigned long PreviousSoundDetectedTime = 0;
int UniqueClapMinTime = 100;
int LEDPin = 13;
unsigned long PreviousClapTime = 0;
unsigned long CurrentClapTime = 0;
unsigned long MaxTimeBetweenClaps = 2000;
unsigned long lastMillisec = 0;
unsigned long current_time = 0;
unsigned long elapsed_time = 0;
int sample = 0;

long totalValue = 0;
int count = 0;

int counter = 1;
int aState;
int aLastState;

int rBr = 0;
int bBr = 0;
int gBr = 0;

boolean state = false;
int lastClap = 2;

void setup()
{
    // put your setup code here, to run once:
    Serial.begin(9600);
    pinMode(rPin, OUTPUT);
    pinMode(gPin, OUTPUT);
    pinMode(bPin, OUTPUT);
    pinMode(SoundPin, INPUT);
    pinMode(LEDPin, OUTPUT);
}

int IsSoundPartOfUniqueClap()
{
    int result = 0;
    unsigned long ElapsedTime =
        SoundDetectedTime -
        PreviousSoundDetectedTime;
    if (ElapsedTime >= UniqueClapMinTime)
    {
        result = 1;
    }
    return result;
}

int CheckTurnOnOffLight()
{
    int result = 0;
    unsigned long ElapsedTime =
        CurrentClapTime - PreviousClapTime;
    if (ElapsedTime <= MaxTimeBetweenClaps)
    {
        if (NumberClaps == 2)
        {
            result = 1;
            NumberClaps = 0;
        }
    }
    else
    {
        NumberClaps = 1;
    }
    return result;
}

void off()
{
    setRed(0);
    setGreen(0);
    setBlue(0);
}

void setRed(int br)
{

    int accu = br > rBr ? 1 : -1;
    for (rBr; rBr != br; rBr += accu)
    {
        analogWrite(rPin, rBr);
        delay(DELAY);
    }
}

void setGreen(int br)
{

    int accu = br > gBr ? 1 : -1;
    for (gBr; gBr != br; gBr += accu)
    {
        analogWrite(gPin, gBr);
        delay(DELAY);
    }
}

void setBlue(int br)
{

    int accu = br > bBr ? 1 : -1;
    for (bBr; bBr != br; bBr += accu)
    {
        analogWrite(bPin, bBr);
        delay(DELAY);
    }
}

void hsv(int value)
{
    if (value <= 60)
    {
        setRed(255);
        setBlue(0);
        setGreen(map(value, 0, 60, 0, 255));
    }
    else if (value > 60 && value <= 120)
    {
        setGreen(255);
        setBlue(0);
        setRed(255 - map(value, 60, 120, 0, 255));
    }
    else if (value > 120 && value <= 180)
    {
        setRed(0);
        setGreen(255);
        setBlue(map(value, 120, 180, 0, 255));
    }
    else if (value > 180 && value <= 240)
    {
        setRed(0);
        setBlue(255);
        setGreen(255 - map(value, 180, 240, 0, 255));
    }
    else if (value > 240 && value <= 300)
    {
        setBlue(255);
        setGreen(0);
        setRed(map(value, 240, 300, 0, 255));
    }
    else if (value > 300 && value <= 360)
    {
        setRed(255);
        setGreen(0);
        setBlue(255 - map(value, 300, 360, 0, 255));
    }
}

void loop()
{
    RawValue = digitalRead(SoundPin);
    if (RawValue == 0)
    {
        NumberSounds++;

        // Process raw data for claps
        PreviousSoundDetectedTime =
            SoundDetectedTime;
        SoundDetectedTime = millis();
        if (IsSoundPartOfUniqueClap())
        {
            NumberClaps++;

            // Update Clap Times
            PreviousClapTime =
                CurrentClapTime;
            CurrentClapTime = millis();

            // Turn Light ON/OFF as needed
            if (CheckTurnOnOffLight())
            {
                LightOn = ~LightOn;
                if (LightOn)
                {
                    state = true;
                }
                else
                {
                    state = false;
                }
            }
        }
    }

    if (state)
    {
        int sensorValue = analogRead(A0);
        totalValue += sensorValue;
        if (count++ == ITERATION)
        {
            hsv(map(totalValue / ITERATION, 0, 1023, 0, 255));
            totalValue = 0;
            count = 1;
        }
        digitalWrite(13, HIGH);
    }
    else
    {
        off();
        digitalWrite(13, LOW);
    }
}

Why did you start a new topic when I explicitly recommended continuing here ?

Now the same code is posted in 2 topics which is totally unnecessary

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.