Hello friends, I hope you all are doing great. Today, I am going to share the LilyGO T-Display S3 Library for Proteus. The T-Display S3 is one of the most popular ESP32 boards with a screen: an ESP32-S3 with 8 MB of PSRAM, a bright 1.9" 170 x 320 IPS display, two buttons and a battery connector, all on a board the size of a pack of chewing gum. With this library it runs your ESP32-S3 Arduino sketch in Proteus 8.5 - the display shows what your sketch draws - and joins our virtual Wi-Fi network.

Updates

LilyGO T-Display S3 Library for Proteus

Latest version: V1.0 (October 2026, this tutorial)

Other ESP32 boards and modules: ESP32 DevKit V1 · ESP32-DevKitC V4 · ESP32-S3 DevKitC-1 · ESP32-C3 SuperMini · ESP32-C6 DevKitC-1 · TTGO T-Display · XIAO ESP32-C3 · LOLIN S2 Mini · Heltec WiFi LoRa 32 V3 · LilyGO T-Beam · ESP32-CAM · ESP32-WROOM-32 · AirLift WiFi Shield · AirLift ESP32 Breakout · WT32-ETH01

Other displays: OLED · Nokia 5110 · LCD 128x64 · ST7735 · ST7789 · ILI9341 · TFT Shield 2.4 inch · TFT Shield 3.5 inch · E-Paper

Infrared sensors: IR Obstacle FC-51 · IR Proximity · IR Tracker · Sharp IR · IR Remote

Helping Tools

For the demo we made a kitchen timer with an IR remote. A VS1838B receiver picks up the remote, the sketch decodes the NEC frames itself, the display shows a menu of two screens with a big countdown, and a phone and a laptop start, pause and reset the timer on the board's web page.

NOTICE: Proteus has no ESP32-S3 model, so our team has put a lot of effort into building this board ourselves: the board's pins, the display, Wi-Fi and the buttons are all our own model, and your sketch compiles with our free TEP Boards for Proteus add-on. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the LilyGO T-Display S3 board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the LilyGO T-Display S3 Library for Proteus:

Figure: The LilyGO T-Display S3 Library for Proteus: the timer counting down on the 1.9" display - the PWR LED on, the antenna green on Wi-Fi, the IR receiver on GPIO1.

What is the LilyGO T-Display S3?

LilyGO's T-Display S3 came out in 2022 as the big brother of the original TTGO T-Display. It moves to the ESP32-S3R8 - two Xtensa LX7 cores at 240 MHz, 512 KB of RAM plus 8 MB of PSRAM, 16 MB of flash, Wi-Fi and Bluetooth LE - and to a larger 1.9" IPS display with 170 x 320 pixels and an ST7789 controller. The display is driven on an 8-bit parallel bus, much faster than SPI, so full-screen animations run smoothly. The board adds a BOOT and a KEY button, a reset button on the side, a JST connector for a LiPo cell with its charger, and a 4-pin I2C connector.

The two T-Display boards
LilyGO T-Display S3TTGO T-Display (ESP32)
ProcessorESP32-S3R8, two LX7 cores at 240 MHzESP32, two LX6 cores at 240 MHz
Memory512 KB RAM, 8 MB PSRAM, 16 MB flash520 KB RAM, 4 MB flash
Display1.9", 170 x 320, ST7789, 8-bit parallel1.14", 135 x 240, ST7789, SPI
USBUSB-C, the S3's own USBUSB-C through a CH9102 bridge
ButtonsBOOT (GPIO0), KEY (GPIO14), RSTGPIO0, GPIO35, RST
Header2 x 12 pins2 x 12 pins

Our TTGO T-Display Library for Proteus is the first T-Display, and the display model inside both comes from our ST7789 TFT LCD Library for Proteus. For the same S3 chip without a screen see the ESP32-S3 DevKitC-1 Library for Proteus.

Why the T-Display S3?

A screen changes what a small project can do: a clock, a weather station, a sensor dashboard, a menu for settings, a game - without wiring a display module. The T-Display S3 has that screen built in, a battery connector for portable builds and the S3's speed for smooth graphics, and it still costs about as much as a bare ESP32 board with a separate display.

