Two special and perhaps unexpected things happen inside analogRead(). Maybe one of them is the cause of your trouble?
- Pin configuration is altered if default input keeper mode detected
- While waiting for the ADC, the yield() function is called.
Hopefully #2 is easy to understand. Normally yield() doesn't do much, but if you're using it any code configure to run from yield() could get called.
#1 is complicated and probably not well understood. The pins default to a input "keeper" mode which applies weak pullup if the pin is already high, or weak pulldown is the pin is already low. The idea is to cause the pin to tend to stay in the same digital state and weakly pull the voltage (either way) away from that critical middle zone between high and low where both of the input transistors conduct.
Input keeper mode can wreck havoc on analog signals. Or it can have little to no noticeable effect. It really depends on the impedance of your signal. If your signal comes from the output of an opamp, the weak pullup or pulldown (probably) just causes a small extra current flow which the opamp's output can easily overcome to hold the voltage correct (as the opamp's feedback circuit dictates). But if your signal is from the 100K pot, changing the pin from weak pullup to pulldown or vise versa will alter the voltage pretty noticeably. With a 10K pot, the effect can still be seen, but much less because the signal impedance is 10X lower so the weak pullup or pulldown has much less effect.
Many people have hit this analog problem, because the ordinary Arduino API is to just call analogRead() without needing to do any configuration to the pin. In the Arduino way, you would normally only call pinMode() if you're doing digital I/O, and even then the pins default to INPUT mode on most boards. Very few have hardware like input keeper!
In the earlier days of Teensy 4.x, the answer to analog signals messed up by the input keeper was to suggest calling pinMode(pin, INPUT_DISABLE). It turns off the digital input circuitry completely, which is the best way for analog signals so you also avoid the pin's input circuitry consuming extra power when your voltage happens to be right at that special low vs high spot.
In more recent times, code went into analogRead() which tries to detect if you're running with input keeper mode. The assumption is because you never called pinMode(), because so far we don't even define INPUT_KEEPER. The only way to get into input keeper mode is to leave the pin at its default by never calling pinMode() at all, or by writing directly to the pin's configuration registers (which presumbly would mean you know about these special modes). That special code starts
at line 81 inside analog.c:
Code:
// check if pin has input "keeper"
volatile uint32_t *pad = portControlRegister(pin);
uint32_t padval = *pad;
if ((padval & (IOMUXC_PAD_PUE | IOMUXC_PAD_PKE)) == IOMUXC_PAD_PKE) {
// disable keeper, as it messes up analog with higher source impedance
// but don't touch user's setting if ordinary pullup, which some
// people use together with capacitors or other circuitry
*pad = padval & ~IOMUXC_PAD_PKE;
}