Go Down

Topic: Circuit interface for speaker level audio into ADC (Read 6117 times) previous topic - next topic


I am hoping this has not been covered already in the fourm.  I have searched the forum and Googled for some info but wanted to validate my thoughts and get some feedback with the forum.

Project at a high level:
I want to take the audio signal from a transceiver (the AF component of a demodulated signal) feed it through an interface into the ADC input of Arduino.  From there I want to FFT or Goertzel the audio signal to detect single series of tones (2/5/6 Tone SelCall).  When the correct set of tones is received, I want to use one of the output data pins to go high to turn on a transistor to act as a switch.

The detail I am looking for is in the interface to the ADC.  I understand there are two types of levels; line level and speaker level.  From what I can read line level is typically +/- 2.2 volts max.  Speaker level is higher than this (as it is often the output of an amp).  For line level I can use the interface described by;

For speaker level what is the best method of controlling the voltage in the interface circuit?  Apart from using a 10K pot and attenuating the speaker level signal (with a relatively fixed value), could I use an automatic gain control (AGC) type circuit?  What would be the best approach to this so I don't overload the ADC pins?

I was thinking if I use an AGC, I don't have to have a fixed output from the transceiver, and don't have to have a fixed attenuation resistor.  This gives me the flexibility of using the project as a modular device and interfacing with different types of tranceivers.

Any advice, guidance comments are really appreciated!!

BTW: I am new to circuit design, understand most of the theory and not new to software development.


Thanks KE7GKP,
Appreciate your feedback.  I'm curious - apart from providing line isolation via coupling, would the transformer provide some sort of a buffer for voltage transients?

I guess it is going to be one of trial and error things?  I have very limited test equipment so I think I will have to just build the circuit and place in a limiting resistor on the ADC input as a safety measure.  Gradually reduce the resistance until I am comfortable with the results.




Either my interpreation of the circuit is incorrect or the simulator doesn't calculate values correctly.

It is your interpretation.


My mistake.

Appears simulator is correct - I walked away from the computer and leaving it run - the bias adjusts correctly.  There appears to be quite some lag between changes of the pot and variation in the 'scope'

Thanks Grumpy_Mike.

Guess I'm just impatient these days and expect instant results ;-)


There appears to be quite some lag between changes of the pot and variation in the 'scope'

That is due to the idealised low impedance of the voltage generator and the low speed the simulator is running at. Remember "sluggish" relative to how many cycles, that is slower as well.  :)


So..  I have had a bit more time to connect an interface to my Arduino UNO and I have the following setup:

I have the biasing voltage configured to 0.55 volts, I am using the internal reference voltage of 1.1 for the ADC,  have an 8 bit sample resolution and trimming shows the value to be 128.  That is a good start !

I created a single tone of 1981Hz (Digit 0 of a CCIR tone) with Audacity at 95% amplitude for duration of 20 seconds.

Using the headphone socket of my PC, I connected that to my audio interface into the Arduino, turned it on and ramped up the volume while echoing the ADC value to a line print.

I noticed a whopping deviation of +/- 2 units (126 - 130).  So from my quick calculation I get a peak to peak value of 17mV at full scale volume.

So out of interest I tested with a DMM set to AC and observed a value of 700mV.  Now I know a DMM is probably the worst tool for this purpose, but without a CRO it is all I could think of.

Where are my assumptions going awry?  Is 17mV an expected value from an audio signal out of a headphone socket at full volume...  or should I be expecting something around 700mV and my Arduino code is at fault?

Sorry for the newbie questions..


When you plug in your headphones, can you hear a sound? If you do, you can estimate voltage level, with 16 Ohm it definitely should be more than 17 mV.
Or other option, try to load this scetch http://oscilloscopeexpress.blogspot.com/ and see what you can get on console screen.


Thanks for your post magician.  That will hopefully help me out quite a bit.  This is my first circuit build with audio.

@KE7GKP points taken ;-).  So..  my assumption is that this code works and the functionality of sampling has not been completely butchered.