Features of the LilyGO T-Display S3 Library for Proteus

  • The board as it looks: the black T-Display S3 with its USB-C port, BOOT, KEY and RST, the PWR LED, the 1.9" display between the two 12-pin rows, the PCB antenna and the PANEL pad.
  • The display: 170 x 320, ST7789, IPS - it shows what your sketch draws with Adafruit_ST7789 and Adafruit_GFX, with the backlight.
  • Your sketch: a .hex for "LilyGO T-Display S3 (TEP Proteus)" with the S3's GPIO numbers - the header's 1, 2, 3, 10 to 13, 16, 17, 18, 21, 43 and 44, analogRead 0 to 4095, PWM, attachInterrupt, micros, pulseIn, the buttons.
  • Wi-Fi: WiFi.begin, WebServer, HTTPClient, mDNS and NTP on our virtual router TEP-WiFi; the board is 192.168.1.101 in the demo.
  • The panel and the serial monitor: the board's panel (Wi-Fi, Pins, Test) and the built-in serial monitor with Monitor, Plotter and Board tabs - our TEP header, no Windows title bar.
  • A complete package: about 3.1 MB with the board, the add-on, the IR receiver and monitor libraries and the demo, without the source code of the models.

The LilyGO T-Display S3 in Proteus

Figure: The part as the library draws it: the top row 5V to 3V3, the bottom row GND to 3V3, BOOT, KEY and RST, the display between the rows and the antenna green on Wi-Fi.

Search T-DISPLAY in Pick Devices; the device LILYGO T-DISPLAY S3 is in TEPTDISPLAYS3.LIB (Microprocessor ICs, ESP32 Boards), with the prefix U. The board lies with the USB-C port on the left. Click the USB-C port to open the serial monitor and the PANEL pad (or the display) to open the board's panel.

Figure: U1 in the demo: the IR receiver's OUT runs to GPIO1; its VCC and GND go to labels.

The Pins

The pins in the library
PinsWhat the library does with them
1, 2, 3, 10 to 13, 16GPIO, analogRead 0 to 4095, PWM, interrupt
21GPIO, PWM, interrupt
18 / 17Wire SDA / SCL
43 / 44Serial0 TX / RX
3V3, 5V, GND3.3 V, 5 V, ground
NCnot connected
On the boardthe display, BOOT (GPIO0), KEY (GPIO14), the battery (GPIO4), the USB (Serial)

The Display in Proteus

On the real board the ST7789 sits on an 8-bit parallel bus. In Proteus our display model listens on the board's SPI instead, so the sketch talks to it through Adafruit's library - the same drawing calls (fillScreen, setCursor, print, fillRect) that TFT_eSPI and Arduino_GFX offer on the real board. Three lines start it, after the LCD power (GPIO15) and the backlight (GPIO38) are switched on, as in LilyGO's own examples:

  tft.init(170, 320);
  tft.setRotation(1);
  tft.fillScreen(ST77XX_BLACK);

Download LilyGO T-Display S3 Library for Proteus

Click the button below to download LilyGO-T-Display-S3-Library-for-Proteus-v1.0.zip (about 3.1 MB, without the source code of the models):

LilyGO T-Display S3 Library for Proteus V1.0
  • README.txt: installation, the demo, the pins, the properties, troubleshooting and the limits.
  • Proteus Library Files: TEPTDISPLAYS3.LIB and the demo's parts: TEPIRREMOTE.LIB, TEPLAPTOP.LIB and TEPMOBILE.LIB.
  • Proteus Model Files: TEPNET.DLL (the board, its display, the laptop, the phone and the network) and TEPIRREMOTE.DLL.
  • Arduino Code: the demo sketch and the TEP Boards for Proteus add-on 1.23.0.
  • Proteus Simulation: the demo project, its HEX file and copies of the DLLs.

No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.

How to Install LilyGO T-Display S3 Library for Proteus

  1. Close Proteus and extract the whole zip file, for example to your Desktop.
  2. Copy the files from Proteus Library Files into the LIBRARY folder of Proteus.
  3. Copy the DLLs from Proteus Model Files into the MODELS folder, replacing an older TEPNET.DLL.
  4. Delete TEPTDISPLAYS3.IDX from the LIBRARY folder if it is there.
  5. For your own sketches, copy Arduino Code\TEP Boards for Proteus\hardware into your Arduino sketchbook (Documents\Arduino) and restart the Arduino IDE; the board is LilyGO T-Display S3 (TEP Proteus). Install Adafruit ST7735 and ST7789 and Adafruit GFX from the Library Manager.
  6. Start Proteus, press P and search for T-DISPLAY.

