Best practice for pin definitions?

This has been asked and answered many times, but I'm still scratching my head. I recent ported code from ESP8266 to ESP32. The pin definitions that work fine for my ESP8266 D1 mini, like "D4", were not found for the ESP32.

I can find enough forum posts and tutorials to figure out the pin numbers I need, and hardwire them into my code. But I'm hopeful there is a more portable way, e.g. GPIO. Being able to find them in an API document would be wonderful.

I played with other names, for instance "A0" compiles just fine for both board environments. A19 only works for ESP32, which isn't a surprise.

I'm on macOS Monterey version 12.4. My Arduino IDE version is 1.8.19. As of today my boards and libraries are up to date.

I boiled down my problem to this simple sketch, which compiles and links for board: "LOLIN(WEMOS) D1 R2 & mini", but doesn't find D4 for "ESP32 Dev Module".

#include <Arduino.h>

#define OnboardLEDPin  D4

void setupBuiltinLED() {
  // set the digital pin as output:
  pinMode(OnboardLEDPin, OUTPUT);
}

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

I'll still have to interpret the Espressif ESP32 DevKitC-32E specification (i.e. web search for cheat cheats). Espressif doesn't quite follow conventions (e.g. ADC2_9, which may or may not be A19). And I still need to know that ADC2 channels can't be used when WiFi is running.
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/_images/esp32-devkitC-v4-pinout.png

It's kind of unfortunate that my particular example still won't be portable, since the on-board LED may be on GPIO2 or GPIO4. But you can't have everything.

Not all board packages define the "Dn" pin numbers. I believe ESP32 is one of those. If you WANT to use that notation, then you need to define them yourself. Otherwise just use the numeric pin number.

It is best to use the pin labels printed on your board. Does your board say "D4" or just "4"?

In this case of using "the pin with the built-in LED" you should probably use the name "LED_BUILTIN" instead of 4 or D4. That will work unless the board manufacturer was particularly lazy. If you get a "LED_BUILTIN is not defined" error you can put "#define LED_BUILTIN 4" just above
#define OnboardLEDPin LED_BUILTIN

Would I have asked this question if I were using a board with standardized pins? e.g. Arduino Nano: Arduino Nano — Arduino Official Store..

There were no definitions for D0-D3 in Arduino.h when I selected board type: "Arduino Nano". Even though the board is marked that way. Is there some other header file that I'm missing?

Sounds like best practice is to define the raw PIN numbers that I need in the body of each sketch. I'll do that up top with a meaningful name, and just change the PIN number to match the board I'm using. This means I've got to research each new board type before using it. Which makes sense, you can't blindly solder to any available pin and expect it to work.

But thanks for those helpful responses. As it turns out, there's no LED_BUILTIN for ESP32-DevKitC. The LED is just for +5V status, it isn't controllable. Otherwise the board is marked mostly with raw PIN numbers. Then for example the data lines for external flash are marked D0/D1/D2/D3 but there are no definitions for them. Maybe that's just as well, those pins on the ESP8266 aren't at all the same.

https://www.google.de/search?q=ESP32+pinout&lr=&newwindow=1&safe=images

Thanks, I've done quite a few searches, and your top search result is one of my favorites.

So yes, I know what pin numbers to use. I was hoping there was a standard naming convention and library definitions. Apparently not.

I think the 'standard naming convention" is "pure numbers."
There are digital pins labeled 0..13 and you access them like digitalRead(12) And there are analog pins 0..5 accessed like analogRead(2)
This worked OK for the early Uno-shaped boards, but not so well for alternatives like the Nano (where the board pin layout was not so neat), and really poorly on third party boards (like the early ESP8266 boards) that had several formats and didn't actually label the pins on their boards.

Many modern boards define additional symbols for accessing the pins, like "LED_BUILTIN", "SDA", "PIN_WIRE_SDA", "PIN_C3", and it's good to use them, especially when there are actual hardware dependencies.

"Best Practice" is that you should define your own meaningful names, early in your program:

static const int LED = LED_BUILTIN;  // LED for debugging
static const int LOWLIMIT = 4;   // Low-end limit switch on digital 4
static const int SENSORS = 6;  // bit-banged dallas one-wire sensors on digital 6
static const int BATTERY = 0;  // battery monitor on analog 0.
// etc.

That way, even if the pin naming conventions on a new board are different, you only have to make modifications in one place.

You can also look for your board at the following links, and then look in the pins_arduino.h file to see what is already defined.

1 Like

I accept using raw pin numbers. Friendly chaos is a natural result of free and open source.

When it's obvious, I think you're right. I'll try to use the pins_arduino.h definitions in my "meaningful names" section.

But sometimes you've got to guess which IDE board type fits best. I've been using "ESP32 Dev Module", but didn't find a similar name in variants. So when I'm uncertain I think I'll stick with raw PIN numbers, which are easier to verify.

Maybe the doitESP32devkitV1 is a better choice anyway for the board I'm using, an Espressif: ESP32-DevKitC-32E

The following file shows that when you choose "ESP32 Dev Module" in the IDE, it will use the parameters for the name "esp32" in the variants folder:

esp32.name=ESP32 Dev Module

https://github.com/espressif/arduino-esp32/blob/master/boards.txt

Yeah. ESP32 is especially chaotic. I count 111 variants and 76 instances of LED_BUILTIN, for example. SCK, SDA, MISO, and MOSI seem to be more universally defined.

I've been using "ESP32 Dev Module", but didn't find a similar name in variants.

boards.txt will map names to variants. For instance:

esp32.name=ESP32 Dev Module
   :
esp32.build.core=esp32
esp32.build.variant=esp32
esp32.build.board=ESP32_DEV

So the relevant pin defs are in variants/esp32/pins_arduino.h

I use ID Utils - GNU Project - Free Software Foundation (FSF) a lot to find stuff in the source code. It's a command-line form of "find definition", essentially, but it has a lot more options and generality.

> gid SDA
ET-Board/pins_arduino.h:23:static const uint8_t SDA = 21;
Microduino-esp32/pins_arduino.h:26:static const uint8_t SDA = 22;//23;
S_ODI_Ultra_v1/pins_arduino.h:23:static const uint8_t SDA = 21;
adafruit_feather_esp32s2/pins_arduino.h:29:static const uint8_t SDA = 3;
adafruit_funhouse_esp32s2/pins_arduino.h:42:static const uint8_t SDA = 34;
adafruit_magtag29_esp32s2/pins_arduino.h:43:static const uint8_t SDA = 33;
adafruit_metro_esp32s2/pins_arduino.h:28:static const uint8_t SDA = 33;
alksesp32/pins_arduino.h:75:static const uint8_t SDA = 27;
atmegazero_esp32s2/pins_arduino.h:26:static const uint8_t SDA = 8;
bpi-bit/pins_arduino.h:31:static const uint8_t SDA = 21;
ch_denky/pins_arduino.h:17:static const uint8_t SDA = 21;
d-duino-32/pins_arduino.h:17:static const uint8_t SDA = 5;
esp32/pins_arduino.h:17:static const uint8_t SDA = 21;
  :

I should have clicked my heels three times. The "pin" numbers in API calls like digitalWrite() are actually the GPIO number (right?).

I was searching for a macro to map GPIO number to some physical PIN number deep inside the selected board. That's not necessary, I'll do something like this.

static const uint8_t MyFunctionPin = 42;

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.