AnalogRead of pin dettaches interrupt

yeahtuna

Well-known member
If I attach an interrupt to a pin (the ISR calls digitalRead) and then at a regular interval call analogRead on that same pin from the main loop, the interrupt gets detached after each analogRead and I have to reattach it.

1. Is there something in the analogRead method that is automatically detaching the interrupt?

2. How taxing on the Teensy if I'm constantly reattaching interrupts on a couple of pins every 5 ms or so?
 
If you call analogRead it's not longer functioning as a GPIO, it's used by the ADC instead. You can't have both.
 
Au contraire. You can, you just have reattach your interrupts after every analogRead(). I just thought there might be a more elegant solution.
 
Inputs pins are either digital or analog, not both at the same time. It is related to the chip pin configuration.
To solve your problem, use two separate pins connected to the same signal: one in digital mode for the interrupt, the other in analog to be read with analogRead.
Which kind of signal are are measuring ????
 
I'm reading a rotary encoder where the push button is wired through a 10K resistor and then back to the one of the pins. So I want to use the encoder with interrupts and then periodically check if one of the pins is being held at a specific voltage. Unfortunately I don't have any extra pin connections available. If I did, then I obviously wouldn't be reading the encoder button in this strange way.
 
1756245772097.png

Pins connected to the tip and ring of the TRS jack. It's not perfect--for example if the encoder rotates while the button is pressed, but it's better than no button.
 
Can you draw a schematic of the _whole_ setup - how are the signals connected to the microcontroller, power, etc...
 
My setup is rather complex, so I'm not going to draw it out for you. It boils to the same as any other encoder--I'm just using two GPIO pins. One is connected to the tip of that TRS and the other is connected to the ring.
 
Two special and perhaps unexpected things happen inside analogRead(). Maybe one of them is the cause of your trouble?
  1. Pin configuration is altered if default input keeper mode detected
  2. 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;
    }
 
t
he 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).
I thought for sure that was going to be the cause because I had poked around in Encoder.h a while back and noticed that the pin configuration registers are changed in there. Alas, I'm seeing the issue on Teensy 3.2 devices, and it's analogRead method is quite different, so it's got to be something else. I could play around with editing analog.c, but it's working extremely well just reattaching the interrupts, so I'll probably just leave it as is.

After more testing, it looks like it's not the analogRead causing the interrupt to be disabled. It must be happening somewhere else in my code.

Update: I figured it out. My code was calling pinMode on the pins in questions a few moments after the Encoder was enabled. Attaching the interrupts after the call to pinMode resolves the problems. Sorry for the noise. It's a big project with lots of code. AnalogRead on a pin that has an interrupt attached works perfectly fine.
 
Last edited:
Back
Top