Lab 8: The Clapper

The questions below are due on Sunday July 29, 2018; 11:59:00 PM.


You are not logged in.

If you are a current student, please Log In for full access to this page.

Goals:

In today's lab we're going to add in a sound transducer circuit (a microphone) along with a preamplifier. First we'll use this signal to just amplify our own voice (by hooking it up directly to the input of our audio amplifier (so if you took that apart, go back and reassemble it). Then we're then going to use the signal generated by our microphone to create a sound-sensitive system that turns on different LEDs. If you finish early, then you should build an actual double-clap clapper system.

1) Microphone Circuit

We've been trying to emphasize the theme of common, repeated circuit topologies in this class. Our friend the voltage divider:

The voltage divider. I'm getting sick of putting this image in.

We can slightly modify the voltage divider by adding in other components in place of one (or both) of the resistors:

Turning a regular old voltage divider into a sensor system!

We've dealt with several of the four sensor circuits above. The switch we've dealt with in several locations, the light sensitive circuit (or a variant of it) we dealt with in Lab 06. Today we're going to be dealing with a sound-sensitive version of the circuit.

We'll be replacing the bottom resistor in a voltage divider with an electret microphone element like shown below:

A microphone circuit

The microphone element looks like the following image.

A real, live microphone

Direction is very important when hooking up the mic (though not in the things will blow up sense...just that it won't work), so you need to pay attention to which pin on the element goes to ground.

Watch the pins

2) Pre-Amp

The voltage out of the voltage divider will vary with the sound hitting the microphone. But the deviation in voltage based on a given sound signal is no much...so what we're going to do is add some "pre-amplification" (meaning) boost the signal up before (pre) we use it. To do this we'll be using an operational amplifier:

The MCP6002 Op Amp

The insides of the MCP6002

The actual preamplifier circuit will make use of the op amp in the following circuit (known as a inverting amplifier). This circuit takes in the signal (an analog signal) from the microphone voltage divider circuit, and amplifiers it by a factor based on the resistor values.

A preamplifier

In particular the gain of this circuit is proportional to the ratio of resistor R5 over R4 or:

A_{pa} = -\frac{R_5}{R_4}

3) Loudspeaker/Megaphone

Build the microphone and preamp circuit above. To test it out we're going to wire the output of it to the input of the audio power amplifier you built (and were using throughout) Labs 03, 04, 05, etc... When doing this you should end up with a circuit that amplifiers whatever sound that goes into it. If you put too much signal in, or have the speaker facing towards the microphone you can get some really nice positive feedback (microphone drives the speaker electrically...speaker drives the microphone audibly,...at greater and greater levels!)

A megaphone-like circuit

Build this circuit and make sure it is working. Test out some feedback by messing with the gain of your audio amplifier and the position of your speaker/microphone like shown:

4) Reading in Signal

Now what we want to do is feed that audio signal into our analog-to-digital converter (ADC) that we built up in Lab06: (you can disconnect the preamp output from the audio amplifier input now.):

Build the following:

Feeding the signal into the Raspberry Pi courtesy of the MCP3008

Make sure your MCP3008 and your audio amplifier are still working by running the hardware check(s) below to make sure your Raspberry Pi is still talking to your MCP3008!

5) Signals

Now that your system is working, let's use our microphone. Run the simple code below which just prints out the readings of the microphone signal. It might be good to have an easier way to visualize this signal so in order to do that change the graphic variable at the top of the file to True. All this does is print out a bunch of * symbols rather than the actual numbers which can often times help us simple humans see the patterns easier.

import time
import spidev


spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 2000000

graphic = False

#don't change the function below
def readChannel(channel):
    adc = spi.xfer2([1,(8+channel)<<4,0])
    data = ((adc[1]&3) << 8) + adc[2]
    return 3.3*data/1024

while True:
    val = readChannel(0)
    if graphic:
        out = "".join("*" for x in range(int(30*val)))
        print(out)
    else:
        print(val)

If we were to instead plot these values out you'd get images like the following...a plot of me snapping my fingers is shown below as an example:

Try and experiment with different sounds. You may need to speak somewhat loudly to get a good signal since we're not really amplifying the microphone's signal here. Here's two other sounds (my voice):

What you should see from this is that, unlike with the photoresistor where a stimulus change resulted in a difference in steady-state value (more darkness lowered the resistance, thus lowering or increasing voltage, etc...), sound by its inherent wave-like nature results in a "wiggle" or non-steady-state signal. If we want to process it or act upon it we might need to do more processing/computation on it than just a simple > or < comparison like we could with light.

6) Your Assignment: The Clapper

So what should you do with this? Well, you may be too young to remember, but television used to be filled with commercials for a device known as The Clapper. It was basically a device that would turn on and off electronic devices based off detecting claps. It was really stupid and if it hasn't already been used as a metaphor in some postmodern or post-postmodern novel, I'm sure it will be eventually.

