Arduino Nano ESP32 GPIO Numbering Explained: Arduino Pins vs Native ESP32-S3 GPIOs

Arduino Nano ESP32 GPIO numbering explained: map D0-D13 and A0-A7 to native ESP32-S3 GPIOs, understand Arduino-pin vs GPIO-number mode, avoid bare-integer bugs and use safe portable pin names.

The Arduino Nano ESP32 has one pin-numbering feature that can confuse even experienced ESP32 users.

The pin printed on the board is not always the number you would normally use on an ESP32-S3 development board.

For example:

All three descriptions refer to the same physical pin.

Arduino solves this by offering two pin-numbering modes:

The most important rule is simple:

Why Nano ESP32 Numbering Is Different

Traditional Arduino Nano boards use a familiar numbering scheme:

Normal ESP32 development boards usually expose raw Espressif GPIO numbers:

Arduino wanted Nano ESP32 to remain compatible with the Nano form factor while still exposing the underlying ESP32-S3 hardware.

The result is a translation layer between:

Complete Nano ESP32 Pin Mapping

Board label Arduino pin number Native ESP32-S3 GPIO Main default function
D0 0 GPIO44 RX
D1 1 GPIO43 TX
D2 2 GPIO5 GPIO / ADC1
D3 3 GPIO6 GPIO / ADC1 / CTS
D4 4 GPIO7 GPIO / ADC1 / DSR
D5 5 GPIO8 GPIO / ADC1
D6 6 GPIO9 GPIO / ADC1
D7 7 GPIO10 GPIO / ADC1 / I2S SCK
D8 8 GPIO17 GPIO / ADC2 / I2S FS
D9 9 GPIO18 GPIO / ADC2 / I2S data
D10 10 GPIO21 SS / CS
D11 11 GPIO38 MOSI / COPI
D12 12 GPIO47 MISO / CIPO
D13 13 GPIO48 SCK / LED_BUILTIN
A0 17 GPIO1 ADC1_CH0
A1 18 GPIO2 ADC1_CH1
A2 19 GPIO3 ADC1_CH2
A3 20 GPIO4 ADC1_CH3
A4 21 GPIO11 SDA / ADC2_CH0
A5 22 GPIO12 SCL / ADC2_CH1
A6 23 GPIO13 ADC2_CH2
A7 24 GPIO14 ADC2_CH3

What “By Arduino Pin” Means

This is the default Nano ESP32 mode.

In this mode:

So this sketch:

does not mean GPIO2.

It means:

What “By GPIO Number” Means

If you select:

bare integers are interpreted as native ESP32-S3 GPIO numbers.

So:

means:

rather than Nano pin D5.

The Same Number Can Mean Two Different Physical Pins

This is the key problem.

Consider:

Arduino-pin mode

GPIO-number mode

The exact same source code controls a different physical pin.

Use Symbolic Pin Names Instead

This code is safe:

because D5 resolves correctly under either numbering mode.

In Arduino mode:

In GPIO mode:

Either way, the same physical D5 pin is used.

This Is the Recommended Coding Style

Use:

rather than:

for board-level code.

Why ESP32 Libraries Sometimes Break on Nano ESP32

Many libraries written for generic ESP32 boards assume:

For example, a library may expect:

but in Nano ESP32’s default Arduino mode:

This can cause:

  • displays not initialising;
  • SPI chip-select failures;
  • wrong interrupt pins;
  • motors or LEDs responding on unexpected pins;
  • boot problems if the wrong native GPIO is driven.

When to Use GPIO-Number Mode

GPIO-number mode can be useful when:

  • porting an existing ESP32-S3 project;
  • using a library that expects raw GPIO numbers;
  • following Espressif documentation directly;
  • working deeply with ESP-IDF APIs;
  • you want the code to match native ESP32 terminology.

But even in GPIO-number mode, symbolic Nano names still work.

When to Keep the Default Arduino-Pin Mode

