Created
January 27, 2013 09:29
-
-
Save anroots/4647548 to your computer and use it in GitHub Desktop.
Python script for Raspberry Pi, Adafruit 7-segment 4-digit LCD backpack and a LED. Uses an USB mic to measure and display sound level.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Sound level indicator on a 7-segment 4-digit LCD, for Raspberry Pi | |
# Uses a USB mic to measure sound level | |
# | |
# https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_LEDBackpack/Adafruit_7Segment.py | |
# https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_LEDBackpack/Adafruit_LEDBackpack.py | |
# https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/blob/master/Adafruit_I2C/Adafruit_I2C.py | |
# | |
# Author Ando Roots <[email protected]> 2013 | |
# http://sqroot.eu | |
import alsaaudio, time, audioop, datetime | |
from Adafruit_7Segment import SevenSegment | |
import RPi.GPIO as GPIO | |
class SoundMonitor: | |
# Red LED address | |
RED_LED = 23 | |
# Light red LED when measured sound value exceeds the preset limit | |
WARNING_THRESHOLD = 800 | |
# Tolerance as a percentage (0.5 is 50%) | |
# LCD output is changed when the measured value exceeds this tolerance | |
TOLERANCE = 0.15 | |
# Minimum time in seconds between each LCD value change | |
MAX_CHANGE_FREQ = 0.5 | |
# 7-segment display (run i2cdetect -y 1 to get the addr) | |
segment = SevenSegment(address=0x70) | |
# Alsaaudio instance | |
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE,alsaaudio.PCM_NORMAL, 'sysdefault:CARD=Set') | |
def __init__(self): | |
# LED | |
GPIO.setmode(GPIO.BCM) | |
GPIO.setup(self.RED_LED, GPIO.OUT) | |
# Set attributes: Mono, 8000 Hz, 16 bit little endian samples | |
self.inp.setchannels(1) | |
self.inp.setrate(8000) | |
self.inp.setformat(alsaaudio.PCM_FORMAT_S16_LE) | |
self.inp.setperiodsize(160) | |
# Write a 4-digit number to the LCD | |
def write_number(self, value): | |
value = int(value) | |
if value > 9999: | |
print "Value %s is out of bounds, setting to 9999" % value | |
value = 9999 | |
value = str(value).zfill(4) | |
self.segment.writeDigit(0, int(value[0])) | |
self.segment.writeDigit(1, int(value[1])) | |
self.segment.writeDigit(3, int(value[2])) | |
self.segment.writeDigit(4, int(value[3])) | |
return self | |
# Get the current sound level | |
def get_sound_level(self): | |
# Read data from device | |
l,data = self.inp.read() | |
if not l: | |
return 1 | |
# Return the maximum of the absolute value of all samples in a fragment. | |
value = float(audioop.max(data, 2)) | |
if value < 1: | |
value = 1.0 | |
return value | |
# Main loop | |
def run(self): | |
print "Running the program - press Ctrl + C to exit." | |
time.sleep(2) | |
saved_value = 1 | |
last_changed = time.time() | |
while True: | |
value = self.get_sound_level() | |
red_state = value > self.WARNING_THRESHOLD | |
print "Level: %s; Red: %s;" % (value, red_state) | |
if abs((saved_value - value) / value) > self.TOLERANCE: | |
if time.time() > last_changed + self.MAX_CHANGE_FREQ: | |
self.write_number(value) # Change LCD output | |
GPIO.output(self.RED_LED, red_state) # Light red LED? | |
saved_value = value | |
last_changed = time.time() | |
time.sleep(.001) | |
# Cleanup on exit | |
def __del__(self): | |
self.segment.disp.clear() | |
GPIO.cleanup() | |
# Run the program | |
monitor = SoundMonitor().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment