#!/usr/bin/env python3 # Control relay using sound sensor. # Clap twice to turn on or off. # (c) 2018 Bradley Knockel # If using hardware SPI, make sure you've enabled SPI using # sudo raspi-config (in Interface Options) # Then reboot the Pi. # How to install the Adafruit modules for ADC... # sudo apt-get install python3-pip # sudo pip3 install adafruit-mcp3008 # sound sensor (KY-037)... # + -> 5V # G -> GND # A0 -> voltage divider -> ADC pin 1 (channel 0) # Sadly, it picks up background noises and any breeze over microphone. # Voltage divider # R1 = 1000 ohm + 1000 ohm # R2 = 5100 ohm # The output of KY-037 should never be much more than 3.3 V unless very loud, # but the voltage divider is for my sanity. # ADC (MCP3008) pins... # VDD (16) to 3.3V # VREF (15) to 3.3V # AGND (14) to GND # CLK (13) to GPIO 11 (sclk) (must be at least 10 kHz) # DOUT (12) to GPIO 9 (miso) # DIN (11) to GPIO 10 (mosi) # CS/SHDN (10) to GPIO 8 (ce0) (must be pulled HIGH/off between conversions) # DGND (9) to GND # Note that the faster SPI and ADC are, the higher the threshold needs to be. # This is because if you sample much more, you are bound to get larger # fluctuations. Or, you could add a delay in the code. relayPin = 21 # or pin that controls the transistor that controls a relay soundSensor = True volumeThreshold = 5 # at least 1 onTimeMax = 1 # max minutes to be on before auto turn off waitMin = 0.1 # min s to wait after first clap for second clap waitMax = 1.0 # max s to wait after first clap for second clap # waitMax also corresponds to the dead time after changing state import RPi.GPIO as IO IO.setmode(IO.BCM) IO.setup(relayPin, IO.OUT) IO.output(relayPin, 0) import time import Adafruit_MCP3008 ## Software SPI configuration: #CLK = 11 #MISO = 9 #MOSI = 10 #CS = 8 #mcp = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI) ## Hardware SPI configuration: import Adafruit_GPIO.SPI as SPI # Adafruit's spidev module mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(0,0)) if soundSensor: val2 = mcp.read_adc(0) on = False time1 = time.time() - waitMax # time at first clap try: while 1: if soundSensor: time.sleep(0.001) val1 = val2 val2 = mcp.read_adc(0) now = time.time() if abs(val1-val2) > volumeThreshold: if now-time1 > waitMin and now-time1 < waitMax: on = not on if on: IO.output(relayPin, 1) timeOn = now else: IO.output(relayPin, 0) time.sleep(waitMax) val2 = mcp.read_adc(0) elif now-time1 > waitMax: time1 = now else: pass # maybe put some code here to prevent continuous sound # from triggering the code if on and now-timeOn > onTimeMax*60: # auto turn off on = False IO.output(relayPin, 0) time.sleep(waitMax) val2 = mcp.read_adc(0) else: # turn on and off forever IO.output(relayPin, 1) # on time.sleep(10) IO.output(relayPin, 0) # off time.sleep(10) except: pass # cleanup IO.output(relayPin, 0) IO.cleanup()