Documentation
Onboarding
Getting Started
Power & Battery
Hardware & Components
Build & Assembly
Radio & RF Design
Frequencies & Regulations
Firmware & Software
USB & Connectivity
GPS & Navigation
Morse & Communication
Modes & Operation
Field Operations & Rescue
Building Effectively
Build Variants
Project & Reference
Docs Hardware & Components Display GPIO and Pin Reference

Display GPIO and Pin Reference

Edit on GitHub

One GPIO/pin table per supported display: SSD1309 OLED, ST7735 TFT, HD44780 LCD 16x2 and 20x4, with the exact firmware pin defines, bus sharing, and how to remap a pin when you have a conflict.

Display GPIO and Pin Reference

This page is the single place to look when you are wiring a display and want to know exactly which ESP32 pins the firmware uses for each screen type.

Only one display is mounted at a time. The OLED and the TFT share an identical 5-pin software SPI bus. The two character LCDs share an identical 6-pin 4-bit parallel bus. If you have the display in front of you, go straight to its table.

All pin numbers below come from AegisBeacon.ino. If you remap any pin there, update the #define for that pin and recompile — the wiki and the dashboard both describe the default wiring only.

Summary table

DisplayDISPLAY_TYPEInterfaceGPIOs usedPower
SSD1309 2.42” OLED1 (default)Software SPI (7-pin)15, 13, 4, 16, 173.3 V
ST7735 1.8” TFT2Software SPI (7-pin)15, 13, 4, 16, 173.3 V
HD44780 LCD 16x234-bit parallel (6 GPIOs)16, 17, 13, 15, 4, 125 V + 3.3 V logic
HD44780 LCD 20x444-bit parallel (6 GPIOs)16, 17, 13, 15, 4, 125 V + 3.3 V logic
HD44780 LCD 16x2 I2C5PCF8574 I2C backpack13 (SDA), 15 (SCL)5 V
HD44780 LCD 20x4 I2C6PCF8574 I2C backpack13 (SDA), 15 (SCL)5 V

The two SPI displays use the same five GPIOs. The two parallel character displays use the same six GPIOs. The two I2C types use two GPIOs, the same pair as the SPI bus. You switch between screens by changing DISPLAY_TYPE and rewiring the display itself.


Display type 1 — SSD1309 2.42” OLED

Default screen. Software SPI on a 7-pin header.

Pin defines in the firmware

CODE
#define PIN_OLED_SCK   15
#define PIN_OLED_SDA   13
#define PIN_OLED_RES   4
#define PIN_OLED_DC    16
#define PIN_OLED_CS    17

Constructor:

CODE
U8G2_SSD1309_128X64_NONAME0_F_4W_SW_SPI u8g2(
  U8G2_R0,
  PIN_OLED_SCK,
  PIN_OLED_SDA,
  PIN_OLED_CS,
  PIN_OLED_DC,
  PIN_OLED_RES
);

Pin table

Display pinESP32 GPIONotes
GNDGNDCommon ground
VCC3V33.3 V only
SCK (D0)GPIO 15Software SPI clock
SDA (D1 / MOSI)GPIO 13Software SPI data
RES (RESET)GPIO 4Hardware reset
DC (A0)GPIO 16Data / command select
CSGPIO 17Chip select, active low

Notes

  • This is software SPI, deliberately separate from the radio’s hardware VSPI bus. The OLED and the radio can run at the same time.
  • The panel must be the 7-pin SPI version. The 4-pin I2C version has the same SSD1309 chip but no SCK/SDA/DC/CS pins and will not work.
  • Display power is 3.3 V. Do not power it from 5 V.
  • If the panel shows nothing, check the 7-pin header pinout against the module silkscreen before blaming the firmware. Some breakers label SCK as D0 and SDA as D1.

Display type 2 - ST7735 1.8” TFT

Color screen. Same 5 GPIOs as the OLED.

Pin defines in the firmware

The TFT reuses the same #defines as the OLED:

CODE
#define PIN_OLED_SCK   15
#define PIN_OLED_SDA   13
#define PIN_OLED_RES   4
#define PIN_OLED_DC    16
#define PIN_OLED_CS    17

Constructor:

CODE
Adafruit_ST7735 tft = Adafruit_ST7735(
  PIN_OLED_CS,
  PIN_OLED_DC,
  PIN_OLED_SDA,
  PIN_OLED_SCK,
  PIN_OLED_RES
);