Keep the default when:

  • you are writing a new Arduino sketch;
  • you want Nano-family portability;
  • you are following Arduino examples;
  • you use Nano carrier boards;
  • you want code to match the silkscreen.

For most users, there is little reason to change the default.

UART Pin Mapping

The default external serial pins are:

Use:

for the external UART while the USB serial connection uses the board’s native USB stack.

Why D0 Is Not GPIO0

This is perhaps the most visually confusing example.

On many ESP32 examples:

has boot-related significance.

On Nano ESP32:

Native:

is instead connected internally to the RGB LED path and other board functions.

SPI Pin Mapping

The Nano-compatible default SPI mapping is:

The safe code is:

or explicitly use:

Do Not Copy Generic ESP32 SPI Pin Numbers Blindly

A common ESP32 example may use something like:

for SCK, MOSI, MISO and CS.

Those numbers originate from older generic ESP32 board conventions.

They are not the Nano ESP32 default SPI header mapping.

I²C Pin Mapping

The default Nano I²C bus is:

Use:

and libraries will normally use the correct pins automatically.

I²C Can Be Remapped

ESP32-S3’s GPIO matrix allows I²C signals to be assigned to many available GPIOs.

But Arduino chose:

as the defaults for Nano compatibility.

Many libraries assume those defaults, so remap only when necessary.

Analog Pin Mapping

The analog header has another useful split.

Nano label Native GPIO ADC unit/channel
A0 GPIO1 ADC1_CH0
A1 GPIO2 ADC1_CH1
A2 GPIO3 ADC1_CH2
A3 GPIO4 ADC1_CH3
A4 GPIO11 ADC2_CH0
A5 GPIO12 ADC2_CH1
A6 GPIO13 ADC2_CH2
A7 GPIO14 ADC2_CH3

A0 Is Not “Pin 0”

In the default Arduino numbering layer:

So:

is the correct portable form.

Avoid:

because that literal changes meaning if GPIO-number mode is enabled.

ADC1 vs ADC2

Nano ESP32 maps:

ESP32 wireless operation can impose more constraints on ADC2 resources than ADC1.

For analog measurements during heavy Wi-Fi use, A0-A3 are generally the safer first choice.

Digital Pins Can Also Be Analog Inputs

The official Nano ESP32 pinout exposes ADC capability on several D pins as well.

For example:

and:

This is useful when the normal A0-A7 header is already occupied.

Built-In LED Mapping

The classic built-in single LED is:

So this works regardless of numbering mode:

RGB LED Mapping

The current Arduino-ESP32 Nano variant defines:

Use the symbolic names:

rather than hard-coding their software pin numbers.

Arduino’s hardware documentation also notes that some early limited-production boards used a different RGB LED arrangement with green and blue inverted.

Why Symbolic RGB Names Are Especially Important

Board revisions and core definitions can hide hardware details.

Your code should express:

rather than:

depending on assumptions about numbering mode or board revision.

Native USB Pins Are Not Normal Header GPIO

ESP32-S3 native USB uses:

on Nano ESP32.

These signals are connected to the USB-C interface and are not part of the normal D0-D13/A0-A7 header set.

Do not treat GPIO19/20 as spare generic header pins when using USB.

Internal Flash and PSRAM Also Consume ESP32-S3 Pins

Nano ESP32 uses the NORA-W106 module with:

  • 16 MB Flash;
  • 8 MB PSRAM.

Some ESP32-S3 GPIOs are therefore used internally by the module memory interface and are not available on the Nano headers.

This is another reason generic ESP32-S3 pinout diagrams should not be applied blindly to Nano ESP32.

Not Every ESP32-S3 GPIO Exists on the Nano Header

The ESP32-S3 has many GPIO numbers, but Nano ESP32 exposes only the subset needed for its Nano-compatible layout.

A generic example that says:

does not mean that GPIO35 is available on the Nano ESP32 header.

