You are on page 1of 16

Food

Living

Outside

Play

Technology

Workshop

Arduino Audio Input


by amandaghassaei on July 25, 2012 Table of Contents Arduino Audio Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Intro: Arduino Audio Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Step 1: Preparing audio signals for Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Step 2: Prepare audio jack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Step 3: Non-Inverting Amplifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Step 4: DC Offset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Step 5: Simple Analog In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 2 4 6 8 9

Step 6: Sampling rate of ~40kHz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Step 7: Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Step 8: Clipping Indicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Related Instructables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Advertisements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

http://www.instructables.com/id/Arduino-Audio-Input/

Author:amandaghassaei

uh-man-duh-guss-eye-dot-com Currently working for instructables!

Intro: Arduino Audio Input


Send sound into your Arduino. This Instructable will show you how to prepare audio so that it can be sampled and processed by an Arduino to make all kinds of awesome audio projects! Some ideas that come to mind include: beat detection - trigger lighting effects, build a set of turntables that beat match themselves, or make a robot that dances along with the music you play for it amplitude detection - make a simple vu meter with LEDS frequency analysis - you could make a project that reacts to different frequencies in different ways, recognizes certain melodies, turns audio into MIDI data , or translates incoming frequencies into square waves with the tone() library digital effects boxes/digital signal processing - check out what I did with my vocal effects box (all processing done with Arduino), lots of possibilities here: pitch bending, distortion, sampling, delay , reverb , granular synthesis , mixing , and much more... I've provided code in this Instructable that lets you sample at up to 38.5kHz. This article is a companion to another Instructable I've written about getting an Arduino to output audio, find that here . digital recorder - with the addition of an SD card of course (the Arduino has very limited memory by itself), this opens up the possibility of looping large samples and doing lots of other digital manipulations to pieces of stored audio graphical representations of sound - Arduino oscilloscope/visualizer Feel free to use any of the info in this Instructable to put together an amazing project for the DIY Audio Contest! We're giving away an HDTV, some DSLR cameras, and tons of other great stuff! The contest closes Nov 26. Parts list: (x1) Microphone Radioshack 33-3038 (x1) TL072 Digikey 296-14997-5-ND or TL082 Digikey 296-1780-5-ND (TL081/TL071 are fine too) I used a tl082 in my examples (x2) 9V battery (x2) 9V battery snap connector Radioshack 270-324 (x1) mono audio jack 1/4" Radioshack 274-340 or Radioshack 274-252 or 1/8" Radioshack 274-333 or Radioshack 274-251 (x1) LED Digikey C513A-WSN-CV0Y0151-ND (x1) 10kOhm potentiometer linear Digikey 987-1301-ND (x3) 100kOhm 1/4watt resistors Digikey CF14JT100KCT-ND (x1) 10uF electrolytic capacitor Digikey P5134-ND (x1) 47nF ceramic capacitor Digikey P4307-ND (x1) Arduino Uno (Duemilanove is fine too) Sparkfun DEV-09950 Additional Materials: 22 gauge wire solder

Step 1: Preparing audio signals for Arduino


If you've ever recorded audio on your computer, you may have seen it represented as a waveform like the one in fig 1. If you zoom in on this wave (as in fig 2) you will see that the shape is made of thousands of tiny oscillations back and forth. This is called an audio signal and when we are dealing with audio signals in electronics, these oscillations represent oscillating voltages over time. When we look at an audio signal with an oscilloscope , we see a similar picture (fig 3). Notice how the audio signal in fig 3 oscillates around a center voltage of 0V; this is typical of audio signals. The amplitude of an audio signal is the distance between its center voltage and its high or low peak. The amplitude of the wave in fig 3 is 2V: it reaches a maximum voltage of +2V and a minimum voltage of -2V. This is a problem if we want to measure the audio signal with one of the Arduino's analog inputs because the Arduino can only measure voltages between 0 and 5V. If we tried to measure the negative voltages in the signal from fig 3, the Arduino would read only 0V and we would end up clipping the bottom of the signal. In this Instructable I'll show you how you can amplify and offset audio signals so that they fall within this 0-5V range. Ideally you want a signal with an amplitude of 2.5V that oscillates around 2.5V (like in fig 7) so that its min voltage is 0V and its max voltage is 5V (see the calculations below). Min voltage = Center Voltage - Amplitude Min voltage = 2.5V - 2.5V = 0V Max Voltage = Center Voltage + Amplitude Max Voltage = 2.5V + 2.5V = 5V Fig 4 shows the signal coming straight out of the microphone on an oscilloscope. The signal is relatively weak, with an amplitude of only 200mV, you may find that signals

