Go Down

Topic: Arduino Clapper - Clap Clap = On - Clap Clap = Off (Read 16700 times) previous topic - next topic

WilliamK Govinda

Aug 31, 2011, 11:46 pm Last Edit: Sep 03, 2011, 03:54 am by WilliamK Reason: 1
I was checking this other thread out, but couldn't make it work with the Sound Sensor I got on eBay a long time ago.

Here's the old thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1251151678

Here's the sensor:

http://www.ebay.com/itm/Sound-Sensor-Module-Arduino-Sensor-Shield-MCU-PIC-/120758238742?pt=LH_DefaultDomain_0&hash=item1c1dc07e16

Edit: here's the final product video, for more videos, check the other posts below.

http://www.youtube.com/watch?v=Qr7aG96H0UI

So I decided to create my own code nearly from scratch, this works perfectly with that Sound Sensor, and has some error checking and noise detection.

WilliamK Govinda

#1
Sep 01, 2011, 01:19 am Last Edit: Sep 03, 2011, 03:54 am by WilliamK Reason: 1
Since the plan is to use this on our bedroom, I added a touch-sensor (just put a wire connected to any metal thingy into a digital input) to also turn the lights on/off.

The relay for the 220V lights I will be using is this one:
http://www.ebay.com/itm/Mini-5V-DC-SONGLE-Power-Relay-SRD-5VDC-SL-C-PCB-Type-/320571789994

Its very easy to setup the relay. At the bottom you will see 5 connections, the left 3, the middle goes to your 110/220V power. Left and right to the Arduino Ground and output pin. Them the other 2 are the On and Off outputs for the 110/220 destination, in this case, our lights.  8)

WilliamK Govinda

#2
Sep 01, 2011, 02:39 am Last Edit: Sep 03, 2011, 03:55 am by WilliamK Reason: 1
So, I just tested the whole thing with an ATtiny85 using its internal 8Mhz clock and it works perfectly. Here's the complete code as I'm using on the ATtiny85.

I use the info from the Beat707 BigtTime code, found over the following link: https://github.com/Beat707/Beat707-BigTime

I didn't use an Arduino as I need something very small to fit on the power-box that has the current light on/off switch, I will replace the whole thing with this setup: ATtiny85, Mini Relay and 5V USB 110/220V adapter from an old Wii controller charger that was no longer used. (the controllers batteries failed, but the charger still works, 5V @ 500ma)

WilliamK Govinda

#3
Sep 02, 2011, 10:31 pm Last Edit: Sep 06, 2011, 08:53 pm by WilliamK Reason: 1
Everything is working perfectly and its already in place. I will post some pictures and videos soon. ;-)

In the end, here's the code I'm using. It only turns the lights off when you clap-clap, to avoid getting them to turn on in the middle of the night if you cough. ;-)

WilliamK Govinda

Here are the videos:

http://www.youtube.com/watch?v=nQCkBHe7Ch8

http://www.youtube.com/watch?v=3RxAffoelYs

http://www.youtube.com/watch?v=tuMXWMQHv7Y

http://www.youtube.com/watch?v=Qr7aG96H0UI

WilliamK Govinda

After using it on the "real" world, I had to do some changes on the code. Now I save to the EEPROM the Background-Noise levels, so when the power fails, which happens a lot here, it doesn't mess up the system if it startups again and there's some noises going on... Also, fixed some other issues.

Code: [Select]
// Arduino Clapper - by WilliamK @ Wusik.com & Beat707.com - September 06 2011 - V 1.2.0 //
// On V1.2.0, when powering up, it will flash the output them detect for 10 seconds any ambient noise and save into the EEPROM and flash the output once its finished //

#include <EEPROM.h>

#define inPin A1                // Pin input for the audio sensor
#define outPin 0               // Output pin to active external device (use relay for 110/220V)
#define touchPin PINB4         // Must be in PINB# format (digital pin 8 ~ 13 = PINB0 ~ PINB5)
#define clapTime 200           // How long to wait between claps
#define clapIdle 1000          // How long to wait after 2 claps before turning on external device
#define debounceTime 150       // Debounce time, to remove double inputs due to echoing
#define waitBeforeRetry 2000   // How long to wait before trying again after a failed set of claps or loud background noise/sounds
#define delayAfterSwitch 500   // How long to wait after a switch has happened
#define defaultSensitivity 50  // 50 should be ok for most uses
#define outputToSerial 0       // Outputs Stage information to the Serial Device
#define force_new_background 0 // If set to 1 it will force a new Noise Background check

// ------------------------------------------------------------------------------------------------------------------------ //
int def2, num1, num2, num3, def = 0;
uint8_t isOn = false;
uint8_t prevIsOn = false;
unsigned long lastMillis = millis();
uint8_t stage = 0;
#if outputToSerial
  uint8_t prevStage = 9;
#endif
int sensitivity = defaultSensitivity;
int lastValue = 0;
uint8_t prevButton = 0;
uint8_t curButton = 0;
uint8_t wasButtonLow = 1;

// ------------------------------------------------------------------------------------------------------------------------ //
void EEPROMWriteInt(int p_address, int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);
  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

// ------------------------------------------------------------------------------------------------------------------------ //
unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);
  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

// ------------------------------------------------------------------------------------------------------------------------ //
void setup() 
{
  pinMode(outPin, OUTPUT);
  pinMode(inPin, INPUT);
   
  if (EEPROM.read(0) != 24 || force_new_background) // Check for the Background Noise //
  {
    delay(2000);

    digitalWrite(outPin, HIGH);
    delay(150);
    digitalWrite(outPin, LOW);
   
    for (char x=0; x<4; x++)
    {
      delay(1000);
      num1 = analogRead(inPin);
      delay(250);
      num2 = analogRead(inPin);
      delay(250);
      num3 = analogRead(inPin);
      def2 = ((num1 + num2 + num3) / 3) + sensitivity;
      if (def2 > def) def = def2;
    }
   
    for (char x=0; x<6; x++)
    {
      delay(1000);
      num1 = analogRead(inPin);
      delay(250);
      num2 = analogRead(inPin);
      delay(250);
      num3 = analogRead(inPin);
      def2 = ((num1 + num2 + num3) / 3) + sensitivity;
      if (def2 < def) def = def2;
    }
   
    // Write Default Background Noise //
    EEPROMWriteInt(1, def);
    EEPROM.write(0, 24);
   
    digitalWrite(outPin, HIGH);
    delay(150);
    digitalWrite(outPin, LOW);
  }
 
  #if outputToSerial
    Serial.begin(38400);
  #endif
 
  prevButton = getcap(1<<PINB0);
  def = EEPROMReadInt(1);
}

