analogRead(0) or analogRead(A0)

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?

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.

Leave a Comment