Wrong analog values when using 2 potentiometers

Hello,

I'm using 2 potentiometers, each on a specific analog input to adjust a threshold param for my project. I have a piezo sensor on a third analog input.

I'm running into the following problem:
When turning the second potentiometer, the piezo sensor value also changes?! (not when turning the first one)

Here is my wiring and code.
I really don't get my error. Thanks for your help.

const int potentiometer1 = A0;  
const int potentiometer2 = A1;  
const int piezotrigger1 = A2;  


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

void loop() {

  int potentiometerValue1 = analogRead(potentiometer1); 
  int potentiometerValue2 = analogRead(potentiometer2); 
  int piezo1Value = analogRead(piezotrigger1);
  
  Serial.println(potentiometerValue1);
  Serial.println(potentiometerValue2);
  Serial.println(piezo1Value);

}

Put a 0.1uF ceramic cap between each pot wiper and ground to lower the pots output impedance and bypass noise.

Put a small delay (couple of milliseconds) between reading the 2 pots.

What is the value of the pots?

Do you really need to do seial prints that often?

You asked virtually the same question back on October 30.

Incorrect analog values when using piezo + potentiometer

You never responded to any of the advice there, nor have you incorporated any of into your sketch or expanded circuit.

Hi, thank you for your advices,
I don't need to print the values at all, I just did it for debug reason because my whole program is not functionning correctly because of these potentiometers issues.
But why is it only happening while turning the second potentiometer and not the first ??

This is a common problem when doing multiple analogReads consecutively.
There is only one ADC that is shared by all of the analog pins and basically it can't keep up.
To avoid this use a small delay or just do something else in between.

void loop() {

  int potentiometerValue1 = analogRead(potentiometer1); 
  Serial.println(potentiometerValue1);
  
  int potentiometerValue2 = analogRead(potentiometer2); 
  Serial.println(potentiometerValue2);
  
  int piezo1Value = analogRead(piezotrigger1);  
  Serial.println(piezo1Value);
}

What are the potentiometer resistances? What is the output impedance of your sensor?

Like @Hutkikz said, there is really only one ADC in the Arduino processor. The ADC inputs are multiplexed into that one ADC. There is a small value capacitor on the input that the voltage coming in must charge or discharge. It takes time for the input voltage to charge that capacitor. The output impedance (resistance) of the voltage source determines how long the charge time is. The higher the impedance the more time that the charging (or discharging) takes. So if your pots impedance is too high, it takes longer to charge (or discharge) the cap than the time between samples. Therefore the error in reading.

The maximum recommend output impedance for inputs to the ADC is 10K for full resolution.

So increase the time (delay or lower the impedance (cap) or lower pot resistance.

1 Like

@van_der_decken when this happens you should flag the topic as a cross-post and give a link to the original topic. Don't think of this as being mean to @humbucker. Think of it as being nice to everyone, including @humbucker and all the other forum members. Let the moderators merge the topics then post your advice to @humbucker.

Try this (untested).
Leo..

const int pot1Pin = A0;
const int pot2Pin = A1;
const int piezo1Pin = A2;
int pot1Value, pot2Value, rawValue, piezo1Value;

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

void loop() {
  pot1Value = analogRead(pot1Pin); // dummy read
  pot1Value = analogRead(pot1Pin);
  Serial.print("Pot1: ");
  Serial.print(pot1Value);
  Serial.print("\t");
  pot2Value = analogRead(pot2Pin);
  pot2Value = analogRead(pot2Pin);
  Serial.print("Pot2: ");
  Serial.print(pot2Value);
  Serial.print("\t");
  piezo1Value = analogRead(piezo1Pin);
  piezo1Value = 0; // reset
  for (int i = 0; i < 100; i++) {
    rawValue = analogRead(piezo1Pin);
    if (piezo1Value < rawValue) piezo1Value = rawValue;
  }
  Serial.print("Piezo1: ");
  Serial.println(piezo1Value);
}

Thank you for these extra details, I'm only beginning to program with Arduino,
my potentiometers are 50K, maybe not the best then :wink:
I will try the capacitor, and also will order 10K potentiometers.
I will write back with the results of these tests, for others who might run into the same problems.

1 Like

It is fine to use higher resistance parts if you are concerned with current use like in battery powered devices. Just be aware of the pitfalls and mitigate the potential of crosstalk with caps and/or lowering the sample rate.

@humbucker Although it will slow your code a bit, which may be irrelevant, doing a double-read of each analog input, discarding the first value and using the second, often cleans up this issue.

BTW, is it necessary to read your analogs at loop( ) speed :thinking: .

1 Like

Well, this project is a "midi controller", piezo trigger are being used as switches to send midi notes,
so I guess I have no choice to read analogs as quick as possible all the time to be able to play notes in time, without extra delay. Right ?
Thank you!

Strongly suggest trying this, anyway. The change in your code speed is likely not going to be noticeable. ISTR each analog read takes a few tens of uS, so the added time will never be noticeable by humans.
I suspect, though I don't know for sure, it would be an exceptional person who could detect even a 5 mS delay. We're just not tuned to that.

The mega328, with default clock, takes 100us to do a conversion.

1 Like

So, 600 uS to do three double reads, plus the execution time of the rest of the code. We have no idea of "the rest of the code", either not written yet or not presented. Hopefully, sub millisecond loop time.

analog.read() is blocking, so one will want to distribute it through the loop, or even check one analog input in each iteration of the loop, but that's all optimization. A millisecond loop time is indistinguishable from instantaneous, for a person.

Point of order - if one does
read AI 1
delay of some form, even doing other things
read AI 2
etc.
You don't benefit from the delay, because the mux is only set to the new channel at the time of the new read; you really have to point the mux to the new channel, then delay, then read, like this:
read AI 0
point to new channel
do something else while mux settles
read AI1
etc
I'm not sure if there's a way to do that, short of a bit of assembly code. Doing the analogread(0), analogread(0), successively, gets it done, and suffices for most of us, but it does suffer from the penalty of the first conversion time.

I agree that using 2 successive anaog reads will help in the high source impedance situation. No argument.

I only meant to clarify the time that one analogRead() takes.

1 Like

Understood. The rest of my post was really for the clarification, as someone else had suggested a simple delay between reads. It really doesn't help.

That was probably me and now that I read your explanation, agree.