// ------------------------------------------------------------------------------------------------------------------------ //
void loop() 
{
  lastValue = analogRead(inPin);
 
  if (isOn)
  {
    switch (stage)
    {
      case 0: if (lastValue > def) { lastMillis = millis() + clapTime; stage = 1; delaySomeTime(debounceTime); } break;   
      case 1: if (lastValue > def) { stage = 5; lastMillis = millis() + waitBeforeRetry; } else if (millis() > lastMillis) { stage = 2; lastMillis = millis() + clapTime; } break;
      case 2: if (lastValue > def) { lastMillis = millis() + clapIdle; stage = 3; delaySomeTime(debounceTime); } else if (millis() > lastMillis) { stage = 5; lastMillis = millis() + waitBeforeRetry; } break;
      case 3: if (lastValue > def) { stage = 5; lastMillis = millis() + waitBeforeRetry; } else if (millis() > lastMillis) stage = 4; break;
      case 4: if (lastValue < def) { isOn = !isOn; } stage = 0; break;
     
      case 5: // This is the Wait Before Retrying stage //
        if (lastValue > def) lastMillis = millis() + waitBeforeRetry; else if (millis() > lastMillis) stage = 0;
        break;
    }
  }
 
  #if outputToSerial
    if (stage != prevStage)
    {
      Serial.println(stage, DEC);
      prevStage = stage;
    }
  #endif
 
  checkButton();
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkNewOn()
{
  if (isOn != prevIsOn)
  {
    digitalWrite(outPin, isOn);
    prevIsOn = isOn;
    delay(delayAfterSwitch);
  }
}

// ------------------------------------------------------------------------------------------------------------------------ //
void delaySomeTime(unsigned long ms)
{
  uint16_t start = (uint16_t)micros();

  while (ms > 0)
  {
    if (((uint16_t)micros() - start) >= 1000)
    {
      ms--;
      start += 1000;
    }
    checkButton();
  }
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkButton()
{
  curButton = getcap(1<<touchPin);
 
  if (curButton != prevButton)
  {
    prevButton = curButton;
    if (wasButtonLow == 1 && curButton > 1)
    {
      isOn = !isOn;
      wasButtonLow = 0;
      stage = 0;
      checkNewOn();
      delay(500);
    }
    if (curButton <= 1) wasButtonLow = 1;
  }
 
  checkNewOn();
}

// ------------------------------------------------------------------------------------------------------------------------ //
char getcap(char pin)
{
  char i = 0;
  DDRB &= ~pin;          // input
  PORTB |= pin;          // pullup on
  for(i = 0; i < 2; i++)
  {
    if( (PINB & pin) ) break;
  }
  PORTB &= ~pin;         // low level
  DDRB |= pin;           // discharge
  return i;
}

CrossRoads

Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

WilliamK Govinda

Thanks.

Last night the lights would turn off just by opening the bathroom door or by speaking, so I had to revisit the code. Also, we had some power spikes here and in one of those the device wouldn't work anymore, as it got a loud background noise when it powered up again, so I had to come with another solution. ;-)

In the next few days we will know if this is really good now.  8)

I really love working with the Arduino IDE, its just pure fun.

Do you think people need some Fritzing files on how I connected the whole thing up? Its actually easy, as the ATtiny85 has so few pins. ;-)

Wk

WilliamK Govinda

Its working much better with the new code now, yeah! Its still a bit too sensitive at the default values, so, when I close the bathroom door, the clicks the door makes shut down the lights. But that's ok, its not often. ;-)

Wk

WilliamK Govinda

I had to update the code, as the lights were turning off with no apparent reason, so I did some hacks to the code and now its 99% perfectly. Before, closing a door would turn the lights off too.

Code: [Select]
// Arduino Clapper - by WilliamK @ Wusik.com & Beat707.com - September 06 2011 - V 1.2.0 //
// On V1.2.0, when powering up, it will flash the output them detect for 10 seconds any ambient noise and save into the EEPROM and flash the output once its finished //

#include <EEPROM.h>

#define inPin A1                // Pin input for the audio sensor
#define outPin 0               // Output pin to active external device (use relay for 110/220V)
#define touchPin PINB4         // Must be in PINB# format (digital pin 8 ~ 13 = PINB0 ~ PINB5)
#define clapTime 250           // How long to wait between claps
#define clapIdle 1000          // How long to wait after 2 claps before turning on external device
#define debounceTime 100        // Debounce time, to remove double inputs due to echoing
#define waitBeforeRetry 3000   // How long to wait before trying again after a failed set of claps or loud background noise/sounds
#define delayAfterSwitch 500   // How long to wait after a switch has happened
#define defaultSensitivity 50  // 50 should be ok for most uses
#define outputToSerial 0       // Outputs Stage information to the Serial Device
#define force_new_background 0 // If set to 1 it will force a new Noise Background check

// ------------------------------------------------------------------------------------------------------------------------ //
int def2, num1, num2, num3, def = 0;
uint8_t isOn = false;
uint8_t prevIsOn = false;
unsigned long lastMillis = millis();
uint8_t stage = 0;
#if outputToSerial
  uint8_t prevStage = 9;
#endif
int sensitivity = defaultSensitivity;
int lastValue = 0;
uint8_t prevButton = 0;
uint8_t curButton = 0;
uint8_t wasButtonLow = 1;

// ------------------------------------------------------------------------------------------------------------------------ //
void EEPROMWriteInt(int p_address, int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);
  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

// ------------------------------------------------------------------------------------------------------------------------ //
unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);
  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

