14
\$\begingroup\$

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);
\$\endgroup\$

2 Answers 2

29
\$\begingroup\$

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?

\$\endgroup\$
7
  • 1
    \$\begingroup\$ I though it was exactly like you explained, I just got confused by the Arduino reference, which contains false information. \$\endgroup\$
    – Tyilo
    Commented Apr 18, 2013 at 19:19
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Tyilo
    Commented Apr 18, 2013 at 19:20
  • 1
    \$\begingroup\$ @Tyilo I updated my response with some more accurate information taken from the source code. \$\endgroup\$
    – Kevin Mark
    Commented Apr 18, 2013 at 20:03
  • 3
    \$\begingroup\$ 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(). \$\endgroup\$ Commented Apr 18, 2013 at 20:16
  • 3
    \$\begingroup\$ @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. \$\endgroup\$ Commented Jul 12, 2013 at 11:31
3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.