Read values from a 3,5mm jack

Hey guys,

I am currently working on a VU-meter using Arduino and the ESP32 Dev Kit V4 from AZ-Delivery.
I would like to use my phone as Input (via a 3.5mm terminal block).

I connected the terminal block GND to the ESP32 GND and L/R to two ADC pins (12 bits if I remember correctly).

My testing code looks as follows:

#define L 33
#define R 32

int Volume_L = 0;
int Volume_R = 0;

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

}

void loop() 
{
  Volume_L = analogRead(L);
  Volume_R = analogRead(R);

  Serial.println(Volume_L);
  Serial.println(Volume_R);

  delay(100);

}

Plugging the jack into my phone gives me a constant reading of 0 on both channels (no matter if I play any sounds or not). If it isnt plugged in, the readings go slowly up and down between 0 and 4095.

I found a youtube video of a student who did something similar and he used the following code to get the values for the VU-meter (no further tweaking was done by him).

int volume = analogRead(input);          //input was declared globally
double value = volume;
Serial.println(value);

He compared "value" to the different levels at which his LEDs turn on as his code. This Code apparently works for a mic and aux, but I dont really see how.

Anyway, it would be great if you guys could help me out here :).

What kind of phone? Desk phone? DECT? IP phone? Mobile phone? Two tin cans and a piece of string?

What do you mean by a 3.5mm terminal block?

Please show a photo of your wiring and a schematic.

Please read How to get the best out of this forum

Thanks,

Mobile phone, but I would probably switch between my mobile phone and the PC from time to time. I could also imagine plugging it into my piano or something.

I will attach a photo of the wiring, but I dont have a schematic for it since I didn't hook it up to my complete build right away


. Thought it would be a good idea to test the different parts individually :).

A terminal block (at least I thought that's what they are called) is a (iny case female) 3.5mm jack that splits into 3 cable (gnd, left and right).

I should probably add that I am pretty new to this, but I guess you can tell from my question.

Hi,
try this tutorial and use a pot as a potential divider to see if you are reading the input correctly.

Tom... :smiley: :+1: :australia:

That's better.

Audio is AC, it goes negative as well as positive, the input to the A2D converter requires the signal to be positive only, no negative bits. At the very least you need a potential divider, say 2 * 10k resistors in series, one end on 0V, one end on 3V3 and the middle to the A2D input. Then you need a capacitor, exact value unimportant at this stage but say around 1μ0 will do. You connect the capacitor between the L or R output from the phone to input of the A2D converter.

After that I'll leave you in the capable hands of people more experienced than me in the kind of thing you are trying to do.

With the code you have I would expect you to see a load of random, or nearly random, numbers.

Good luck with your project.

Thank you for the answer. Not to doubt you, but are you sure that this is necessary? The "project tutorials" I saw online just hook it up and apparently that works.
What you are saying makes sense, but why would someone build a functioning project and then upload the wrong "schematic"?
Please excuse the annoying question, but I am a bit confused since I am getting different answers from all sorts of people and its kinda hard to filter them :).

Sadly I do not have a potentiometer :/. But I guess connecting the GPIO pins to gnd or 3.3V should do the trick. Doing this gives me either 0 or 4095, so that should not be the problem.

You are asking me why someone I don't know would do something, guess what? I do not know.

It might work OK but that doesn't mean it's correct. There is a lot of rubbish on the internet, not just in electronics but in all subjects.

I don't really want to advise you on this because it falls into the category of something I could do myself if I wanted to but I have not done it, so any advice would be based on what I think should work, not what I know from doing it definitely would work. You do need to shift the voltage up though so it doesn't go negative. There are definitely people here better able to advise you than me, you just have to hope one of them takes an interest.

Have fun.

I don't know anything about the ESP32 but I made The Worlds Simplest Lighting Effect with the Arduino Uno as a little example project. There is an attached schematic for the bias circuit and since you don't have a potentiometer you should at-least build the voltage divider with two equal value resistors as Perry suggested.

The bias circuit should give you a reading of about 2048 on your 12-bit ADC and you'll know if you are getting any analog readings at all. If you are not reading about half of the analog range you'll need to troubleshoot that.

Of course, you'll eventually need two input-bias circuits if you want to read both channels.

You'll generally want to subtract-out the bias in software but that's up to you.

Without the bias the signal is negative half of the time. If "nothing bad" happens half of your readings should be zero.

The Uno has little protection diodes that "short out" when you go more than about 1/2V negative or about 1/2V over Vcc. (I don't know if the ESP32 has those.) If your signal peaks over 1/2V negative, at best the signal will get distorted. At worst, you'll fry the microcontroller, or there is a slight chance you'll damage your phone or whatever is connected.

Since you are reading a waveform that's negative half of the time and crosses-through zero twice per cycle, your "testing code" should give "random" readings (within a range). And, you might want to take-out the delay.

1 Like

See that bit that says stereo audio output from headphone socket?
That is why that circuit will not always work. That is the problem with poor schematics is that they only work under specific circumstances that the author found himself facing. The signal from a headphone socket is not always the same. In this case the author happened to had a source that had a DC bias on it. Or that the author’s expectation of what works is a bit suspect.

1 Like

Hi,

Yup, no problems, good bit of thinking if no pot.

Tom... :smiley: :+1: :coffee: :australia:

Hey there again Mike :),
That makes a lot of sense. It is very frustrating as a beginner tho. You see a lot of projects that look easy to do and every step is about 4 times as complicated as you thought it would be. I am still enjoying the process tho an feel like I am learning a lot, mostly thanks to you guys.
Anyway, I kinda ignored the problems and found some sort of sorcery code that turns the digital signals from my mic into (obviously faked) analog ones. Not entirely sure why that works, but it works well enough for me. I just have to get the entire code stitched together now.
Doesnt work yet for some reason, but I am sure I will figure it out somehow :). An thank you for taking the time... again :slight_smile:

Thank you a lot for the deliberate answer. I am learning so much in here. I found a way to use my digital mic as the input, so I will use that for now and come back to the aux input at a later stage. I just want to get it to work :slight_smile:

If you post the code then perhaps we could explain it to you. My guess is that it is using the PWM to generate an analogue signal when averaged, with the PWM frequency set to a high "ultrasonic" frequency.
Read about how PWM works here:-
http://www.thebox.myzen.co.uk/Tutorial/PWM.html

Hi,
Did you google

esp32 vu meter

Have a look at this YouTube video.

Tom... :smiley: :+1: :coffee: :australia:

I have, but he uses a different library and I have a different mic. But I found a good solution for my input issues. Thanks a lot for taking the time to help me out :slight_smile:

I will definetely give that a thorough read. Judging by the quick scimming I did and the animation included, I would say that that is kinda what the code does. I am pretty confident that I understand what it does, I am just a bit confused why that is possible. Anyway, I will read what you sent :).

I have one last problem though (everything else works now, so I am very close to completion) and it is just from a programming standpoint I guess. Since you made the mistake of answering me again (thank you :)), I am going to ask you first. I will put my Code below.

The comments in the code should explain what it does, but I will try to explain it here too. The while loop is where I get my "analog" output from (the sorcery) and the for loops are adressing the two LED stripes. Some tweaking in that part of the code might be necessary, but it shouldnt play a role with my problem.

This is my problem:
I need the mic code to run until there is an output that the LEDs can use and I opted for a while loop. The problem is that I can basically choose between the mic code working

while(millisElapsed <= (Sample_Time+1))

and LED code working (I am assuming that I never exit the while loop and never reach the LED code otherwise)

while(millisElapsed <= Sample_Time)

This is the complete code, I hope I dont violate any international laws with my programming style.

#include <Adafruit_NeoPixel.h>

#define LED1 17
#define N_PIXELS 25

#define LED2 32

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(N_PIXELS, LED1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(N_PIXELS, LED2, NEO_GRB + NEO_KHZ800);

const int micPin = 33;
const int Sample_Time = 10;
unsigned long millisCurrent;
unsigned long millisLast;
unsigned long millisElapsed = 0;

int Volume = 0;

int i = 0;
int Height = 0;
 

double Sensitivity = 1;


void setup() 
{
  Serial.begin(9600);
  while( !Serial) delay(20); 
  pinMode(micPin , INPUT);

}

//while loop takes the binary output from the mic and turns it into a (faked but surprisingly well working) analog output to use for the VU-Meter
void loop() 
{
  while(millisElapsed <= (Sample_Time+1))                       // while loop added because the mic code has to run often enough for if (millisElapsed > Sample_Time) to activate (no output otherwise)
  {
    millisCurrent = millis();                                   //millis() is time since the programm started              
    millisElapsed = millisCurrent - millisLast;                 //millisElapsed is time since end of last Sample time
    if(digitalRead(micPin) == HIGH)                             // HIGH = there is a sound detected (mic output is only binary)
    {
     Volume++;                                                  
    }

    if (millisElapsed > Sample_Time)                            //Sample time is 10 millis
    {
     Serial.println(Volume);                                    // basically just for testing purposes
     Height = Volume / 240 * Sensitivity;                       // Height is how many of the 25 LEDs will light up (numbers probably need some tweaking)
     Volume = 0;                                                // Volume reset for next loop
     millisLast = millisCurrent;                                // in order to calculate the next millisElapsed
   }
  }
  Height = 12;                                                  // just to see if the LEDs work without relying on the mic data
 
  for (i = 0; i < N_PIXELS; i++)                                // rest of the code isnt that important for the problem, it works when commenting the mic code or changing while(millisElapsed <= (Sample_Time+1)) to while(millisElapsed <= Sample_Time)
  {
    if (i >= Height)
    {
      strip1.setPixelColor(i, 0, 0, 0);
    }
    
    else
    {
      strip1.setPixelColor(i, 0, 0, 150);
    }
    strip1.show();
  }

  for (i = 0; i < N_PIXELS; i++)
  {
    if (i >= Height)
    {
      strip2.setPixelColor(i, 0, 0, 0);
    }
    
    else
    {
      strip2.setPixelColor(i, 220, 0, 0);
    }
    strip2.show();
  }
}

I feel like I have been looking at this long enough to stop seeing my own mistakes, so a 2nd pair of (qualified) eyes just might do the trick. I cant wait to see if this just takes a small change or if everything collapses. Again thanks for your help and have a great day/night.

The while loop must only look / generate the output not cover both the output generation and the LEDs.
You need to impose some sort of limit on the volume variable not let it run forever upwards.

Hm, isnt that covered with the Volume = 0; in the if part of the while loop? I made some changes to the code though and am still running into a similar problem. I will make (one last thread) to finish the trilogy and hopefully get it running :slight_smile:

No, that as yore comment says is for next time, not the current time.