• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Inaccurate voltage readings on an esp32 as opposed to multimeter

Arjuna_1000

New Member
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

Simple 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

Thanks!
 
Last edited:

Nigel Goodwin

Super Moderator
Most Helpful Member
It doesn't help you're trying to measure an AC signal with a DC converter, you're never going to get a sensible reading - you first need to convert the signal to DC.
 

Arjuna_1000

New Member
I solved it by averaging the values over 500 cycles.

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 ++;
}
 

Les Jones

Well-Known Member
Most Helpful Member
The true average of an AC signal should be zero. But the way you are doing it I think it will be treating all the negative values as zero so your result would be about half the average of the positive samples. As Nigel has told you you should use an active rectifier to convert the AC signal into a DC signal. An alternative would be at add an offset value equal to half the full scale reading of your ADC to your AC input signal. You would then need to use software to convert all readings less than half the ADC full scale to the corresponding positive value. You would also need to subtract half the ADC full scale value fro all the readings greater than half the full scale value.

Les.
 

Nigel Goodwin

Super Moderator
Most Helpful Member
Why do people do this? If should be a define!! I guess the optimizer takes care of it. But better to get it right in the first place.

Mike.
Certainly a very strange thing to do, and regardless of the optimiser it's going to be no better (and probably worse) than doing it properly.

I would imagine a 'better' compiler would flag it as an error?.
 

gophert

Well-Known Member
Most Helpful Member
Why would it not work? its even used in the lesson on variables at Arduino.cc
I'm beginning to think OCD is a real thing.

 

dougy83

Well-Known Member
Why do people do this? If should be a define!! I guess the optimizer takes care of it. But better to get it right in the first place.
You can use constexpr to mark the typed variable as a compile-time constant, if you wanted; this also honours variable namespaces/scoping/etc., unlike #define.
 

Pommie

Well-Known Member
Most Helpful Member
You can use constexpr to mark the typed variable as a compile-time constant, if you wanted; this also honours variable namespaces/scoping/etc., unlike #define.
But the OP had it as a global variable. Obviously, the Arduino compiler optimises it to the same code but if you did this on XC8 (without optimisation as most people use it) it will reserve two bytes of memory(RAM) for it. However, I do like this method.

Mike.
 

dougy83

Well-Known Member
But the OP had it as a global variable.
Locally-scoped variables (or class members) with the same name as the global variable are possible. Try that where a #define exists. As an example:
C++:
#ifdef USE_DEFINE
  #define dataPin 1    // <-- this will cause issues if 'dataPin' is used elsewhere in code
#else
  constexpr int dataPin = 1;  // <-- this is fine
#endif

class MyHardware
{
  int dataPin;
public:
  MyHardware(int dataPin) : dataPin(dataPin) {}
};
Obviously, the Arduino compiler optimises it to the same code but if you did this on XC8 (without optimisation as most people use it) it will reserve two bytes of memory(RAM) for it.
True; they probably compile to the same code. I'd almost swear that XC8 purposely puts in garbage code to incentivise paying for the compiler.
 

Pommie

Well-Known Member
Most Helpful Member
I'd almost swear that XC8 purposely puts in garbage code to incentivise paying for the compiler.
I used to believe that but now think it's just the way it compiles and leaves it to the optimiser to tidy up. I have a friend who wrote a C compiler and that is the method he used.

BTW, I always define constants in upper case and variables in camel case.
So in my case (N.P.I.) I'd have,
Code:
#define DATAPIN 1
or, more probably
#define DATA_PIN 1
And, of course, variables as in your example (camel case).

Mike.
 

dougy83

Well-Known Member
I also think that's the case. I remember the output of the old hitech picc was better than the current XC8 output; they must've stripped out _ALL_ of the optimisations.
Fair enough; there'll be no name conflicts that way. I'll still avoid preprocessor substitution where possible.
 

Nigel Goodwin

Super Moderator
Most Helpful Member
I used to believe that but now think it's just the way it compiles and leaves it to the optimiser to tidy up.
It used to add loads of extra rubbish, presumably deliberately to make it large and slow, as the extra code had no function at all (other than wasting space and cycles) - but it seems rather better now than it used to be.
 

Latest threads

EE World Online Articles

Loading
Top