Skip to main content

ESP32 Pin Mapping

This article explains the mapping between ESP32 on-chip peripherals and the TuyaOpen TKL layer's software ports and pins โ€” covering the correspondence between TUYA_GPIO_NUM_E enum values and physical GPIO numbers, and how to route peripherals to specific pins using the pinmux interface.

Common Pin Mapping Mechanicsโ€‹

These mechanisms apply to all ESP32 chip variants.

GPIO Number Mappingโ€‹

TuyaOpen uses a direct 1:1 mapping on ESP32: TUYA_GPIO_NUM_E enum values map directly to physical ESP32 GPIO numbers. TUYA_GPIO_NUM_18 operates on physical GPIO18, TUYA_GPIO_NUM_5 operates on physical GPIO5, and so on.

This mapping is defined in the pinmap[] array in tkl_pin.c. The available GPIO range varies by chip variant.

For the available GPIO range per chip, see the Per-Platform Pin Mapping Docs below.

Pinmux (Pin Multiplexing)โ€‹

What it does: ESP32 on-chip peripherals (I2C, PWM, UART, etc.) are not hardwired to fixed pins โ€” they can be flexibly routed to different GPIOs. The TKL tkl_io_pinmux_config() function wraps this capability, letting developers assign a peripheral function to a specific pin before initialization.

When to use it:

  • The board's default pins conflict with your hardware design (e.g., a pin is occupied by another peripheral)
  • Your custom board does not follow TuyaOpen's default pin assignments
  • Your application uses multiple instances of the same peripheral type (e.g., two I2C buses) that need separate pins

How to use it: Call tkl_io_pinmux_config() before the corresponding tkl_xxx_init():

// Route I2C0 to GPIO42 (SCL) and GPIO41 (SDA)
tkl_io_pinmux_config(TUYA_GPIO_NUM_42, TUYA_IIC0_SCL);
tkl_io_pinmux_config(TUYA_GPIO_NUM_41, TUYA_IIC0_SDA);
tkl_i2c_init(TUYA_I2C_NUM_0, &cfg); // picks up the pin assignment above

// Route PWM0 to GPIO5
tkl_io_pinmux_config(TUYA_GPIO_NUM_5, TUYA_PWM0);
tkl_pwm_init(TUYA_PWM_NUM_0, &pwm_cfg);
Note

tkl_io_pinmux_config() must be called before the corresponding tkl_xxx_init(). Calling it after initialization has no effect.

Per-Platform Pin Mapping Docsโ€‹

Each ESP32 chip variant has a dedicated pin mapping document covering its GPIO range, UART defaults, and board configurations:

  • ESP32 (Classic) -- Dual-core Xtensa LX6, GPIO 0โ€“39
  • ESP32-S3 -- Dual-core Xtensa LX7, GPIO 0โ€“48, AI/audio capable
  • ESP32-C3 -- Single RISC-V core, GPIO 0โ€“21, cost-optimized
  • ESP32-C6 -- Single RISC-V core, GPIO 0โ€“30, Wi-Fi 6

ADC Mappingโ€‹

ADC on ESP32 uses a port + channel bitmask model in tkl_adc.c:

TuyaOpen PortESP-IDF UnitNotes
TUYA_ADC_NUM_0ADC_UNIT_1Always available
TUYA_ADC_NUM_1ADC_UNIT_2Unavailable during Wi-Fi on classic ESP32

Channel selection: cfg->ch_list.data is a bitmask where bit N enables ADC_CHANNEL_N.

Fixed settings: Attenuation is ADC_ATTEN_DB_12 (~0โ€“3.3 V range). tkl_adc_ref_voltage_get() returns 3300 mV. Calibration uses curve-fitting (S2/S3/C3/C6) or line-fitting (classic ESP32).

Not supported: tkl_adc_temperature_get() returns OPRT_NOT_SUPPORTED. Use the ESP-IDF temperature sensor driver instead.

Referencesโ€‹