Code: [Select]
/* Derived from:
* http://interface.khm.de/wp-content/uploads/2008/10/arduino_audio_loopback.zip
* Arduino Audio Loopback Test
* Arduino Realtime Audio Processing
* 2 ADC 8-Bit Mode
* analog input 1 is used to sample the audio signal
* KHM 2008 / Lab3/  Martin Nawrath nawrath@khm.de
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

boolean div32;
boolean div16;
// vars altered by interrupt
volatile boolean f_sample;
volatile byte badc0;
volatile byte badc1;
volatile byte ibb;

int ii;
unsigned int iSampleSet[511];

void setup()
  Serial.begin(57600);        // connect to the serial port
  Serial.println("Arduino Audio Loopback");

  // set adc prescaler  to 64 for 19kHz sampling frequency
  cbi(ADCSRA, ADPS2);
  sbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);

  sbi(ADMUX,ADLAR);  // 8-Bit ADC in ADCH Register
  /*sbi(ADMUX,REFS0);  // VCC Reference 5.v
  sbi(ADMUX,REFS0);  // Internal AREF Reference 1.1v
  sbi(ADMUX,MUX0);   // Set Input Multiplexer to ADC Channel 1

  // Timer2 to normal mode - no PWM
  cbi (TCCR2A, COM2A0);
  cbi (TCCR2A, COM2A1);
  cbi (TCCR2A, WGM20);
  cbi (TCCR2A, WGM21);

  cbi (TCCR2B, WGM22);

  // Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  //cli();                         // disable interrupts to avoid distortion
  cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay is off now
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt
  Serial.print("ADC offset=");     // trim to 127


void loop()
  while (!f_sample) {         // wait for Sample Value from ADC
  }                           // Cycle 15625 Hz = 64uSec

  // loop to fill a 512 element array with ADC samples
  // 512 * 64uSec = 32.768 mSec
  for (int i=0; i < 512; i++) {     
    iSampleSet[i]=badc1;                // load sample into u_int array

  for (int i=0; i < 512; i++) {     
    Serial.println(iSampleSet[i]);      // echo values of array elements
} // loop

// Timer2 Interrupt Service at 62.5 KHz
// here the audio is sampled in a rate of:  16Mhz / 256 / 2 / 2 = 15625 Hz
// runtime : xxxx microseconds
ISR(TIMER2_OVF_vect) {

  PORTB = PORTB  | 1 ;

  div32=!div32;                      // divide timer2 frequency / 2 to 31.25kHz
  if (div32){
    div16=!div16;  //
    if (div16) {                     // sampled with 15.6kHz
      //sbi(ADMUX,MUX0);               // set multiplexer to ADC channe1
      badc1=ADCH;                    // get ADC channel 1
    //alternate 15.6 Khz cycle
    ibb++;                          // short delay before start conversion
    sbi(ADCSRA,ADSC);               // start next conversion


Schematic attached.
Parts list:
R4 15K
R1 100K
R2 10K
R3 15K
C1 4.7nF
C2 10uF


Forgive my ignorance as I appreciate your advice.  At 2000Hz, I calculate C1 to provide approx 17Kohm of reactance to ground path, would that still be considered 'short'.  Should I be looking at something like 470 pF ~ 170Kohm reactance?



I look at yours schematic, if you want a audio signal into the analog pin, I will use a simple commun emitter transistor circuit. 

Look at this site. http://www.st-andrews.ac.uk/~jcgl/Scots_Guide/experiment/lab/expt5/page1.html

And look at the transistor circuit... Just use Rb1 about 100K to 470 K, delete Rb2, use C1 a 10uF - neg side of the cap toward the input, delete Re, Rg and Ce and connect E - emitter to GND, use Rc about 1 K to 4.7 K. And connect the analog pin at C - collector, delete C2.

So in my schematic, use Rb 100 K <>470 K    C  1 uF <> 10 uF  Rc 1 K <> 4.7 K . Just experiment to see what happen.  The signal  will at the output of the transistor from 0 V to 5 V , if the input signal is too strong... it will simply become a "square wave".

I will do that circuit if I want a audio signal into the Arduino.


Thanks KE7GKP,
Pulled out C1 and got more deviation, but only marginal.  At full scale, over 512 samples I see deviation of +/- 10 units ~ 85mV p-p.  Not quite what I expected.

@Magician - ran your sketch no mods - at the slow end of the sampling, I can see the waveform (thank you), with p-p measure of 160mV. 

I think the audio interface circuit is not optimal for my purpose, I am expecting a lot more deviation so I can perform an FFT with a decent range of magnitudes.  Results are going to be pretty ordinary when sampled with brown noise background.

@Techone, thanks will review your info.



I just come across a schematic using a single supply  using an op-am instead of a transistor...same idea. The circuit came from EPE October 1993. I copy it into a sheet. Sorry for the "napkin" drawing.


Problem with that circuit is that it has a gain of 1 so there is no voltage amplification.
You need to use a larger value of feedback resistor to get anything other than a unity gain.

Also you need a capacitor across the two 1K resistors forming the virtual ground at the +ve input to the amplifier.



I know about the gain is 1. you simply change Ri and Rf   Gain = - ( Ri / Rf ) My drawing is  an example.

Also you need a capacitor across the two 1K resistors forming the virtual ground at the +ve input to the amplifier.

In my napkin, all resistors are 10 K. You mean a cap // with R1 and a cap // with R2 ? Right ? And I am assuming the cap value is about 1 uF to 10 uF ?

Anyway, I am trying to help, because sending an audio signal DIRECTELY into the analog pin is a BAD Idea.  Both circuits will "lift" the signal above the 0 V - GND line and place in between 5 V and GND ( at 2.5 V point is ideal ) so the analog pin of the Arduino can manage.   

Go Up