Use of identifiers (e.g., Dn pin identifiers)

Continuing the discussion from Low-level manipulation of LED matrix on UNO R4 WiFi:

Does the above imply that I could alternatively use D35 as a synonym for 35 when addressing this pin in my code?

Not for the pins connected to the matrix.

However, you can do that with other pins, but not due to the referenced code. This is possible due to other code from the UNO R3 WiFi's core variant:

My personal opinion is that one of the biggest mistakes made in the early days of Arduino was the decision to use the An format for the names of pins that happen to have ADC capability. The mistake was further compounded by choosing to mark the pins without ADC with a Dn format on the silkscreen of boards. The gives the user the false impression that pins have only one capability. Even in that era when Arduino was mostly the ATmega8, that was false, and it is far more so with the more feature rich microcontrollers (a fact which the designers should have considered even in the early days). It is silly to try to convey the capabilities of a pin in its name. The pin name should only be an arbitrary identifier.

The one mistake they avoided at that time was codifying the Dn pin names in the code. Unfortunately the developers of the "esp8266" boards platform did make that mistake, then that mistake ended up creeping into the modern official Arduino cores. However, it is not implemented in all cores, so the use of these identifiers is harmful to portability.

So all this is to say that I strongly recommend against using the Dn pin names in your code.

Interesting โ€” until I read your comment, I would have assumed the opposite. So the preferred method to reference pin numbers is by their naked (unsigned integer) value?


P.S. Actually, would it be possible to split this comment (#9) into a separate topic, and respond to it there? (as I also have follow-up questions about conventions for using some other other all-caps identifiers, such as HIGH/LOW, which will be off-topic in the current thread.)

I have split the tangential discussion out to a dedicated topic as requested.

Carry on.

A post was merged into an existing topic: Low-level manipulation of LED matrix on UNO R4 WiFi

I always tend to use GPIO numbers not D0, D1, etc which depend critically on Tools>Board settings

Using the Arduino firmware allows to run code on any number of supported boards.

By "GPIO numbers", you mean the unsigned integer digits (e.g., just 2 or 2u for Digital Pin 2)?

And how do you distinguish D2 from A2 (especially if you want to maximize portability of your code to other boards)?

That's crap. D2 is different from 2. See the implementation of the D2 macro.

Let the compiler do that.

Huh? I was asking a question, not expressing an opinion.

In the opening comment by @ptillisch, the following advice was given:

Therefore, this thread (which started as a side discussion in a different thread) I was seeking first to clarify the advice that was given by @ptillisch:

cannot remember having any major problems porting code e.g. ESP32 - STM32 - RP2040 etc

That's good to know, but I still don't understand what convention you are actually using. You said "I always tend to use GPIO numbers not D0, D1", but I don't know what you mean by "GPIO numbers". So what exactly would you use in your code instead of D2 and A2?

1 Like

I particularly like the PIN_PC5 style definitions (the Arduino Pin Number associated with PORTC/bit5) used in the add-on cores for chips that don't have "standard" boards (MCUDude and DrAzzy's many cores, in particular.)

It's a shame it isn't more widespread, plus the ambiguity and confusion when you have PIND5, PORTD5, PIN_D5, PIN_PD5, D5, and 5... (all of which are 5, on an Uno. But not so elsewhere, or with A3 vs PORTA3 on some chips...)

You are probably thinking of an ESP8266 board.

Traditionally, Arduino pin numbers are only arbitrary identifiers for a pin, completely abstracted from the low level pin identifiers to which they are mapped by the core variant code. The core functions take Arduino pin numbers as parameters and then derive the associated low level identifiers from the Arduino pin number.

The developers of the "esp8266" core took a non-standard and confusing approach to pin mapping where they made the Arduino core API use the low level GPIO numbers, then used macros to map the pin numbers/names as marked on the board silkscreen to the lower level GPIO number. So indeed the numeric component of the macro doesn't necessarily match to the GPIO number when using those boards. For example:

