Skip to content

Instantly share code, notes, and snippets.

@aplocher
Last active March 17, 2017 05:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aplocher/e83fdc72e705c099936cc187cee74768 to your computer and use it in GitHub Desktop.
Save aplocher/e83fdc72e705c099936cc187cee74768 to your computer and use it in GitHub Desktop.
Python script to detect signal from MAX4466 Mic Amp and send an RF signal to power on/off a plug when it detects two clap sounds (aka "DIY The Clapper"). Implemented on Raspberry Pi Zero
#!/usr/bin/python
#
# usage: clapper.py [-h] [--on | --off]
#
# With no arguments, this will run continuously and listen for clap noises to
# trigger an RF power plug to turn on or off (aka The Clapper). Can
# alternatively be used to manually control a power plug with arguments
#
# optional arguments:
# -h, --help show this help message and exit
# --on Send an ON signal to the power plug and exit
# --off Send an OFF signal to the power plug and exit
import spidev
import os
import time
import argparse
# <config stuff>
# Determine what frequency you should send by using the RFSniffer utility
rf_power_off = "4216268 -l 183"
rf_power_on = "4216259 -l 183"
# Higher number means the sound needs to be louder to trigger a "clap"
minimum_sound_level = 640
# Time in seconds between claps. Must detect 2 claps between min/max seconds apart to trigger power on/off
min_time_between_claps = 0.2
max_time_between_claps = 2.0
# Path to codesend bin
code_send_path = "/var/www/rfoutlet/codesend"
# ADC channel
channel = 0
# </config stuff>
# SPI device - bus 0, device 0
spi = spidev.SpiDev()
spi.open(0, 0)
def enum(**enums):
return type('Enum', (), enums)
def change_power_status(rf):
os.system("{} {} -p 0".format(code_send_path, rf))
arg_parser = argparse.ArgumentParser(description='With no arguments, this will run continuously and listen for clap noises to trigger an RF power plug to turn on or off (aka The Clapper). Can alternatively be used to manually control a power plug with arguments')
arg_group = arg_parser.add_mutually_exclusive_group()
arg_group.add_argument('--on', help='Send an ON signal to the power plug and exit',action='store_true')
arg_group.add_argument('--off', help='Send an OFF signal to the power plug and exit',action='store_true')
args = arg_parser.parse_args()
if (args.on):
change_power_status(rf_power_on)
exit()
if (args.off):
change_power_status(rf_power_off)
exit()
PowerStates = enum(ON=1, OFF=0)
last_triggered_time = 0
current_power_state = PowerStates.OFF
print("LISTENING")
while True:
if ( (channel > 7) or (channel < 0) ):
raise ValueError('Invalid channel {}'.format(channel))
spi_result = spi.xfer( [1, (8 + channel) << 4, 0] )
adc_out = ( (spi_result[1] & 3) << 8 ) + spi_result[2]
if (adc_out > minimum_sound_level):
# Detected sound was loud enough to trigger a "clap"
print(adc_out)
triggered_time = time.time()
last_triggered = triggered_time - last_triggered_time
if (last_triggered > max_time_between_claps):
# Second clap occured too long after the first clap - count as a new FIRST clap
clap_count = 1
elif(last_triggered > min_time_between_claps and last_triggered < max_time_between_claps):
if (clap_count == 0):
# First clap
clap_count = 1
elif (clap_count > 0):
# Second clap (within allotted time range)
if (current_power_state == PowerStates.ON):
current_power_state = PowerStates.OFF
print("SENDING ON")
change_power_status(rf_power_on)
else:
current_power_state = PowerStates.ON
print("SENDING OFF")
change_power_status(rf_power_off)
clap_count = 0
last_triggered_time = triggered_time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment