arduino / ArduinoCore-mbed

330 stars 195 forks source link

`analogRead()` does not reset pin properly after previous `pinMode()` #829

Open dhalbert opened 8 months ago

dhalbert commented 8 months ago

BSP: Arduino MBed OS Giga boards v4.0.10 Board: Giga R1 Arduino IDE: 2.2.1

Sample sketch:

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

  // Attach A0 to 3.3V through a 220K or other high-value resistor,
  // so it's not stronger than the driven output.

  delay(100);
  Serial.println(analogRead(A0));

  pinMode(A0, INPUT);

  delay(100);
  Serial.println(analogRead(A0));

  Serial.println("Done");
}

void loop() {
}

On my test setup, this prints:

744
92
Done

I would expect it to print 744 or close to that twice. Once the pin is used in the pinMode(), it appears to be pulled low.

By comparison, the same sketch on an Arduino Uno prints (with the 220K resistor connected to 5V):

1023
1023
Done

The use case is a resistive touch screen driver (https://github.com/adafruit/Adafruit_TouchScreen) which flips pins back and forth between digital input/output and analog input modes to read X/Y resistance values.

This is reminiscent of (though order is different) to https://github.com/arduino/ArduinoCore-mbed/issues/328 and https://github.com/arduino/ArduinoCore-renesas/issues/58

MattGlobal commented 8 months ago

Hello @dhalbert , i modified your text and it seems to be working :

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

void loop() {
  // Attach A0 to 3.3V through a 220K or other high-value resistor,
  // so it's not stronger than the driven output.

 delay(100);
  Serial.println(analogRead(A0));

delay(100);
  Serial.println("Done");

}

the problem is still the same with touchsceen... but i'm wondering if it's not just about a pins definition problem ?

dhalbert commented 8 months ago

@MattGlobal In the example you gave, there is no pinMode() between analogRead() calls. In my example, the pin usage alternates between pinMode() and analogRead(). My hypothesis is that the second call to analogRead() is assuming the pin is already set up where as in fact its settings where changed "behind the back" of analogRead().

dhalbert commented 8 months ago

Here is the impl: https://github.com/arduino/ArduinoCore-mbed/blob/68fbece79947ce2a64bf49f7ba5f5f8111d89454/cores/arduino/wiring_analog.cpp#L101-L121 The first time through, a new mbed::AnalogIn object is created. That's reused on subsequent calls.

A workaround might be to call analogUpdate() before every call to analogRead(). I'll try that. (EDIT: ANALOG_CONFIG isn't defined, so analogUpdate() is not included, so it requires some surgery in the sources, which is not a clean workaround for the average user.) But there's an assumption being made in the code in this file that the pin state is not changing out from under analogRead().