Demo: an IR Kitchen Timer

A kitchen timer is a small job with a real need for a remote: your hands are busy, flour on your fingers, and the timer is across the room. The cheap 21-key remotes sold with IR receiver kits are perfect for it - number keys to type the time and a play key to start. The T-Display S3 shows the countdown big enough to read from the cooker.

Open T-Display-S3-IR-Timer.pdsprj. U1 runs TDisplayS3_IR_Timer.hex. U2 is the receiver with its remote from our IR Receiver + Remote Library for Proteus - the Advance version: it opens its pop-up window at Run, with the remote to click and a live view of every frame. PC1 is the Laptop WiFi Monitor and MOB1 the Mobile WiFi Monitor.

Figure: The whole demo: U1 at the centre, the IR receiver and its remote at the right, the laptop and the phone.
The wiring of the IR timer
Receiver pinConnected toWhat it does
OUTGPIO1LOW while it sees the 38 kHz light
VCCthe VCC labelthe supply (3V3 on a real board)
GNDthe GND labelground

How an IR Remote Talks

The remote's LED does not just switch on: it flashes at 38 kHz, and the receiver only reacts to light flashing at that rate - sunlight and lamps are ignored. While it sees the 38 kHz light, the VS1838B pulls OUT LOW. The NEC protocol, used by most cheap remotes, sends a 9 ms burst and a 4.5 ms pause as a header, then 32 bits: an address, its inverse, a command and its inverse. Every bit is a 562 us burst followed by a short pause (a 0) or a long one (a 1). Held down, the remote sends a short repeat code every 108 ms.

The remote's keys (address 0x00)
KeyCommandIn the timer
0 to 90x16, 0x0C, 0x18, 0x5E, 0x08, 0x1C, 0x5A, 0x42, 0x52, 0x4Atype the time
>||0x43start / pause
EQ0x09clear
+ and -0x15, 0x07add / take 10 s
100+0x19add a minute
CH+ and CH-0x47, 0x45switch the screen

Why send every byte twice, once inverted? A 0 and a 1 differ only in the length of a pause, and a flash of sunlight or a lamp can stretch or cut a pause. With the inverse beside it, a byte that changed on the way no longer matches its partner, so the receiver knows the frame is broken and drops it instead of acting on a wrong key. The address lets two devices in one room use the same command numbers without answering each other's remote.

Decoding NEC Without a Library

Instead of a library the sketch measures the gaps between falling edges of OUT: from the start of one burst to the start of the next. The header gives 13.5 ms, a 0 gives 1.125 ms, a 1 gives 2.25 ms and a repeat code 11.25 ms - four numbers far enough apart that a little timing error does not matter. An interrupt on every falling edge does the work:

void IRAM_ATTR onFall() {
  unsigned long now = micros(), gap = now - lastFall;
  lastFall = now;
  if (gap > 12500 && gap < 14500) { nBits = 1; bits = 0; return; }          // the leader: 9 ms + 4.5 ms
  if (gap > 10500 && gap < 12300) { repeatReady = true; nBits = 0; return; } // the repeat code: 9 ms + 2.25 ms
  if (nBits == 0) return;
  if (gap > 900 && gap < 1500) bits >>= 1;                                   // a 0: 562 + 562 us (LSB first)
  else if (gap > 1900 && gap < 2600) bits = (bits >> 1) | 0x80000000UL;      // a 1: 562 + 1687 us
  else { nBits = 0; return; }                                                // broken: wait for the next leader
  if (++nBits == 33) { frame = bits; frameReady = true; nBits = 0; }
}

NEC sends the least significant bit first, so each new bit enters at the top and the word shifts right. The main loop takes a finished frame and checks that the command and its inverse agree - a broken frame is simply ignored:

void readRemote() {
  if (frameReady) {
    noInterrupts(); unsigned long f = frame; frameReady = false; interrupts();
    uint8_t cmd = (f >> 16) & 0xFF, inv = (f >> 24) & 0xFF;
    if ((uint8_t)(cmd ^ inv) == 0xFF) onKey(cmd);             // the command and its inverse must agree
  }
  repeatReady = false;                                        // (a held key is not repeated here)
}