http://www.instructables.com/id/Arduino-Audio-Input/

from other sources (ipods, guitars, record players...) also produce audio signals with small amplitudes. These signals need to be amplified to get them up to the amplitude we want (2.5V). Amplification means increasing the amplitude (distance between the center point and max or min) of a signal. Amplification also buffers the audio source (in my case this was a microphone) from any loads that you may put on it later in the circuit, which is a good thing because it prevents distortion. Fig 5 shows the same microphone signal after amplification, you can see how the height of the peaks has increased so that the wave has an amplitude of 2.5V. But since the center voltage of the wave is still 0, the wave is oscillating between -2.5 and +2.5V. It will need to be DC offset to correct this. DC offset means changing the center voltage that the wave oscillates around (the average voltage of the wave). Fig 6 shows the signal after it has been DC offset; it still has an amplitude of 2.5V, but the center voltage is 2.5V instead of 0V, so the wave never drops down below 0V. (Note- the slight change in shape between the signals in figures 5 and 6 is dues to changes in my voice between the two pics, it has nothing to do with the circuit). The signal in fig 6 is ready to go to an Arduino analog input pin.

Image Notes 1. zoomed in from fig 1 shows individual oscillations of signal

Image Notes 1. 0V 2. volts/div = 2V

Image Notes 1. signal directly from microphone has a relatively small amplitude 2. volts/div = 2V

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. amplified signal oscillates between -2.5 and 2.5 V 2. volts/div = 2V

Image Notes 1. DC offset moves midpoint of signal to 2.5V, now the signal oscillates between 0 and 5V 2. volts/div = 2V

Image Notes 1. microphone mono input 2. amplifier 3. DC offset

Step 2: Prepare audio jack


In this Instructable, I'm only going to talk about how to route one channel of audio into an Arduino. It is possible to copy the same circuit I've proposed here many times to add multiple channels, but it can complicate/slow things down in the code and at some point you will probably have to lower your sampling rate. I'll leave it up to you to figure out the details, but please post what you learn in the comments! Almost all microphones and electronic instruments are mono , meaning they only have one microphone element or pickup which is generating a signal (as opposed to stereo ). You can tell for sure by looking at the plug and comparing it to the image above. My microphone has a 1/4" plug on it so I used a 1/4" jack for this instructable, you may find that you need a 1/8" jack, but the main ideas here still apply. Solder a black wire to the ground pin of the mono jack. The ground pin is usually the larger pin on the jack, test for continuity with the threaded portion of the jack to make sure that you have located the ground pin correctly (see fig 3). Solder a green wire to the signal pin of the mono jack. Test for continuity with the clip that extends out from the jack (fig 3). If you have an oscilloscope handy, connect the reference to the black wire, connect the probe tip to the green wire, plug the microphone in the jack and look for a signal (fig 5). The signal from my microphone has an amplitude of about 200mV.

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. stereo plug 2. mono plug

Image Notes 1. the ground pin will be electrically connected to this portion of the jack 2. The signal pin will be electrically connected to this portion of the jack 3. ground pin 4. signal pin

Image Notes 1. volts/div = 200mV

http://www.instructables.com/id/Arduino-Audio-Input/

