Inaccurate voltage readings on an esp32 as opposed to multimeter

Thread Starter

Arjuna_1000

Joined May 6, 2021
10
I am working on detecting the amplitude of a signal coming from a guitar pickup. I am using an esp32 and an LM386 module for amplifying the signal.

I get quite stable readings with a multimeter, but the readings on the Arduino IDE show peaks and also peaks come when no signal should be there.

Screen Shot 2021-05-07 at 11.02.22 AM.png

Here is a link for short videos of both the esp32 readings and the multimeter:

https://drive.google.com/drive/folders/1gpvkN_sz627jG0TNPpUps82105EB89OF?usp=sharing

Thanks!
 

ericgibbs

Joined Jan 29, 2010
18,766
hi,
Have you tried the ESP32 ADC test with a fixed tone, say from a signal generator.?

Also can we check the Sketch.?

E

BTW:
The linearity on the 1023 ADC for the ESP32 is not very good.
 

Thread Starter

Arjuna_1000

Joined May 6, 2021
10
Code:

Code:
int ampedVoltagePin = 12;

void setup() {
  pinMode(ampedVoltagePin, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(ampedVoltagePin));
  delay(100);
}
Diagram:

Screen Shot 2021-05-10 at 12.12.45 PM.png
 

ericgibbs

Joined Jan 29, 2010
18,766
hi A,
Ran your Sketch in a ESP32.
There is now way, that Sketch can track in the ADC an analog sinusoidal signal.
E
void loop() {
Serial.println(analogRead(ampedVoltagePin));
delay(100);
 

ericgibbs

Joined Jan 29, 2010
18,766
hi A,
I guess you know that the ADC input should not exceed +3.3V and never go negative. [ for 4027 counts]
To measure the peak or rms value of the sine, you need a precision rectifier, before the ADC.

Your DVM will give a steady ready reading, because of the way it measures the signal.
E
 

ericgibbs

Joined Jan 29, 2010
18,766
hi A,
You could check easier by using the Serial Plotter option on the IDE.
Also I have changed the Baud rate and delay.
E
Displaying mains hum, almost in sync at a lower sample rate.!
 

Attachments

Sensacell

Joined Jun 19, 2012
3,432
Your setup applies a signal that goes below ground- this is a problem.

Use 2X 10k resistors to make a voltage divider at 1/2 Vcc, connect this to the ADC input - then couple the signal to this node through a 10 uF capacitor. (the + side goes to the resistors)
This sets the bias of the signal in the center of the ADC range, the positive and negative signal can then be read above and below this reference.
 

trebla

Joined Jun 29, 2019
542
If you want get stable reading of AC signal you must use a low pass filter after biasing the input signal, as mentioned before.
 

Thread Starter

Arjuna_1000

Joined May 6, 2021
10
Your setup applies a signal that goes below ground- this is a problem.

Use 2X 10k resistors to make a voltage divider at 1/2 Vcc, connect this to the ADC input - then couple the signal to this node through a 10 uF capacitor. (the + side goes to the resistors)
This sets the bias of the signal in the center of the ADC range, the positive and negative signal can then be read above and below this reference.
I was wondering about this but I am not sure the LM386 is already doing that. I am trying to get an oscilloscope to check that.
 

Thread Starter

Arjuna_1000

Joined May 6, 2021
10
I am now getting readings that make sense by printing the average every 500 rounds:

New code:

Code:
int ampedVoltagePin = 12;
int counter = 0;
int sumOfVoltages = 0;
int sampleSize = 500;
int average;

void setup() {
  pinMode(ampedVoltagePin, INPUT);
  Serial.begin(9600);
}

void loop() {

  sumOfVoltages += analogRead(ampedVoltagePin);
 
  if (counter > sampleSize -2) {
    average = sumOfVoltages/sampleSize;
    Serial.println(average);
    sumOfVoltages = 0;
    counter = 0;
  }
 
  counter ++;
}
 

Thread Starter

Arjuna_1000

Joined May 6, 2021
10
Does anyone have an idea why I can only get proper readings if I have the speaker connected? I don't really need a speaker in my setup.

Also, thanks everyone. I am studying software engineering and have no access to an electronics mentor, except of course in forums like this one.
 

ericgibbs

Joined Jan 29, 2010
18,766
hi A,
This what I see on the Serial Plotter, with your Sketch, with 50hz hum, you need some form of filtering.
E

BTW: the TS as asked for. detecting the amplitude of a signal coming from a guitar pickup

Not averaged signal level.
 

Attachments

ericgibbs

Joined Jan 29, 2010
18,766
hi t,
I am running some tests with a signal generator input sine wave, ESP32 and the TS's Sketch.
Will try to post some results later today.
E
 

Sensacell

Joined Jun 19, 2012
3,432
Does anyone have an idea why I can only get proper readings if I have the speaker connected? I don't really need a speaker in my setup.

Also, thanks everyone. I am studying software engineering and have no access to an electronics mentor, except of course in forums like this one.

The LM386 is a single-ended amplifier, with no signal, the output hovers at 1/2 the supply voltage.
Speakers cannot tolerate DC, so a large DC blocking capacitor is always used to remove this DC offset, only the AC part flows to the speaker.
If you remove the speaker, the ADC input has no DC bias, it's floating around all random crazy- bad readings are assured. The Speaker provides a DC path to ground.

Your averaging scheme 'looks' like it's working, but you are just getting random points on the sine wave, the input protection diodes are clamping the negative-going peaks.

If all you really want is the absolute amplitude, look into using a precision peak detector circuit, otherwise you must sample the signal at a very high rate to catch the peaks accurately.
 

trebla

Joined Jun 29, 2019
542
Put this code to Nucleo-F103RB, but obviously needed to tune up:
C:
#define SAMPLE_COUNT 100
#define SAMPLERATE 100

int A_in = A5;    // select the analog input pin
//int ledPin = 13;      // select the pin for the LED
volatile int sample = 0;  // variable to store the value coming from the input
volatile int max_s, min_s; // variables for maximum and minimum readings
volatile long amplitude;
void setup() {
 //pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  sample = analogRead(A_in); //get first sample
max_s = min_s = sample;

for(int i = 0; i < SAMPLE_COUNT; i++) {

  sample = analogRead(A_in);
 
  if(sample > max_s)
    max_s = sample;
 
  if(sample < min_s)
    min_s = sample;
 
  delayMicroseconds(SAMPLERATE);
 
 }
 
 amplitude = max_s - min_s; //TODO: need implementing the EMA filter
 
 Serial.println((amplitude * 3300) / 1024, DEC);  //10 bits ADC
}
Input divider is 1:10, input sinal is half wave sine (diode rectified).
 
Top