Typing the Time

Digits fill the MM:SS display from the right, like a microwave oven: 3 then 0 gives 00:30, a third digit 5 would give 03:05. The sketch keeps the time in seconds and rebuilds the four digits for each key:

  for (int d = 0; d < 10; d++)
    if (code == CODES[d]) {                                   // a digit: MM:SS fills from the right
      long mmss = (leftSec / 60) * 100 + leftSec % 60;
      mmss = (mmss * 10 + d) % 10000;
      setTimer((mmss / 100) * 60 + mmss % 100, "the remote");
      return;
    }

The Screens

The display shows a menu of two screens: TIMER with the big countdown and a bar of the time left, and INFO with the network and the remote's last key. CH+ and CH- (or the board's BOOT button) switch between them. The countdown redraws only the digits, the state and the bar each second - the text is drawn with a background colour, so no flicker:

void drawTimer() {
  char buf[8];
  snprintf(buf, sizeof buf, "%02ld:%02ld", leftSec / 60, leftSec % 60);
  tft.setTextSize(8); tft.setCursor(40, 38);
  tft.setTextColor(timeUp ? ST77XX_RED : running ? ST77XX_GREEN : ST77XX_WHITE, ST77XX_BLACK);
  tft.print(buf);
  tft.fillRect(8, 112, 96, 16, ST77XX_BLACK);
  tft.setTextSize(2); tft.setCursor(8, 112);
  tft.setTextColor(timeUp ? ST77XX_RED : ORANGE, ST77XX_BLACK);
  tft.print(stateText());
  int w = setSec ? (int)(200L * leftSec / setSec) : 0;          // the bar: the time left of the time set
  tft.drawRect(108, 112, 204, 16, ST77XX_WHITE);
  tft.fillRect(110, 114, w, 12, running ? ST77XX_GREEN : ORANGE);
  tft.fillRect(110 + w, 114, 200 - w, 12, ST77XX_BLACK);
}

Wi-Fi and the Page

The web server has a page for the phone with START, PAUSE, RESET and +1 MIN, and a JSON page for programs:

  server.on("/", handleRoot); server.on("/json", handleJson); server.on("/start", webStart);
  server.on("/pause", webPause); server.on("/reset", webReset); server.on("/plus", webPlus);

Run the Demo

Press Run. The serial monitor opens and the board joins TEP-WiFi. On the remote in the receiver's pop-up click 3 and 0:

T-Display S3 IR Timer - The Engineering Projects
Connecting to TEP-WiFi
Timer page: http://192.168.1.101/
Key 0x5E
Timer set to 0 min 3 s (from the remote)
Key 0x16
Timer set to 0 min 30 s (from the remote)
Figure: The serial monitor: the page's address and the keys 3 and 0 - the timer set to 30 s.
Figure: The receiver's pop-up: the remote, key 0 received (command 0x16) and the frame - the header and the 32 bits.
Figure: The display: 00:30, SET.
Figure: The board's panel: on TEP-WiFi, the router's list, the address 192.168.1.101.

Start: the Countdown

Click >||. The timer starts: the digits turn green and the bar shrinks every second.

Figure: The running T-Display S3 with its LED on: the PWR LED, the antenna green on Wi-Fi and the countdown on the display.