Always check the Nano-specific pinout.

Interrupts

Arduino documents all exposed Nano ESP32 GPIO as interrupt-capable.

Use:

Again, symbolic pin names avoid numbering-mode bugs.

PWM

ESP32-S3 PWM uses the LEDC peripheral and can be routed to many GPIOs.

When assigning PWM pins, use:

or whatever labelled pin you have chosen.

Do not convert to a raw GPIO unless the library specifically requires it.

Touch-Capable GPIOs

ESP32-S3 supports capacitive touch on a subset of GPIOs.

On Nano ESP32, touch capability is exposed through pins whose underlying native GPIO supports the touch peripheral.

If a library accepts raw ESP32 GPIO numbers, translate the Nano label using the mapping table before configuring touch input.

What Happens Inside the Arduino Core?

The Nano ESP32 variant file contains two alternative definitions.

In Arduino-pin mode, symbols are assigned Nano-style numbers:

The core then remaps those numbers to the actual ESP32-S3 GPIO.

In GPIO-number mode, the same symbols are defined directly as:

That is why symbolic names work in both modes.

Example: D2 in Both Modes

Arduino-pin mode

GPIO-number mode

The application source code does not change.

Example: Why Bare 2 Is Dangerous

Arduino-pin mode

GPIO-number mode

So switching the IDE option silently moves the output from D2 to A1.

Example: Why Bare 10 Is Dangerous

Arduino-pin mode

GPIO-number mode

A library using literal pin 10 as SPI CS could therefore change physical pins when the numbering option changes.

Best Practice for Libraries

If you are writing a library intended to support Nano ESP32, accept a pin value from the sketch rather than assuming a raw GPIO.

Good application code:

Less portable application code:

unless the library explicitly documents that it requires native ESP32 GPIO numbers.

How to Port Generic ESP32-S3 Code to Nano ESP32

Suppose an ESP32-S3 example contains:

Do not assume those are Nano pin numbers.

If the source means raw ESP32 GPIO:

Rewrite the Nano version as:

This makes the intent explicit and protects the sketch from numbering-mode changes.

How to Find the Nano Label for a Raw ESP32 GPIO

Use the mapping table in reverse.

Examples:

How to Find the Raw GPIO for a Nano Label

Examples:

Recommended Style for New Nano ESP32 Projects

Prefer code like:

This is clear, readable and independent of the selected pin-numbering mode.

Common Mistake 1: Copying ESP32 DevKit Pin Numbers

You find an example online:

and paste it into Nano ESP32.

That is a generic ESP32 convention, not the Nano ESP32 default.

Nano ESP32 uses:

Common Mistake 2: Assuming D13 Means GPIO13

It does not.

Meanwhile:

Common Mistake 3: Assuming A0 Means GPIO0

It does not.

Native GPIO0 is used by the board’s RGB LED path and boot-related hardware.

Common Mistake 4: Changing Numbering Mode to Fix One Library

Changing the global IDE pin-numbering mode may make one raw-GPIO library work but break other code that uses bare Nano numbers.

A better fix is normally:

  • use symbolic Nano pin constants everywhere you control;
  • translate raw GPIO requirements explicitly;
  • change numbering mode only when the entire project expects it.

Common Mistake 5: Using Bare Numbers in Shared Code

A line such as:

does not tell the reader whether:

Write:

or, if raw GPIO is deliberately required, comment it clearly.

Quick Mapping Reference

Final Recommendation

For almost every Nano ESP32 Arduino sketch:

Switch to raw GPIO-number mode only when you are deliberately porting ESP32 code or using software that explicitly requires native GPIO values.

The core lesson is:

Once that distinction is understood, Nano ESP32 pin handling becomes straightforward.

For the full board hardware reference, see our Arduino Nano ESP32 pinout guide. For comparison with the standard Espressif development board, see Nano ESP32 vs ESP32-S3 DevKitC-1.

Share your love