Problems with simple headphone level audio detection

Inspired by, among others, this project I wanted to use an Arduino to detect whether a device with is playing audio or not. Currently, the device is my Android phone, but I potentially want to use this on other devices outputting sound through a 3.5mm plug.

I've made this simple circuit:

with this corresponding simple code:

int sensorPin = A0;   
int sensorValue;

void setup() {
Serial.begin(9600);
}

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);    
  Serial.println(sensorValue,DEC);     
  delay(250);
}

My problem is that whether I play music or not, the Arduino only outputs zeros. I've tried several variations without much luck:

  • Without the capacitor
  • Without the resistor
  • With resistor values between 10 Ohm and 10k Ohm

If I unplug my headphones however, I'm able to detect some low values (max ~25). It appears that the signals are to weak (possibly low voltage?) for the Arduino to detect.

Does anyone have a (preferably simple) circuit I can use to detect whether music is playing from my 3.5mm audio devices?

Do not. You can't drive PA output to arduino input w/o risk to damage it, even from the headphones line. For minimal safety precaution, set resistor 10 k in series with A0. But check first, if it's still alive, connecting to on-board 3.3V and see if readings make any sense.

A0 outputs 0 when connected to ground, 669 when connected to 3.3V and 1023 when connected to 5V (all through 10k resistor) so that makes sense. If I can't connect the signal directly to the Arduino analog input, is there any IC or circuit I can use in between?

Are you trying to replicate what this man from instructables (wrongly) did, just to check if there is NO signal at specified period of time?
Or you need actually measure the level, like VU meter?

A simple audio/no audio detection is sufficient. The goal is to detect which source is playing audio and direct this (probably using relays) to my amplifier.

In.1 ----------------^^^^^(R 10 k) --------------analog in.
|

< R 10 k

|
Gnd-------------------------------------------------arduino ground.

First resistor (in series) to protect input against negative, or over voltage. Second to recharge an output cap if there is any at the output of your signal source. Repeat this circuit how many inputs you have. Than in software you need to read analog input periodically (1, 10 sec) continuously for 50 millisec (20 Hz minimum freq. audio), approximately 500 analogRead, because there is a 50/50 chances you could read during negative halfwave and get "0". Don't have to store any of this 500, just check on maximum value and compare after with pre-set threshould.

Looking at the specs for a pair of Apple in-ear headphones, I find this:

Impedance (at 100Hz): 23 ohms
Sensitivity (at 100Hz): 109 dB SPL/mW

109 dB is very loud - the CDC lists the permissible occupational exposure time at that level as under two minutes. So, unless you like it really loud, that would be a reasonable upper limit.

The calculation for voltage, using V^2/R = P, gives about 0.15V for a milliwatt into 23 ohms; assuming a sinusoidal input, the peak voltage at that RMS level is about 0.21V. That corresponds to an ADC output of about 43 using 5V as Aref. If all this is correct, then I'm not surprised that you read a peak of something like 25 from the ADC. I think that the voltage of the headphone output of a personal audio device is pretty low.

For this application, I'd recommend driving the analog input with an op-amp, powered from 5V and GND, with the signal capactively-coupled to the inverting input; biasing the inverting input at 2.5V, with either a high-impedance resistive divider, or a 2.5V reference IC and a high-value resistor, which will be less noisy; tying the non-inverting input to 2.5V, and picking the input and gain resistors to make it work - I think that's something of a trial and error effort. That'll give an ADC reading that swings back and forth around mid-scale, with a swing that's set by the op-amp circuit; you can use the differences between recent maxima and minima to decide whether the music is on. With the op-amp powered from the Arduino's own supply, you needn't worry that the analog input will swing outside the allowable range. You'll get wider swings with a rail-to-rail op amp than with a general purpose op-amp. And, of course, your op amp needs to operate at a supply of 5V.

A series resistor between the headphones and the input capacitor will help protect the circuit from unexpected excursions on the input. A couple of signal diodes in parallel would limit excursions to about 0.7V at the capacitor - I'd test that, though, to make sure that they don't give you noticable distortion on the signal at the listening levels you like.