// ------------------------------------------------------------------------------------------------------------------------ //
void setup() 
{
  pinMode(outPin, OUTPUT);
  pinMode(inPin, INPUT);
   
  if (EEPROM.read(0) != 24 || force_new_background) // Check for the Background Noise //
  {
    delay(2000);

    digitalWrite(outPin, HIGH);
    delay(150);
    digitalWrite(outPin, LOW);
   
    for (char x=0; x<4; x++)
    {
      delay(1000);
      num1 = analogRead(inPin);
      delay(250);
      num2 = analogRead(inPin);
      delay(250);
      num3 = analogRead(inPin);
      def2 = ((num1 + num2 + num3) / 3) + sensitivity;
      if (def2 > def) def = def2;
    }
   
    for (char x=0; x<6; x++)
    {
      delay(1000);
      num1 = analogRead(inPin);
      delay(250);
      num2 = analogRead(inPin);
      delay(250);
      num3 = analogRead(inPin);
      def2 = ((num1 + num2 + num3) / 3) + sensitivity;
      if (def2 < def) def = def2;
    }
   
    // Write Default Background Noise //
    EEPROMWriteInt(1, def);
    EEPROM.write(0, 24);
   
    digitalWrite(outPin, HIGH);
    delay(150);
    digitalWrite(outPin, LOW);
  }
 
  #if outputToSerial
    Serial.begin(38400);
  #endif
 
  prevButton = getcap(1<<PINB0);
  def = EEPROMReadInt(1);
}