On the laptop click Browser and Go (the home page is http://192.168.1.101/json); on the phone the same with http://192.168.1.101/:

Figure: The laptop: the JSON - the time left, the time set, the state and the keys received.
Figure: The phone: the time left, RUNNING, and START, PAUSE, RESET and +1 MIN.

The INFO Screen

Click CH+: the INFO screen shows the network and the remote's last key. CH- goes back to the timer, which kept counting.

Figure: The INFO screen: the SSID, the address, the signal and the keys received.

Pause and Start from the Phone

Tap PAUSE on the phone: the countdown stops, the bar turns orange. START goes on.

Figure: The phone after PAUSE.
Figure: The display: PAUSED.

Time Up

At 00:00 the digits turn red and the display says TIME UP; the page and the JSON say so too:

Figure: The display at 00:00: TIME UP in red.
Figure: The phone after REFRESH: TIME UP.
Figure: The laptop after Go: "left":0 and "state":"TIME UP".
Figure: The demo at the end: the display red, the antenna green, the laptop and the phone on TEP-WiFi.

The built-in serial monitor, in the look of our TEP Serial Monitor Advance for Proteus, logs every key and every change:

Key 0x43
Timer started (from the remote)
Key 0x47
Key 0x45
Timer paused (from the web page)
Timer started (from the web page)
TIME UP
Figure: The serial monitor after the run: the keys, the starts and pauses, TIME UP.
Figure: The monitor's Board tab: every GPIO live, the PWR LED, RESET, BOOT and KEY.

Try It Yourself

  • Click HOLD + 1 s on the receiver's pop-up: the remote sends repeat codes - the sketch ignores them, so a held key counts once.
  • Move the remote away with DISTANCE: past its reach the frames break and the timer does not react.
  • Press the board's KEY button to start and pause, BOOT to switch the screen.
  • Type STATUS, START, PAUSE or RESET in the monitor.

Ideas to Extend the Timer

  • Add a buzzer on a free pin that beeps at TIME UP.
  • Keep several timers (eggs, pasta, oven) and choose them with |<< and >>|.
  • Show the time of day from NTP on a third screen.
  • Learn any remote: print unknown codes and store them as keys with Preferences.

Your Own Sketches

Write the sketch in the Arduino IDE with the board LilyGO T-Display S3 (TEP Proteus), use Sketch > Export Compiled Binary and set the board's PROGRAM property to the .hex. For the real T-Display S3 select "LilyGo T-Display-S3" in Espressif's "esp32" package; the IR decoder, the timer, the buttons and the web page stay the same, and the drawing goes through TFT_eSPI with LilyGO's setup or through Arduino_GFX on the parallel bus.

Things to Know Before Using a Real T-Display S3

  • GPIO15 powers the LCD: set it HIGH first, or the display stays dark on battery power.
  • USB CDC: Serial goes over the S3's own USB; enable "USB CDC On Boot" in the IDE to see it.
  • The receiver on 3.3 V: the VS1838B works from 2.7 V, so it sits on the 3V3 pin and OUT goes straight to a GPIO.
  • The battery: GPIO4 reads half the battery voltage only when USB is unplugged.
  • Flash and PSRAM: choose "OPI PSRAM" and 16 MB flash in the IDE's Tools menu.

Properties of the LilyGO T-Display S3

Double-click the T-Display S3 to change them
PropertyWhat it does
PROGRAMthe sketch: a .hex from TEP Boards for Proteus (board "LilyGO T-Display S3")
WIFISSID, WIFIPASSthe router in range (TEP-WiFi, 12345678)
MONITOR, BAUD, AUTOOPENthe built-in serial monitor: on, its baud rate (115200), open at Run
TIMEthe clock for NTP: PC or a fixed UTC time

Troubleshooting

  • The display stays dark: GPIO15 and GPIO38 HIGH; tft.init(170, 320) and setRotation(1).
  • The picture is shifted: the display is 170 x 320 - not 135 x 240 or 240 x 320.
  • The remote does nothing: the receiver's OUT on GPIO1, its VCC on the power rail; the remote within reach.
  • The board stays off the network: the sketch's SSID and password must match WIFISSID and WIFIPASS.
  • A number goes wrong above 32767: int is 16 bits in the simulation - use long.

Limitations of the Simulation

  • Your sketch gets 8 KB of RAM in the simulation and runs slower than on the S3's two 240 MHz cores with 512 KB and 8 MB of PSRAM.
  • The display is reached over SPI instead of the 8-bit parallel bus; PSRAM, Bluetooth LE, the battery charger and the native USB devices are not modelled. One T-Display S3 per design.
  • The router, the addresses and the windows are TEP additions.
  • LilyGO and T-Display are names of LilyGO, ESP32-S3 of Espressif Systems; this library is not made or endorsed by them or by Labcenter.
  • Tested in Proteus 8.5 in October 2026 (the demo as shipped, about 46 s of simulation). Proteus 7 is not supported.

So, that was all about the LilyGO T-Display S3 Library for Proteus. I hope it helps you build and test your T-Display S3 projects before you touch the hardware - the screen, the remote, the buttons and the web page in one simulation. If you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!