Step 3: Non-Inverting Amplifier


The amplifier is the first step in the circuit, it increases the amplitude of the signal from around + or - 200mV to + or - 2.5V (ideally). The other function of the amplifier is to protect the audio source (the thing generating the audio signal in the first place) from the rest of the circuit. The outgoing amplified signal will source all its current from the amplifier, so any load put on it later in the circuit will not be "felt" by the audio source (the microphone element in my case). Do this by setting up one of the op amps in the TL072 or TL082 package in a non-inverting amplifier configuration . The datasheet of the TL072 or TL082 says that it should be powered with +15 and -15V, but since the signal will never be amplified above + or - 2.5V it's fine to run the op amp with something lower. I used two nine volt batteries wired in series to create a + or - 9V power supply. Wire up your +V(pin 8) and -V(pin 4) to the op amp. Wire the signal from the mono jack to the non-inverting input (pin 3) and connect the ground pin of the jack to the 0V reference on your voltage supply (for me this was the junction between the two 9V batteries in series). Wire a 100kOhm resistor between the output (pin 1) and inverting input (pin 2) of the op amp. In this circuit I used a 10kOhm potentiometer wired as a variable resistor to adjust the gain (the amount that the amplifier amplifies) of my noninverting amplifier. Later in this Instructable, I'll show how you can add an LED indicator to Arduino pin 13 to let you know when you have this pot turned up too high (resulting in clipping of the incoming signal by the Arduino); this way you know when you should turn the pot down and get the signal back in the range you want (amplitude of ~2.5V). Wire this 10K linear taper pot between the inverting input and the 0V reference. The following equation describes the relative amplitudes of the signal before and after the non-inverting amplifier: Vout =~ Vin * (1 + R2/R1) or Vout/Vin =~ 1 + R2/R1 where R2 is the feedback resistor (between the output and non inverting input), R1 is the resistor to ground, Vout is the amplitude of the outgoing signal (the output from the amplifier), and Vin is the amplitude of the incoming signal (the input to the amplifier) In this circuit R2 is a 100kOhm resistor and R1 is a 10kOhm potentiometer (variable resistor). By turning the pot you can change the resistance of R1 from 0Ohms to 10KOhms. Here are some example calculations: When the pot is turned all the way to the left the resistance of R1 is 10kOhms and the ratio of Vout to Vin is about: 1+ 100/10 = 11 A signal coming out of the microphone with an amplitude of 200mV (which is fairly loud on my microphone) will be amplified to: 200mv * 11 = 2200mV = 2.2V this is right in the range we want (amplitude close to 2.5V without going over) Turning the pot to its halfway position will give it a resistance of 5kOhms, we can calculate the ratio of Vout to Vin again: 1+ 100/5 = 21 now the amplitude gets multiplied by 21 this is too much amplification for the 200mV signal: 200mV * 21 = 4200mv = 4.2V >> 2.5V but this amplification would be perfect for a 100mV signal: 100mV *21 = 2100mV = 2.1V =~ 2.5V Turning the pot farther to the right will keep decreasing the resistance of R1 and increase the amplification (also called gain ) of this amplifier theoretically to infinity. Obviously at some point the amplifier will not be able to power a signal with a huge amplitude, but you get the idea. By adjusting the potentiometer you can adjust the gain of the amplifier and tune the sensitivity of the microphone while still keeping it in a range that the Arduino likes. Note: As you can see in the circuit above, this project only uses one of the two available op amps in the TL072/TL082 package. I used this chip because they are easily sourced (you can even buy the TL082 at Radioshack these days), they are basically the same price as the single op amp packages (TL071 and TL081), and you may want to use the extra op amp somewhere else on your circuit (another channel of input, an audio out circuit...). But if you have a TL071 or TL081, it will do fine for this project.

Image Notes 1. non-inverting amplifier 2. unused op amp in dual package 3. microphone input