Google "op amp" "single supply" to see some a lot of representative circuits. If op-amps aren't your forte, well, you'll want to learn to use them if you hope to play with audio interfaces.

Some warnings:

  • The dynamic range of music content is huge - a reasonable expectation of the range might be 60 dB, making the input voltage vary by a factor of 1,000. It's unlikely that you'll be able to detect soft passages with any reliability. You can alleviate this by setting the op-amp gain really high, and letting it clip for louder passages; and by requiring a considerable delay before you decide that there's no music. You don't really care that the analog input is accurate.
  • The headphones seem to load the output considerably - you read nothing with them connected, and 25 or so without them. The circuit is more likely to detect music when the headphones are disconnected.

Finally - I don't see that the capacitor and resistor in parallel with the input are helping anything. They'll just reduce the signal, though - if their values aren't too unreasonable - not by much.

Thanks, both of you! Not much luck with simple circuits so I guess I'll have to start looking into op amps...

According to this site Droid output voltage test (and a few signal generator apps) | DIYMobileAudio.com Car Stereo Forum
the level is quite high to be easily detectable.
Post 10 here What is Voltage Output of iPod Headphone Jack? | Headphone Reviews and Discussion - Head-Fi.org
states 1.1 V
Don't have android , can confirm this.
In my opinion, there are two possibilities:

  1. You wire it up with wrong polarity, or ground wire mistake.
  2. android has sensor "headphones disconnected" to save power turning off PA, as it portable devise.
  • Edited:*
    If you don't have oscilloscope or voltmeter, try to connect phone output to line-in on your PC sound card. There is a lot of free software (audacity etc.) that turning sound card in high-tech audio-lab

Magician:
Post 10 here ... states 1.1 V

Indeed, and it was probably correct. But, 1.1V is the maximum output of the iPod. The circuit here is intended to detect music rather than test tones, and, because it has headphones connected, I think it's not unreasonable to presume that someone will listen to those phones.

Using the numbers for the Apple in-ear headphones - 23 ohms, 109 dB SPL/mW - I calculate 126 dB SPL at 1.1V RMS. That's extremely loud. I don't think that we can expect anybody to listen at that level just to make things convenient for his music detector circuit. I think that we could maybe hope for a level of 85 dB, which translates to a voltage of about 10mV RMS, with a peak-to-ground voltage of about 15 mV, and a peak-to-peak of 30 mV. That's about 13 ticks on the ADC single-ended, and 26 ticks of swing, with the band-gap as Aref. That's a lot less than 1.1V, but it seems to be doable, if the noise at the ADC input is low enough.

But, 85 dB is still loud. It wouldn't be at all unreasonable to expect that the listening level could be 70 dB or lower, which would correspond to a voltage of only about 1.7mV - about 3 ticks of swing with the 1.1V reference, and one or two ticks single-ended. That would be hard to detect reliably. I think we're still stuck with amplifying the signal.

I mentioned noise. I see that the purpose of the parallel resistor/capacitor combination is to reduce noise at the analog pin when the headphones and player are disconnected. It looks like a very good idea to me now, and I apologize for objecting to it earlier. I'd recommend a resistor whose value is at least twenty times the impedance of the headphones, and a capacitor whose impedance at 20kHz is at least that big, to make sure that they don't load the player's output. I'd say maybe 1 Kohm and 8200 pF, to give plenty of headroom. Please note that the resistor value is just a guess, and the capacitor calculation isn't experimentally verified.

Using the numbers for the Apple in-ear headphones - 23 ohms, 109 dB SPL/mW - I calculate 126 dB SPL at 1.1V RMS.

I'm not argue with math, though I'm not always believe in what tech. specification manufacturers printed for their products. Again, OP says Android device , which is not Apple product. The same time I agree, simple OPA amplifier would make detector much reliable, especially with wide variety audio input sources.