Continue to Site

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.

  • 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

Status
Not open for further replies.

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:
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.
 
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 ++;
}
 
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.
 
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?.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top