Image Notes 1. signal directly from microphone has a relatively small amplitude 2. volts/div = 2V

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. amplified signal oscillates between -2.5 and 2.5 V 2. volts/div = 2V

Image Notes 1. 9V 2. 0V reference, both audio in ground 10k pot ground connect here. Arduino ground will reference here as well, more info in the next step 3. -9V

Image Notes 1. -9V to 082 pin 4 2. 9V to 082 pin 8 3. signal pin from mono jack to pin 3 of 082 4. ground pin from mono jack 5. battery snaps 6. battery snaps 7. battery snaps 8. 100k bridges pins 1 and 2 of 082 9. 10k pot bridges pin 2 of 082 and 0V reference between two 9V batteries in series

http://www.instructables.com/id/Arduino-Audio-Input/

Step 4: DC Offset
The next portion of the circuit DC offsets the output from the amplifier. As I explained in step 1, this +2.5V DC offset causes audio signal to oscillate around 2.5V so that it stays within the acceptable range for the Arduino's analog inputs (0-5V). Compare the non dc offset signal is fig 2 with the dc offset in fig 3. Specifically, notice how the signal in fig 3 always stays within the 0-5V range. The DC offset circuit has two main components: a voltage divider and a capacitor. The voltage divider is made from two 100k resistors wired in series from the Arduino's 5V supply to ground. Since the resistors have the same resistance, the voltage at the junction between them equals 2.5V. This 2.5V junction is tied to the output of the amplifier via a 10uF capacitor. As the voltage on the amplifier side of the capacitor rises and falls, it causes charge to momentarily accumulate and repel from the side of the capacitor attached to the 2.5V junction. This causes the voltage at the 2.5V junction to oscillate up and down, centered around 2.5V. As shown in figs 3-8 and the schematic, connect the negative lead of a 10uF capacitor to the output from the amplifier. Connect the other side of the cap to the junction between two 100k resistors wired in series between 5V and ground. Also add a 10nF capacitor from 2.5V to ground.

Image Notes 1. DC offset

Image Notes 1. amplified signal- oscillates between -2.5V and 2.5V 2. volts/div = 2V

Image Notes

Image Notes

http://www.instructables.com/id/Arduino-Audio-Input/

1. amplified and dc offset signal- oscillates between 0 and 5V 2. volts/div = 2V

1. to Arduino Vin 2. to Arduino 5V 3. to Arduino A0 4. to Arduino ground 5. 47nF 6. 100k resistors 7. 0V reference- junction between two 9V in series 8. 9V

Step 5: Simple Analog In


Load the following code onto the Arduino. This code reads the voltage of the incoming audio signal using analogRead(A0) as a number between 0 and 1023 and stores it as the variable "incomingAudio." From here you could store this value for later use, perform mathematical operations to it, or do any other manipulations you can think of.
//Simple Audio In //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ int incomingAudio; void setup(){ } void loop(){ incomingAudio = analogRead(A0);//read input from A0 //do stuff with the variable "incomingAudio" }

In the images above I set up a really simple 8 bit digital to analog converter (read more about it here , or check out fig 4) so that I could visualize the data points that the Arduino was storing as the variable "incomingAudio" and see how close it was to the original signal. You can see from fig 2 (zoomed in view of fig 1) that the Arduino is taking one sample every 125us from A0. We can calculate the sampling rate as follows: sampling rate = 1/125us = 1/0.000125s = 8000hz

http://www.instructables.com/id/Arduino-Audio-Input/

