AN_INPUT Ok to use?

Hi. I’m reading a piece of thermocouple wire (TW). First with a digital read to see if it’s there and then with an analog read to see if it’s hot. Since the TW has a nominal resistance of around 2 ohms, I figured I can see if it’s grounding out the pin with a simple digital read. If the wire is missing or has burned away, the pin should pullup high. Otherwise, it will be low.

void readFlame () {

  int raw;

  // see if thermocouple wire is present
  pinMode(A2,INPUT_PULLUP);
  raw = digitalRead(A2);

  Serial.println("A2 digital read=" + String(raw));

  if (raw) {
    Serial.println("There is no thermocouple wire.");
  } else {
    pinMode(A2, AN_INPUT);

    raw = analogRead(A2);
    Serial.println("A2 analog read=" + String(raw));

    if (raw >= 8) { // Indicate flame at around 6 mV
      digitalWrite(D7,HIGH);
    } else {
      digitalWrite(D7, LOW);
    }
  }
} // =============================================================

So far this seems to work well.

My question is with the documentation and the status of AN_INPUT.

The documentation states ‘do not set the pinMode() with analogRead()’. Also Particle Dev does not syntax highlight AN_INPUT as a valid pinMode.

By changing between digital and analog reads, am I in safe territory here? Is AN_INPUT a valid pinMode? Will AN_INPUT become a valid pinMode in the future? Is there another way I’m supposed to be doing this?

analogRead() sets the pin mode implicitly to AN_INPUT and if you had set another pin mode prior to the first call to analogRead() the pin will be set back to what it was. But you shouldn’t need to keep changing the pin mode after that anymore.

try this

void setup()
{
  pinMode(A2, INPUT_PULLUP);  // set this once as default state for the pin
}

void loop()
{
  if(digitalRead(A2))
  { // A2 is set as INPUT_PULLUP
    Serial.println(analogRead(A2));  // will be temporarily changed to AN_INPUT
    // and now should be back to INPUT_PULLUP 
  }
  delay(1000);
}

But why would you need digitalRead() anyway?
How does your circuitry look that you need to use INPUT_PULLUP and not just stick with analogRead() permanently?

1 Like

Thank for looking at this. But my question remains. Is AN_INPUT OK to use?

How can I see if there’s a wire attached between ground and A2 with analogRead? I’ve watched A2 for quite some time with nothing attached and it floats all around, usually 400-2000. I’ve seen low hundreds to 4000.

When my wire is cold, it A2 is 0 or 1 and when hot, it is around 15. Can I absolutely depend on the floating value of A2? Always being above 15?

I like my way better using the internal pull-up resistor and looking for a digital 0 or 1.

Again, my code works but I’m depending on the pinMode(AN_INPUT) which seems to be sort of ‘undocumented’. Does anyone know if AN_INPUT will become documented?

I can’t see any danger in using AN_INPUT, but have you tried the intended behaviour I described above, where you set INPUT_PULLUP once and thereafter let analogRead() do the switching between modes?

BTW, with such minimal signals, I’d rather go for a measuring amplifier.


Update
I have now tested the intended behaviour and it seems that there is something “broken”.
I filed an issue on GitHub

With this issue present, I’d think pinMode(A2, AN_INPUT) is the only way to go, if you want to stick with that kind of hardware setup.
And I already proposed the documentation of AN_INPUT back in February
[solved] Analog pin configuration outside of setup()

@ScruffR

The Photon works as documented. This is from the Firmware Reference:

  • The pinMode() is automatically set to AN_INPUT the first time
    analogRead() is called for a particular analog pin. If you explicitly
    set a pin to INPUT or OUTPUT after that first use of analogRead(), it
    will not attempt to switch it back to AN_INPUT the next time you call
    analogRead() for the same analog pin. This will create incorrect
    analog readings.

That is why I’m calling pinMode(AN_INPUT) manually before each analogRead(). I would not call this bad behavior or even a bug; you just have to know to change pinMode to switch the pullup resistor in and out.

The problem is: AN_INPUT does not syntax highlight in Particle Dev so I suspect it may not be a feature someone at Particle wants me to use. ???

I suggest changing your GitHub issue to make AN_INPUT a fully supported pinMode. This allows the user to control the Photon without black magic happening behind the curtain. In other words, you’re supposed to set the pinMode for digitalRead, what’s the problem with setting it for analogRead?

The difference is in the detail.
While it is documented that setting pinMode() after first analogRead() will cause worng readings, there is no mention of such a behaviour if you do it before hand.
And even more, it's not setting pinMode() that causes the problem but digitalRead() (as I've shown in my test code in the GitHub issue).

And by looking at the implementation of analogRead() what would be the use of storing the previously set pinMode() if not for restoring it to what it was - or even more if it was "forbidden" to set another pinMode() beforehand anyway?

BTW: That part of the docs you quoted there was a result of my own discussion with @BDub in order to clarify what was previously undocumented and not intended to work that way and still isn't.
So even if it's behaviour as documented it's not necessarily behaviour as intended or even expected or logical.

As mentioned by @BDub in the other thread, the reason for that is, that Arduino does not force you to do it, and Particle has decide to keep close to that pattern where possible.
The "need" for or better benefit of documenting AN_INPUT as a possible/additional pin mode was brought up by me in that thread already, but wasn't picked up on.

OK now I understand.

The way it SHOULD work is:
Set pinMode to INPUT PULLUP
Ech time I call analogRead the pinMode is saved, the pinMode is set to AN_INUT then the pinMode is restored

1 Like