When using one of those boards, I do recommend using the macro simply because this is the only way to have your code match what is written on the board's silkscreen.

However, this discussion started as being about the UNO R4 WiFi. The developers of that board's "Arduino UNO R4 Boards" platform used the standard approach for pin mapping, but then added these Dn macros to the variants as an afterthought. So when using one of the platforms that does standard pin mapping, you can use the integer Arduino pin number, or the Dn macro interchangeably.

I guess you never tried to compile the code for many different boards then. Many significant boards platforms do not define Dn pin names. I just did a quick survey of some of the boards platforms that happened to come to mind and found they are not defined by any of these:

You would also find that it fails to compile for most ESP32 boards, since they are only defined in a small subset of the core variants.

Some of the discussion is difficult for me to follow, because I am not familiar with all of the terminology. For example, when you say "low level GPIO numbers", or when @horace says "GPIO numbers", are you referring to the integer numerical values like 13 (for Pin 13)?

Also, you said:

If I would like for code to be portable, say, between the genuine Arduino "classic", Mega, and Nano families, would the above apply (i.e., do these all use "standard pin mapping")?

I'm not sure I really understand the disadvantage of using the macro conventions Dn โ€” wouldn't this make the code more portable (in that the pin designation in the code would always match the corresponding silkscreen identifier, even for platforms that don't use "standard pin mapping" โ€” as long as they are not among the 13 platforms in your list above)?

Furthermore, I am confused by what best practices would be for how to reference the "A" pins. If you recommend that the code should reference pin 2 instead of D2 for digital GPIO pin #2, then what is the recommended way of referencing the A2 pin?

The D1, A2 etc. identifiers correspond to board pins. These pins then are mapped to controller pins and finally to controller ports and pinmasks.

This allows to e.g. develop code for an ATTny custom board on an ATMega.

They are the identifiers for the IO pins on the microcontroller:

If you have worked with the AVR microcontrollers, you might be familiar with the low level pin identifiers like "PB5" (port B, bit 5):

๐Ÿ“ท

arduino atmega328 Web by pighixxx - CC BY-NC-ND 3.0

The GPIO number are the same thing. The manufacturer of the chip simply chose a different format for the identifiers.

Yes.

Here are the mappings for the Mega:

and here for the Nano:

https://github.com/arduino/ArduinoCore-avr/blob/1.8.6/variants/standard/pins_arduino.h#L150-L194

No. Try compiling this simple sketch for the Arduino AVR Boards platform's Arduino Uno and then come back and tell me whether you believe the use of D2 instead of 2 made that code more portable:

void setup() {
  pinMode(D2, OUTPUT);
}
void loop() {}

Here we are stuck with the unfortunate decision the developers made 20 years ago. The silkscreen on the board says "A0", and that is not reliably equivalent to the integer 0, so the only reasonable approach is to use A0 in your code.

I surmise based on the inclusion of "Arduino AVR Boards" at the top of your list above (of platforms that do not define Dn names) that this will not compile.

My point/question was based on the assumption that there are at least three categories of boards/platforms:*

  1. Boards/platforms* that do not have Dn macro definitions (e.g., the 13 that you listed above), but that (presumably) use "standard pin mapping".
  2. Boards/platforms* that use "standard pin mapping" but also have Dn macros defined ("as an afterthought", as you said) โ€” such as the UNO R4 WiFi.
  3. Boards/platforms* that do not use "standard pin mapping" but that do have Dn macros defined (e.g., ESP8266, if I understood the above discussion correctly).

Thus, wouldn't designating digital pins by their numerical integer values (e.g., 2) improve portability/compatibility between the first two categories, while using the Dn macros would improve portability/compatibility between the second two categories of boards?

 


*Edit: Changed "platforms" to "boards/platforms".

It's a board matter, preceding the platform definitions. Look where the related header files reside and how they are selected from the IDE "Board" menu.

Thank you for correcting my use of unfamiliar terminology. I have now revised the wording of my post#18 in a way that I hope will improve my chances of getting an answer to the question posed.