Pin table

Module pinESP32 GPIONotes
GNDGNDCommon ground
VCC3V33.3 V only
SCKGPIO 15SPI clock, same bus as the OLED
SDA (MOSI)GPIO 13SPI data, same bus as the OLED
RESETGPIO 4Hardware reset, same bus as the OLED
DC (A0)GPIO 16Data / command select, same bus as the OLED
CSGPIO 17Chip select, active low, same bus as the OLED
LED / BL3V3Backlight, keep always on

Notes

  • The OLED and the TFT share the same bus. Only one can be connected at a time. Disconnect the OLED before connecting the TFT and vice versa.
  • The backlight (LED / BL) is powered from 3.3 V and is always on. If your module has a separate backlight enable pin, tie it to 3.3 V or pin it out according to the module silkscreen.
  • The firmware initialises the panel with INITR_BLACKTAB and rotation 0. If your module shows garbage on boot, the init tab may differ (some panels are INITR_RED_TAB). That is a module difference, not a wiring fault.
  • The display uses the full 128x160 pixel area. The UI is not centred in a smaller box; it fills the panel.

Display type 3 - HD44780 LCD 16x2

Character display, 4-bit parallel bus on 6 GPIOs.

Pin defines in the firmware

CODE
#define PIN_LCD_RS    16
#define PIN_LCD_EN    17
#define PIN_LCD_D4    13
#define PIN_LCD_D5    15
#define PIN_LCD_D6    4
#define PIN_LCD_D7    12

Constructor:

CODE
LiquidCrystal lcd(PIN_LCD_RS, PIN_LCD_EN,
                  PIN_LCD_D4, PIN_LCD_D5,
                  PIN_LCD_D6, PIN_LCD_D7);

Initialisation:

CODE
lcd.begin(16, 2);   // from DISP_COLS / DISP_ROWS

Pin table

LCD pinESP32 GPIONotes
VSSGNDGround
VDD5VPower (external 5 V or USB)
V0 (contrast)10k pot wiperAdjust until text is clear
RSGPIO 16Register select
RWGNDWrite-only; saves a GPIO
ENGPIO 17Enable pulse
D4GPIO 13Data bit 4
D5GPIO 15Data bit 5
D6GPIO 4Data bit 6
D7GPIO 2Data bit 7 - strap pin, boot-safe (high-Z input)
A (backlight +)5V via 100ΩBacklight anode
K (backlight -)GNDBacklight cathode

Notes

  • The LCD logic runs on 5 V, but the data lines (RS, EN, D4–D7) are 3.3 V from the ESP32. Most HD44780 modules accept 3.3 V logic levels on a 5 V supply; if your module is picky, use a level shifter on the six data/control lines.
  • R/W is tied to GND. The firmware never reads the display, so the write-only bus saves one GPIO.
  • D7 is on GPIO 2. GPIO 2 is a strapping pin, but the HD44780 data line is a high-impedance input on the ESP32 side, so it cannot disturb the boot sample. The GPS no longer shares any LCD pin: the firmware never transmits to the GPS and PIN_GPS_TX is left unconnected, so the GPS/LCD conflict that existed in earlier releases is gone entirely.
  • Contrast is mandatory. Without the potentiometer on V0 the display shows a faint rectangle or nothing at all.
  • Backlight current is significant on battery builds. If you want to reduce it, raise the series resistor on the A line or switch the backlight off in bright environments.

Display type 4 - HD44780 LCD 20x4

Character display, same 6 GPIOs as the 16x2, same constructor call.

Pin defines in the firmware

Exactly the same as the 16x2:

CODE
#define PIN_LCD_RS    16
#define PIN_LCD_EN    17
#define PIN_LCD_D4    13
#define PIN_LCD_D5    15
#define PIN_LCD_D6    4
#define PIN_LCD_D7    12

Constructor:

CODE
LiquidCrystal lcd(PIN_LCD_RS, PIN_LCD_EN,
                  PIN_LCD_D4, PIN_LCD_D5,
                  PIN_LCD_D6, PIN_LCD_D7);

Initialisation:

CODE
lcd.begin(20, 4);   // from DISP_COLS / DISP_ROWS

Pin table