To give you a point of comparison, normal audio sampling rates are at least 40kHz. If a sampling rate of 8kHz or less is good enough for your purposes then you should probably go ahead and use analogRead() to measure your signal, as it keeps things very simple. You can see in fig 1 that it actually does a pretty good job of tracing out the path of the incoming 360hz signal. In order to get above 8kHz, we'll have to bypass the analog read function. It may sound daunting, but it's actually not too bad, just a matter of copying some setup() code that I've written in the next step. I also want to point out the behavior of the Arduino in response to a signal that rises over 5V and dips under 0V. In fig 3 you can see how the Arduino clips the incoming signal so that it is always bounded by 0 and 5V. This causes the tops of the peaks and the bottom of the valleys to get flattened. In step 8 I'll talk some more about this and how to set up a clipping indicator light to let you know to turn the amplifier down. Some notes about the 8 bit digital to analog converter (DAC): I used the command "PORTD = " to send a value between 0 and 255 out of the Arduino and into the DAC where it is converted back into a voltage between 0 and 5V. The code I used can be found below. I've written a whole instructable about the 8 bit DAC here .
//Simple Audio In w output to 8 bit DAC //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ int incomingAudio; void setup(){ for (byte i=0;i<8;i++){ pinMode(i,OUTPUT);//set digital pins 0-7 as outputs (DAC) } } void loop(){ incomingAudio = analogRead(A0);//read voltage at A0 incomingAudio = (incomingAudio+1)/4 - 1;//scale from 10 bit (0-1023) to 8 bit (0-255) if (incomingAudio<0){//deal with negative numbers incomingAudio = 0; } PORTD = incomingAudio; }

Image Notes 1. input to A0 shown in yellow, data stored in Arduino (subsequently output from 8 bit DAC) shown in blue 2. volts/div = 2V 3. time/div = 500us

Image Notes 1. one sample each ~125us 2. tims/div = 100us 3. volts/div = 2V

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. when input signal (yellow) drops below 0V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 2. when input signal (yellow) rises above 5V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 3. volts/div = 2V 4. time/div = 500us

Image Notes 1. signal out from 8 bit R2R DAC 2. resistor ladder digital to analog converter (DAC)

Step 6: Sampling rate of ~40kHz