Anyways....

Your job is to build one of those....

You'll have three LEDs:

  • LED One should be connected from GPIO Pin 4 to ground
  • LED Two should be connected from GPIO Pin 17 to ground
  • LED Three should be connected from GPIO Pin 27 to ground

Your system should work as follows:

  • When the code starts both LED 1, 2, and 3 are off
  • When you clap your hands (once) LED 1 should turn on
  • When you clap your hands again (also once) LED 1 should turn off and then LED 2 should turn on
  • When you clap your hands again (also once) LED 2 should turn off and then LED 3 turns on
  • When you clap your hands again (also once) LED 3 should turn off and then none should be on
  • If you clap your hands again, the system should restart (so LED 1 turns back on, etc...)

There is a starter code chunk of code below which you can coppy-paste. All it does as handed to you is just run an infinite loop of channel Readings (on the MCP3008 Channel 1 input which is where your microphone should be hooked up!) and print them...you'll see lots of numbers fly by and if you look closely you should see slight deviations in those numbers as you tap or blow on the microphone.

You should also seriously consider using the code above to get an idea of what the pattern/duration/shape of a clap is and use that to guide your design. I want this thing actually working...not like sorta working.

import time
import pygame
import os, os.path
import spidev
import wave

import RPi.GPIO as GPIO
GPIO.setwarnings(False)

GPIO.setmode(GPIO.BCM)

pins = [4,17,27]
#is running LED:
GPIO.setup(4,GPIO.OUT)
GPIO.setup(17,GPIO.OUT)
GPIO.setup(27,GPIO.OUT)

spi = spidev.SpiDev()
spi.open(0,0)
spi.max_speed_hz = 2000000


def readChannel(channel):
    adc = spi.xfer2([1,(8+channel)<<4,0])
    data = ((adc[1]&3) << 8) + adc[2]
    return data

GPIO.output(4,0)
GPIO.output(17,0)
GPIO.output(27,0)

state=0

###################
##################
readings = []
for x in range(100):
    readings.append(readChannel(0))

#calculate background value: 
ambient = sum(readings)/len(readings)

def state_to_led(state):
    #your code here
    pass

try:
    while True:
        mic_signal = readChannel(0)
        #your code here!
        
except KeyboardInterrupt:
    GPIO.cleanup()

For starters try to write some code to get your LED on pin 27 to turn on when sound is above a certain value. Experiment with thresholds, absolute values,and time.sleep delays. What you may find is that your system responds to sound...but responds too much...so like when you clap...it flashes through the LEDS several times....this is going to happen because your system is too quick...it sees the single clap sound as several "triggers" and responds until they go away. How could you fix this?

Remember you can set GPIO outputs like so:

GPIO.output(23,1) # to turn pin 23 HI
GPIO.output(23,0) # to turn pin 23 LO

and you can get the analogReadings you need (coming in in terms of bit values) via:

readChannel(0) #reads channel one on the MCP3008 which is where your microphone should be hooked up.  This will give you back the value read at that output in volts!!!

You'll probably really want to use the time.sleep function which takes in a single argument of time to sleep (in seconds). You may also find the time.time() command useful. This gives you the absolute amount of time since the Unix time (the number of seconds that have elapsed since midnight on January 1, 1970) to microsecond accuracy. This is a useful function to use for timing purposes. For example to figure out how long somethign takes you can do:

start = time.time()
#do stuff here
#do more stuff
stop = time.time()
print(stop - start) # will print the amount of time (in seconds with six places of precision) between the two time.time() calls

I've included a brief discussion on some of these thoughts at the youtube link here.

When done you should have something like this:

7) Pattern Recognition

So your system should be able to recognize claps now and change LEDs on and/or off based of that. However, truth be told, any loud sound would trip your system. If you yell into the mic loud enough, your system will think it is a clap.

Can you have your system light one LED if it hears one clap, and light the other LED if it hears two claps (in somewhat quick succession)? Or can you have it work like the actual clapper and only respond to two claps that occur within a short period of time of one another? This is really nothing more than a "double-click" of sound events, so if you want, you should be able to do this! This is a very basic example of pattern recognition, but the ideas that go into getting this part of the lab to work are the same fundamental ones that go into getting Siri, Cortana (the knockoff one from Microsoft or wherever), or Amazon's recently released Alexa.

So next, try and modify your code so that it can recognize one or two claps. Your approach should be somewhat similar to before (the idea of states should really help), but try to think of what you as a human would do when trying to determine if one or two claps has taken place.

8) Deliverable

Upload your code demonstraing sharp noises cycling the lights. Make sure your code is not too sensitive!

Enter the url for the video

Place all of your code into a folder and zip it up before uploading here:

 No file selected

Enter any comments you may want me to know about. For example, you can list non-obvious things you got working, things you're proud of, outstanding issues, etc.. Please hit submit on this question even if you don't have any comments.