// ------------------------------------------------------------------------------------------------------------------------ //
void loop() 
{
  lastValue = analogRead(inPin);
 
  if (isOn)
  {
    switch (stage)
    {
      case 0: if (lastValue > (def+10)) { lastMillis = millis() + clapTime; stage = 1; delaySomeTime(debounceTime); } break;   
      case 1: if (lastValue > (def+10)) { stage = 5; lastMillis = millis() + waitBeforeRetry; } else if (millis() > lastMillis) { stage = 2; lastMillis = millis() + clapTime; } break;
      case 2: if (lastValue > (def+10)) { lastMillis = millis() + clapIdle; stage = 3; delaySomeTime(debounceTime); } else if (millis() > lastMillis) { stage = 5; lastMillis = millis() + waitBeforeRetry; } break;
      case 3: if (lastValue > (def+10)) { stage = 5; lastMillis = millis() + waitBeforeRetry; } else if (millis() > lastMillis) stage = 4; break;
      case 4: if (lastValue < def) { isOn = !isOn; } stage = 0; break;
     
      case 5: // This is the Wait Before Retrying stage //
        if (lastValue > (def+10)) lastMillis = millis() + waitBeforeRetry; else if (millis() > lastMillis) stage = 0;
        break;
    }
  }
 
  #if outputToSerial
    if (stage != prevStage)
    {
      Serial.println(stage, DEC);
      prevStage = stage;
    }
  #endif
 
  checkButton();
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkNewOn()
{
  if (isOn != prevIsOn)
  {
    digitalWrite(outPin, isOn);
    prevIsOn = isOn;
    delay(delayAfterSwitch);
  }
}

// ------------------------------------------------------------------------------------------------------------------------ //
void delaySomeTime(unsigned long ms)
{
  uint16_t start = (uint16_t)micros();

  while (ms > 0)
  {
    if (((uint16_t)micros() - start) >= 1000)
    {
      ms--;
      start += 1000;
    }
    checkButton();
  }
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkButton()
{
  curButton = getcap(1<<touchPin);
 
  if (curButton != prevButton)
  {
    prevButton = curButton;
    if (wasButtonLow == 1 && curButton > 1)
    {
      isOn = !isOn;
      wasButtonLow = 0;
      stage = 0;
      checkNewOn();
      delay(500);
    }
    if (curButton <= 1) wasButtonLow = 1;
  }
 
  checkNewOn();
}

// ------------------------------------------------------------------------------------------------------------------------ //
char getcap(char pin)
{
  char i = 0;
  DDRB &= ~pin;          // input
  PORTB |= pin;          // pullup on
  for(i = 0; i < 2; i++)
  {
    if( (PINB & pin) ) break;
  }
  PORTB &= ~pin;         // low level
  DDRB |= pin;           // discharge
  return i;
}

tkbyd

When you connected the sound sensor...

Did you power it from the Arduino's 5v? Or was it powered by something higher? (Ebay description speaks of supplying "<=12v"... 5v seems a LOT "less than", but it would be so nice if the device was as simple as I am hoping...  (^_^)


WilliamK Govinda

Yes, I used the 5V, it lowers the sensitivity a lot, but still works. If you need the full-range-sensitivity, use 12V.

Wk

WilliamK Govinda

Here's a new code which works much better.

Code: [Select]
// Arduino Clapper - by WilliamK @ Wusik.com & Beat707.com - November 06 2011 - V 1.4.0 //
// On V1.4.0, a volume checker is placed which checks for background noise x sound "pops".

#define inPin A1               // Pin input for the audio sensor
#define outPin 0               // Output pin to active external device (use relay for 110/220V)
#define touchPin PINB4         // Must be in PINB# format (digital pin 8 ~ 13 = PINB0 ~ PINB5)

// ------------------------------------------------------------------------------------------------------------------------ //
uint8_t isOn = false;
uint8_t prevIsOn = false;
uint8_t prevButton = 0;
uint8_t curButton = 0;
uint8_t wasButtonLow = 1;

unsigned long sensorValue = 0;
unsigned char counter = 0;
unsigned long backgroundNoise = 0;
unsigned char claps = 0;
unsigned long milliS = millis();

// ------------------------------------------------------------------------------------------------------------------------ //
void setup() 
{
  pinMode(outPin, OUTPUT);
  pinMode(inPin, INPUT);
 
  prevButton = getcap(1<<PINB0);
}

// ------------------------------------------------------------------------------------------------------------------------ //
void loop() 

  if (isOn)
  {
    sensorValue += analogRead(inPin);
    counter++;
    if (counter > 125)
    {
      if (backgroundNoise > 0 && sensorValue > (backgroundNoise+1400))
      {
        claps++;
        if (claps == 2) milliS = millis() + 1000; else milliS = millis() + 4000;
      }
      if (sensorValue > backgroundNoise) backgroundNoise = sensorValue;
        else if (backgroundNoise > sensorValue && backgroundNoise >= 400) backgroundNoise -= 400;
      counter = 0;
      sensorValue = 0;
    }
    delayMicroseconds(250);
 
    if (milliS > 0 && millis() > milliS)
    {
      if (claps == 2)
      {
        isOn = !isOn;
        checkNewOn();
      }
     
      claps = milliS = 0;
    }
  }
 
  checkButton();
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkNewOn()
{
  if (isOn != prevIsOn)
  {
    digitalWrite(outPin, isOn);
    prevIsOn = isOn;
    sensorValue = backgroundNoise = claps = counter = milliS = 0;
    delay(2000);
  }
}

// ------------------------------------------------------------------------------------------------------------------------ //
void checkButton()
{
  curButton = getcap(1<<touchPin);
 
  if (curButton != prevButton)
  {
    prevButton = curButton;
    if (wasButtonLow == 1 && curButton > 1)
    {
      isOn = !isOn;
      wasButtonLow = 0;
      checkNewOn();
      delay(500);
    }
    if (curButton <= 1) wasButtonLow = 1;
  }
 
  checkNewOn();
}

// ------------------------------------------------------------------------------------------------------------------------ //
char getcap(char pin)
{
  char i = 0;
  DDRB &= ~pin;          // input
  PORTB |= pin;          // pullup on
  for(i = 0; i < 2; i++)
  {
    if( (PINB & pin) ) break;
  }
  PORTB &= ~pin;         // low level
  DDRB |= pin;           // discharge
  return i;
}

sbright33

http://www.ebay.com/itm/Sound-Sensor-Module-Arduino-Sensor-Shield-MCU-PIC-/120758238742?pt=LH_DefaultDomain_0&hash=item1c1dc07e16

Is this sensor capable or recording audio too?
Or does it only measure energy levels?
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Go Up