LCD pinESP32 GPIONotes
VSSGNDGround
VDD5VPower (external 5 V or USB)
V0 (contrast)10k pot wiperAdjust until text is clear
RSGPIO 16Register select
RWGNDWrite-only
ENGPIO 17Enable pulse
D4GPIO 13Data bit 4
D5GPIO 15Data bit 5
D6GPIO 4Data bit 6
D7GPIO 2Data bit 7 - strap pin, boot-safe (high-Z input)
A (backlight +)5V via 100ΩBacklight anode
K (backlight -)GNDBacklight cathode

Notes

  • The 20x4 uses the same six GPIOs and the same constructor call as the 16x2. The only difference is the display module itself and the lcd.begin(20, 4) call, which the firmware makes automatically from DISP_COLS and DISP_ROWS.
  • You can swap a 16x2 for a 20x4 and back again without changing any wiring, only DISPLAY_TYPE.
  • D7 is on GPIO 2, boot-safe for this use because the HD44780 data line is a high-impedance input. The GPS shares no LCD pin at all: its TX line is unconnected because the firmware never transmits to the module.
  • The 20x4 shows a third and fourth row on every screen where the firmware has one. That is the main reason to choose it over the 16x2: coordinates, decoded Morse, and scan history can stay on screen at the same time.

Bus sharing and what can be connected together

The display buses are exclusive stacks:

  • SPI bus (OLED + TFT): same five GPIOs, one display at a time.
  • LCD bus (16x2 + 20x4): same six GPIOs, one display at a time.

You cannot mix SPI and LCD simultaneously without changing pins in the firmware, and you cannot mix the 16x2 and the 20x4 without rewiring the display itself (they use the same pins).

CombinationPossible with default pins?
OLED + Radio (VSPI)Yes - different buses
TFT + Radio (VSPI)Yes - different buses
OLED + TFTNo - same bus, one at a time
LCD 16x2 + LCD 20x4No - same bus, one at a time
LCD + GPSYes, with no conflicts: D7 is on GPIO 2 (strap-safe) and the GPS TX line is unconnected.

Moving a pin when you have a conflict

There are no default conflicts left between the displays and the GPS: D7 sits on GPIO 2 (boot-safe high-Z input) and the GPS TX line is unconnected.

To move D7:

  1. Pick a free GPIO. GPIO 14 is a safe choice on the 30-pin DevKit V1; it is also the SX1262 reset pin, so only use it if the display is the only screen and you are not building the radio version with the default reset pin. GPIO 2 carries the LCD D7 line (boot-safe: the HD44780 input is high-impedance) and GPIO 39 carries the radio DIO1 line. Avoid GPIO 12 (MTDI strap) entirely.
  2. In AegisBeacon.ino, change #define PIN_LCD_D7 to the new GPIO.
  3. Recompile and flash.

If you move D7, update the wiki pin tables on your copy if you publish a derivative, because the default wiring no longer matches.

The SPI pins (15, 13, 4, 16, 17) are shared between the OLED and the TFT and are part of the default radio layout only in the sense that the radio uses VSPI on 18/19/23/5. The display SPI pins are a separate software bus and do not conflict with the radio GPIOs. You can move them, but then the OLED and TFT are no longer drop-in interchangeable, so only do that when you have a specific reason.


Contrast and power for the character LCDs

Both LCDs need contrast on V0. Use a 10k potentiometer between 5V and GND with the wiper on V0. If you see blocks but no text, the contrast is wrong; if you see nothing and the backlight is on, check V0 first before chasing GPIO wiring.

Backlight current on the LCDs is much higher than on the OLED. If battery runtime matters and you are using a character display, consider lowering the backlight current with a larger series resistor on the A line, or switching the backlight off when the unit is in a well-lit environment.


Quick checklist

  • DISPLAY_TYPE matches the display you have wired.
  • For OLED/TFT: 3.3 V, not 5 V.
  • For LCD: 5 V on VDD, 3.3 V logic on RS/EN/D4–D7 is usually fine, contrast pot on V0.
  • For LCD + GPS with a 20x4: nothing to move, D7 on GPIO 2 and GPS TX unconnected.
  • Only one display connected at a time.
  • OLED is the 7-pin SPI version, not the 4-pin I2C version.
  • TFT backlight (LED/BL) tied to 3.3 V.
  • Serial monitor at 115200 shows the display init line if you want confirmation: OLED ready - SSD1309 128x64, Display ready - ST7735 128x160 (color), or Display ready - LCD 20x4.