14

The arduino reference states that you would use the following code to read the value from analog pin #5:

int val1 = analogRead(5);

However to read from digital pin #5, you would pass the same pin number to digitalRead:

int val2 = digitalRead(5);

Shouldn't you use analogRead(A5) instead of analogRead(5)?

If not, what does the following code do:

int val3 = analogRead(A5);
Tyilo
  • 377
  • 1
  • 3
  • 12

2 Answers2

29

To answer Tyilo's specific questions:

analogRead(5) and digitalRead(5) will read from two different places. The former will read from analog channel 5 or A5 and the latter will read from pin 5 which happens to be a digital pin. So yes, if you want to read an analog pin with digitalRead you should be using A5.

Why?

analogRead requires a channel number internally but it will allow you to give it a pin number too. If you do give it a pin number it will convert it to its corresponding channel number. As far as I can tell analogRead is the only function which uses a channel number internally, is the only one to allow a channel number, and is the only function with this undocumented pin-to-channel conversion. To understand this let's start off with some examples.

If you want to use analogRead on the first analog pin A0 you can do analogRead(0) which uses the channel number or analogRead(A0) which uses the pin number. If you were to use the pin number variant, analogRead would convert the pin number A0 to its proper channel number 0.

If you want to use digitalWrite on the first analog pin A0 you can only do digitalWrite(A0, x). digitalWrite doesn't use analog channels internally and does not let you pass it a channel number. Well, it'll let you but you'll select the wrong pin. The same applies to digitalRead and even analogWrite.

What about the pin-to-channel conversions done by analogRead? The source for that function can be found in hardware/arduino/avr/cores/arduino/wiring_analog.c You'll see that it does some simple subtraction based on the board type. The A0/A1/A2/etc. constants represent the pin number of the analog channels and can be used everywhere you need to refer to the analog inputs. For that reason they are the best option to use in your Arduino code because it's very obvious that you're using the same physical port even when you're using different functions. The definitions of those constants depend on your board.

For example, here's the analog pin definition code for the Arduino Uno in hardware/arduino/avr/variants/standard/pins_arduino.h

static const uint8_t A0 = 14;
static const uint8_t A1 = 15;
static const uint8_t A2 = 16;
static const uint8_t A3 = 17;
static const uint8_t A4 = 18;
static const uint8_t A5 = 19;
static const uint8_t A6 = 20;
static const uint8_t A7 = 21;

For comparaison here is the analog pin definition code for the Arduino Mega:

static const uint8_t A0 = 54;
static const uint8_t A1 = 55;
static const uint8_t A2 = 56;
[...]
static const uint8_t A13 = 67;
static const uint8_t A14 = 68;
static const uint8_t A15 = 69;

Further EE discussion on analog pins: Can I use the analog pins on the Arduino for my project as digital?

Kevin Mark
  • 1,473
  • 1
  • 15
  • 20
  • 1
    I though it was exactly like you explained, I just got confused by the Arduino reference, which contains false information. – Tyilo Apr 18 '13 at 19:19
  • 1
    Also you can **only** do `analogRead` on analog pins! On the other hand, `analogWrite` can be used on both the analog and the PWM pins. – Tyilo Apr 18 '13 at 19:20
  • Hi @Tyilo, I'm also very disappointed of the Arduino reference in many ways! I was always wondering if it's only me... – powtac Apr 22 '13 at 09:33
  • 1
    @Tyilo I updated my response with some more accurate information taken from the source code. – Kevin Mark Apr 18 '13 at 20:03
  • @JamesC4S Yet another undocumented "feature" :\ – Kevin Mark Apr 18 '13 at 20:34
  • 3
    analogWrite() can be called on any of the pins, but it only does something on the PWM pins. On non-PWM ditial pins and all analog pins, it simply calls digitalWrite(). – baldengineer Apr 18 '13 at 20:16
  • 3
    @powtac - It's generally accepted that the arduino documentation is fairly abominable, at least around here. Don't feel like you're missing something, it's not you, it's the arduino people. – Connor Wolf Jul 12 '13 at 11:31
3

I spent hours on this. I thought I had a hardware problem. It turns out that I was calling analogRead() incorrectly.

Incorrect (erroneous sample code from DFRobot ):

val = analogRead(0); //connect sensor to Analog 0

Correct:

val = analogRead(A0); //connect sensor to Analog 0

Update: analogRead() takes GPIO pin numbers. A0 etc. are #defines for Arduino pin numbers, where A0 == 36.

Be careful: on e.g. the FireBeetle ESP32, pin labeled "IO36/A0" (GPIO36) equals Arduino A0, but "IO39/A1" (GPIO39) equals Arduino A3 (not A1), "IO34/A2" (GPIO34) equals Arduino A6 (not A2), etc.

jrc
  • 131
  • 3