In the code below I bypassed the function analogRead() in order to increase my sampling rate. The code required to do this is fairly advanced, maybe it can be the subject of another instructable if there's interest (leave a comment if you are interested), but for now it's only important to understand how to use this code in the loop() function, not how I set it up. Here's simple explanation (all you need to know for now): Basically in the setup() function I've told the Arduino that I want it to continuously measure pin A0 and forget about the other analog inputs all together. So while other things are going on in the loop() function, the Arduino is constantly updating a variable called "ADCH" with new values from A0 at a rate of 38.5kHz (that's one sample every 26us, you can see it in fig 2). When I want to get one of these values I can just set a variable equal to ADCH, or as I wrote in my code: incomingAudio = ADCH; I did have to lower the resolution of these analog measurements a little bit to get a higher sampling rate. In the last step we were using analogRead() to measure the voltage of the signal as a value between 0 and 1023, now these values will always be between 0 and 255. Also, continuous monitoring of A0 means that the other analog pins are now useless, but if you really need to measure a potentiometer or sensor, check out how you can do it with a digital pin using RCTime It's possible that the analog pins can still be used as digital I/O pins, but I haven't actually tested this yet, leave a comment if you try it! The complicated explanation (not necessary, but for those who are interested): I manually set the Arduino's internal analog to digital converter (ADC) counter to 500kHz and read an 8 bit value from analog input 0 from the ADCH directly (I just read the most significant 8 bits of the 10 bit ADC to save time in the code). I set the ADC counter to 500kHz because the ADC takes 13 clock cycles to read a new analog value. 500/13 =~ 38.5kHz which gets me pretty close to 40kHz (standard audio sampling rate) without introducing extra noise. As you can see in fig 2, this gives me one sample every 13/500000 = 26us. A lot of the ideas here (prescalers and counters) are similar to the setup for Arduino timer interrupts, and you can read more about how that works here .
//Audio out with 38.5kHz sampling rate //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ int incomingAudio;//storage for A0 data void setup(){ //set up continuous sampling of analog pin 0 (you don't need to understand this part, just know how to use it in the loop()) //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA ADCSRA ADCSRA ADCSRA |= |= |= |= (1 (1 (1 (1 << << << << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADATE); //enabble auto trigger ADEN); //enable ADC ADSC); //start ADC measurements

//if you want to add other things to setup(), do it here } void loop(){

http://www.instructables.com/id/Arduino-Audio-Input/

incomingAudio = ADCH;//get new value from A0 //do other stuff here }

As in the previous step, I sent the values of the variable "incomingAudio" out an 8 bit DAC so that I could visualize the data as it was being stored in the Arduino. You can see the incoming signal (yellow) and output from the DAC (blue) in the images above. Notice how much better the Arduino follows the signal compared to the last step. In fig 2 you can see that the step size is down to 26us (compared to 125us when using analogRead). Again you can see the effects of clipping at 0V and 5v in fig 3. The code for sampling rate of 38.5kHz with DAC output is given below.
//Audio out with 38.5kHz sampling rate and DAC output //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ void setup(){ for (byte i=0;i<8;i++){ pinMode(i,OUTPUT); } //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA ADCSRA ADCSRA ADCSRA } void loop(){ PORTD = ADCH;//send 8 bit value from analog pin 0 to DAC } |= |= |= |= (1 (1 (1 (1 << << << << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADATE); //enabble auto trigger ADEN); //enable ADC ADSC); //start ADC measurements

Image Notes 1. volts/div = 2V 2. time/div - 500us 3. input to A0 shown in yellow, output from Arduino D0-D7 in blue

Image Notes 1. one sample every 26us 2. time/div = 25uS 3. volts/div = 2V

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. when input signal (yellow) drops above 5V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 2. when input signal (yellow) drops below 0V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 3. volts/div = 2V 4. time/div = 500us

Step 7: Interrupt
In this piece of code, I set up the Arduino to continuously monitor pin A0 at 38.5kHz, but now I've added a piece of code that automatically updates the variable "incomingAudio" each time a new value from A0 has been calculated. Instead of putting the line: incomingAudio = ADCH; in the loop() function of the Arduino sketch, I've put it in a special function called an "interrupt routine." The interrupt routing looks like this: ISR(ADC_vect) { incomingAudio = ADCH; } Think of it as a normal sketch, the Arduino first goes through the setup() function then it starts the loop(), but every 26us (when a new value is ready from A0) the Arduino stops what it is doing in the loop and does whatever is encapsulated in the interrupt routine (in this case just the line "incomingAudio = ADCH;"). Once the interrupt routine has finished, the Arduino picks up again where it was in the loop() for another 26us. Then the interrupt routine executes again.... this goes on repeating forever. If you want, you can read more about Arduino interrupts here . This interrupt code generally a better way of reading the incoming signal than the way I wrote it in the last step because you are only updating the variable incomingAudio once each time a new value comes in. Updating the variable multiple times, before the value has even had time to change is redundant. Also, if you want to record these values you can put the storage code in the interrupt routine so you know that your storage sampling rate is exactly 38.5kHz.
//Audio out with 38.5kHz sampling rate and interrupts //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ int incomingAudio; void setup(){ cli();//diable interrupts //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA ADCSRA ADCSRA ADCSRA ADCSRA |= |= |= |= |= (1 (1 (1 (1 (1 << << << << << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADATE); //enabble auto trigger ADIE); //enable interrupts when measurement complete ADEN); //enable ADC ADSC); //start ADC measurements

sei();//enable interrupts } ISR(ADC_vect) {//when new ADC value ready incomingAudio = ADCH;//update the variable incomingAudio with new value from A0 (between 0 and 255) }

http://www.instructables.com/id/Arduino-Audio-Input/

void loop(){ //do other stuff here }

Step 8: Clipping Indicator


A clipping indicator LED is useful so that you know if you need to turn the gain down on your amplifier. If your signal is clipping as it comes into the Arduino, you are losing information about the signal. Figs 2 and 3 show the incoming signal (yellow) and the data stored in the Arduino (blue) for both 8kHz and 38.5kHz sampling rates. Notice how the Arduino completely misses the behavior of the peaks and valleys due to clipping. To set up the clipping counter I created a few new variables. "clipping" has a state of 1 when the Arduino detects clipping (the incoming signal is measured to be 0 or 5V) and a state of 0 when the Arduino does not detect clipping. In the code below (for 8kHz sampling rate) I also set up a variable called clippingCounter. The purpose of this variable is to keep the indicator LED on for a moment after the clipping was detected so that it is visible to the human eye. In the 38.5kHz code (at the bottom of this step) I used a delay(100) to achieve the same effect.
//Simple Audio In with clipping indicator //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * */ int incomingAudio; boolean clipping = 0;//zero = not clipping, one = currently clipping int clippingCounter = 5000; void setup(){ } void loop(){ incomingAudio = analogRead(A0);//read input from A0 //do stuff with the variable "incomingAudio" if (incomingAudio == 0 || incomingAudio == 1023){//if clipping digitalWrite(13,HIGH);//set pin 13 high clipping = 1;//currently clipping clippingCounter = 5000;//reset clippingCounter } if (clipping){ if (clippingCounter>0){ clippingCounter--;//decrement clipping counter } else{//if clippingCounter has counted all the way down clipping = 0;//no longer clipping digitalWrite(13,LOW);//turn of clipping indicator } } }

and below is the code for 38.5kHz with interrupts:


//Audio in with 38.5kHz sampling rate, interrupts, and clipping indicator //by Amanda Ghassaei //http://www.instructables.com/id/Arduino-Audio-Input/ //Sept 2012 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version.

http://www.instructables.com/id/Arduino-Audio-Input/

* */ //variable to store incoming audio sample byte incomingAudio; //clipping indicator variables boolean clipping = 0; void setup(){ pinMode(13,OUTPUT);//led indicator pin cli();//diable interrupts //set up continuous sampling of analog pin 0 //clear ADCSRA and ADCSRB registers ADCSRA = 0; ADCSRB = 0; ADMUX |= (1 << REFS0); //set reference voltage ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only ADCSRA ADCSRA ADCSRA ADCSRA ADCSRA |= |= |= |= |= (1 (1 (1 (1 (1 << << << << << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz ADATE); //enabble auto trigger ADIE); //enable interrupts when measurement complete ADEN); //enable ADC ADSC); //start ADC measurements

sei();//enable interrupts } ISR(ADC_vect) {//when new ADC value ready incomingAudio = ADCH;//send 8 bit value from analog pin 0 to DAC if (incomingAudio == 0 || incomingAudio == 255){//if clipping digitalWrite(13,HIGH);//set pin 13 high clipping = 1;//currently clipping } } void loop(){ if (clipping){//if currently clipping clipping = 0;// digitalWrite(13,LOW);//turn off clipping led indicator (pin 13) } delay(100); }

Image Notes 1. when input signal (yellow) drops below 0V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 2. when input signal (yellow) rises above 5V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 3. volts/div = 2V 4. time/div = 500us

http://www.instructables.com/id/Arduino-Audio-Input/

Image Notes 1. when input signal (yellow) drops above 5V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 2. when input signal (yellow) drops below 0V the Arduino clips it as it measures it. This clipping is reflected in the outgoing signal from the Arduino (blue) 3. volts/div = 2V 4. time/div = 500us

Related Instructables

Arduino Vocal Effects Box by amandaghassaei

Lo-fi Arduino Guitar Pedal by kylemcdonald

Audio Delay Module by LargeMouthBass

Girino - Fast Arduino Oscilloscope by Caffeinomane

The Talking USB Headphone Breathalyzer Hack! by Mark II by babblin5 EngineeringShock

Advertisements

http://www.instructables.com/id/Arduino-Audio-Input/