Hello friends, I hope you all are doing great. Today, I am going to share the new TFT LCD Shield Library for Proteus V1.0. The red 2.4" TFT LCD shield is the easiest colour touch screen for an Arduino UNO: it plugs straight on the board, with no wires at all, and gives you 240 x 320 pixels, 65,536 colours and a resistive touch screen. It is the shield of countless Arduino projects: menus, games, meters, paint programs, home controls. With this TFT LCD Shield Library for Proteus, your sketch draws on a shield that behaves like the real one, and you touch it with the mouse: click and drag on the glass, and the sketch reads the point with analogRead(), exactly as on the real board.

This is our own model of the shield, written from the datasheet and from the physics of the touch film: the ILI9341 controller on its 8-bit parallel bus, with every command, the frame memory, the rotations, the colour order and the register reads that the MCUFRIEND_kbv library uses to find out which controller it talks to; and the 4-wire resistive film as a real resistor network in the analog simulation, sharing four LCD pins as on the real shield. You get two devices: TFT Shield Simple with a live STATUS panel on the schematic and TFT Shield Advance with a pop-up window, a bus log and five test tools. The demo runs on our Arduino UNO V4.0, with its serial monitor built into the board.

NOTICE: This library is very special to our team. The 2.4" shield is the first display we modelled with a touch screen that is read with analog pins: the film shares the LCD's pins, so the same wire is a digital bus line one microsecond and an analog input the next. We modelled the ILI9341's parallel bus and its reads, put the film into the analog simulation as a real resistor network, and tested it with the real MCUFRIEND_kbv and Adafruit TouchScreen libraries until every touch landed on the pixel under the mouse. It took our team a lot of hard work and many test runs. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the LCD Library board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the TFT LCD Shield Library for Proteus V1.0:

Figure: The TFT LCD shield demo in Proteus 8.5: TFT1 (Simple) is being touched in its paint strip, its STATUS panel says TOUCHED; the pop-up of TFT2 (Advance) shows the colour test; ARD1's monitor lists every touch.

What is a 2.4" TFT LCD Shield?

A TFT (thin-film transistor) display is a colour LCD: every pixel has its own tiny transistor and three sub-pixels, red, green and blue, that filter the white light of the backlight. The red 2.4" shield carries a 240 x 320 glass with a controller that keeps the picture in its own frame memory, and a resistive touch film on top of the glass. Unlike the SPI modules, the shield talks to the Arduino over an 8-bit parallel bus: eight data lines and five control lines, plugged straight into the UNO's headers. That makes it about twice as fast as SPI on an UNO, but it takes almost every pin of the board.

These shields are sold by many makers, often with the name "mcufriend" printed on them, and the same red board comes with different controllers: ILI9341, ST7781, ILI9325, HX8347, ILI9486 and more. That is why the popular MCUFRIEND_kbv library first reads the controller's ID and then picks the right start-up for it. Our model is the ILI9341 version, which answers 0x9341.

The 2.4" TFT LCD Shield at a Glance

The red 2.4" TFT LCD UNO shield
2.4" TFT LCD shield (ILI9341)
Glass2.4 inch diagonal, 240 x 320 pixels, a normally-white TN panel with BGR colour filters
Colours65,536 (16-bit, RGB565) or 262,144 (18-bit)
ControllerILI9341 (ILI Technology), 240 x 320 x 18-bit frame memory
Interface8-bit parallel (8080-I): LCD_D0 - LCD_D7, LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST
Touch4-wire resistive film on four of the LCD pins, read with analogRead()
Supply5 V from the UNO (the shield has a 3.3 V regulator and level shifters)
ExtrasA micro SD card slot on D10 - D13
Board72.2 x 52.7 mm, the size of an Arduino UNO

Terms You Will See in This Article

Words of this article
TermMeaning
RGB565A colour in 16 bits: 5 for red, 6 for green, 5 for blue. Adafruit GFX colours are RGB565.
LCD_RSRegister select (data / command): low = the byte is a command, high = a parameter or pixel data
LCD_WR / LCD_RDThe write and read strobes: a byte is written on the rising edge of LCD_WR
readID()MCUFRIEND_kbv's function that reads the controller's ID over the data lines
MADCTLThe command that sets the rotation (MY, MX, MV) and the colour order (RGB or BGR)
XP, XM, YP, YMThe four wires of the touch film: the ends of the X plate and of the Y plate
Raw x / y / zWhat TouchScreen's getPoint() reads: the position (0 - 1023) and the pressure

How the 8-Bit Bus and the Touch Film Work

To write a byte, the Arduino pulls LCD_CS low, sets LCD_RS (low for a command, high for data), puts the byte on LCD_D0 - LCD_D7 and pulses LCD_WR: the ILI9341 takes the byte on the rising edge. To draw, the library sets the address window with CASET (2A) and PASET (2B), sends MEMORY WRITE (2C) and then the pixels, two bytes each at 16-bit colour. A filled rectangle is one window and many identical pixels, which is why fillRect() is fast and drawPixel() is slow. To read, the data pins become inputs and every pulse on LCD_RD brings the next byte of the answer; the first one is a dummy. MCUFRIEND_kbv reads register D3 this way at start-up and gets 00 93 41: an ILI9341.

At power-on the ILI9341 is asleep and its display is off. After a reset a sketch must wait 120 ms, send SLEEP OUT (11), choose 16-bit colour, set MADCTL and send DISPLAY ON (29). MCUFRIEND_kbv's begin() does all of this. Until then the glass is not driven, and a TFT glass that is not driven is white.

The touch film is two resistive layers that touch where you press: the X plate between XP and XM, the Y plate between YP and YM. On the shield these four wires are shared with the LCD: XP is LCD_D0 (D8), YM is LCD_D1 (D9), XM is LCD_RS (A2) and YP is LCD_CS (A3). To read X, Adafruit's TouchScreen library drives XP high and XM low, so the X plate becomes a voltage divider, and reads the voltage of the touch point on YP with analogRead(A3). For Y it swaps the plates and reads A2; two more readings give the pressure. Then the sketch must give A2 and A3 back to the LCD as outputs. That is why the shield's touch pins are A2 and A3: they are the only shared pins that can do analogRead().

What's New in TFT LCD Shield Library for Proteus V1.0

  • Our first UNO TFT shield: the red 2.4" ILI9341 shield drawn at its real size, with its 20 header pins, ready to wire to the Arduino UNO the way it plugs on.
  • The 8-bit parallel bus of the ILI9341 as on the real chip: LCD_CS, LCD_RS, LCD_WR, LCD_RD, LCD_RST and LCD_D0 - LCD_D7, with the write cycle measured.
  • Register reads on the data lines: MCUFRIEND_kbv's readID() finds 0x9341, and readReg() reads the power mode, MADCTL, the pixel format and the self-diagnostic back.
  • A real resistive touch film in the analog simulation: the X and Y plates, the contact and even the 20 ohm drive of the ATmega's pins. The sketch reads it with analogRead() like on the real shield.
  • Touch it with the mouse: click and hold on the glass to press, drag to move your finger.
  • The full ILI9341 command set from the datasheet: sleep, display on / off, the address window, MADCTL with its four rotations and the colour order, 16 and 18-bit colour, inversion, idle mode and scrolling.
  • The white screen and the classic colour faults (red and blue swapped, colours inverted), with a banner that names the cause.
  • Five test tools on the Advance device: Init check, 8-bit bus, Speed, Pixels and Touch.
  • A touch demo on our Arduino UNO V4.0: buttons, a slider, a paint strip and a calibration screen, with the serial monitor built into the board.
  • A compact package: about 1.34 MB, without the C++ source code.

TFT Shield Simple vs TFT Shield Advance

The two devices (search "SHIELD" in Pick Devices; category Optoelectronics > Graphical LCDs)
TFT Shield SimpleTFT Shield Advance
DeviceTFTSHIELD24TEPTFTSHIELD24ADVTEP
On the schematicThe shield + the TFT SHIELD STATUS panelThe shield only
StatusBanner, 10 readouts, the last 6 transfersA pop-up window: Display, Bus log, Tests
Test tools-Init check, 8-bit bus, Speed, Pixels, Touch
Best forSeeing the state at a glanceFinding out why a screen or a touch is wrong

Download TFT LCD Shield Library for Proteus

Click the button below to download TFT-LCD-Shield-Library-for-Proteus-v1.0.zip (about 1.34 MB, without the C++ source code):

TFT LCD Shield Library for Proteus V1.0
  • README.txt: a detailed guide to the devices, the installation, the demo, the wiring, the test tools, the touch calibration and real hardware.
  • Proteus Library Files: TEPTFTSHIELD.LIB (the two devices) and ArduinoV4TEP.LIB from our Arduino Library for Proteus V4.0, with the Arduino UNO V4.0 of the demo.
  • Proteus Model Files: TEPTFTSHIELD.DLL and TEPARDUINO.DLL.
  • Proteus Simulation: TFT-Shield-ArduinoUnoV4.pdsprj, TFT_Shield_Touch_Demo.hex (both UNOs run it) and copies of both DLLs.
  • Arduino Code: TFT_Shield_Touch_Demo.ino, the demo sketch. It needs "MCUFRIEND_kbv", "Adafruit GFX Library" (which offers Adafruit BusIO too) and "Adafruit TouchScreen" from the Library Manager.

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 TFT LCD Shield Library for Proteus

  1. Close Proteus and extract the whole zip file to a normal folder, for example your Desktop.
  2. Copy the two files from Proteus Library Files into the LIBRARY folder, usually C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY (on some PCs C:\ProgramData\Labcenter Electronics\Proteus 8 Professional\LIBRARY).
  3. Copy TEPTFTSHIELD.DLL and TEPARDUINO.DLL from Proteus Model Files into the MODELS folder. If you have our Arduino Library V4.0, its files are the same.
  4. Delete TEPTFTSHIELD.IDX from the LIBRARY folder if there is one.
  5. Start Proteus, press P and search for SHIELD: you get the two devices.

Tip: the demo project needs its .hex file and the two DLLs beside it, so keep the Proteus Simulation folder together. The library was tested in Proteus 8.5; Proteus 7 is not supported.

The TFT LCD Shield in Proteus

Figure: TFT1 (Simple) running: the touch dashboard on the glass, the PWR LED on, and the STATUS panel: READY - 320 x 240 LANDSCAPE (ROT 1), 16-BIT 565, DISPLAY ON.

The part looks like the real shield at its real size, seen from the top: the red board, the glass with its black frame under the touch film, the flat cable end and the micro SD slot. Its 20 pins are on the left, in the order of the shield's pin list, and each one is named after the shield's own label, so wiring it to the UNO is easy to check. The glass lies along the board, so MCUFRIEND's setRotation(1) is the upright landscape picture, 320 x 240.

Pinout

The 20 pins of the shield, from the top
Shield pinFunctionArduino UNO
LCD_RSTHardware reset, active lowA4
LCD_CSChip select, active low (and YP of the touch film)A3
LCD_RSRegister select: command / data (and XM of the touch film)A2
LCD_WRWrite strobe: the byte is taken on the rising edgeA1
LCD_RDRead strobe: the next byte of an answerA0
GND / 5V / 3V3Ground and supplyGND / 5V / 3.3V
LCD_D0, LCD_D1Data bits 0 and 1 (and XP, YM of the touch film)D8, D9
LCD_D2 - LCD_D7Data bits 2 - 7D2 - D7
SD_SS, SD_DI, SD_DO, SD_SCKThe micro SD card (not simulated in V1.0)D10, D11, D12, D13

LEDs, the TEP Strip and the Properties

Three LEDs on the board show what happens: PWR lights with power, BUS flashes when a byte reaches the TFT, and TOUCH lights while the film is pressed. A slim TEP strip under the board holds the SIMPLE / ADVANCE badge, the title and the panel button. The LEDs, the strip and the panels are TEP additions; a real shield has none of them. The SD card is not simulated in V1.0; its pins are there and the slot is drawn.

Component properties (double-click the part, Edit Properties)
PropertyValuesWhat it does
PANELOPEN (default), CLOSEDSimple only: the STATUS panel at the start

Touch the Shield with the Mouse

Figure: A drag in the paint strip: the line follows the finger, the slider was moved the same way; while the film is held, the TOUCH LED lights and the banner says TOUCHED with the point on the glass and what getPoint() reads there.

In Proteus your mouse is the finger. Press the left button on the glass and hold it: the film is pressed at that point. Move the mouse with the button down and the finger slides. Let go and the film is released. The film is part of the analog simulation: when the sketch drives XP high and XM low, the voltage on A3 really is the voltage of the point you hold, and analogRead() converts it. At the glass edges getPoint() reads about 120 - 900 across the short side and 100 - 920 along the long side, and a pressure of about 350.

The demo's dashboard shows what a touch screen sketch does with it. The three buttons act once per press, the slider follows the finger, and the paint strip draws a line along your drag. The status line under it shows the screen point, the pressure and the raw values, and the serial monitor prints every new touch.

Figure: A touch on COLOUR: the paint colour changes from green to cyan; the mark at the right end of the paint strip shows it.
Figure: A touch on INVERT: invertDisplay(true) sends INVON (21), the controller inverts every colour; the memory stays.

Calibrating the Touch Screen

Figure: The CAL screen: touch a cross and the sketch prints its raw x / y; the magenta dots are the touches it mapped.

Every real touch film is a little different, so a sketch needs four numbers: the raw values at the glass edges. Type CAL in the monitor, touch the crosses in the corners and read the raw values; these are the TS_MINX / TS_MAXX / TS_MINY / TS_MAXY of the sketch. On this model the film reads x 120 - 900 and y 100 - 920 at the glass edges, and those are the demo's numbers. Note that the film's x runs across the short side of the glass: in the landscape rotation 1, the screen x comes from the raw y, and the screen y from the raw x.

The White Screen: Why a TFT Shield Starts White

Figure: After SLEEP: the glass is white, the panel says WHITE SCREEN - SLEEP IN (SEND SLPOUT 11 TO WAKE); the picture is still in the frame memory.

The glass of these shields is a normally-white TN panel: where the controller drives no voltage, the liquid crystal lets the backlight through, and the screen is white. That is why a TFT shield is white while it is asleep, while its display is off, and when the sketch never initialised it. The "white screen" is the most common question about these shields, and its usual causes are a wrong library for the controller, a missing tft.begin(ID) or a bad contact on one of the pins.

The model shows exactly that, and the STATUS panel names the cause: NOTHING ON THE BUS YET (check LCD_CS, RS, WR, D0-D7), STILL IN SLEEP: SEND SLPOUT (11), DISPLAY OFF: SEND DISPON (29), or SLEEP IN after the sketch's SLPIN, as in the picture. Two more faults have their own red banners: RED / BLUE SWAPPED when MADCTL asks for RGB order on this BGR glass, and COLOURS INVERTED when the display function (B6) sets REV = 0 on a normally-white glass.

Rotation on the Shield

Figure: ROTATE 0: setRotation(0) is portrait (240 x 320), so on the shield the picture lies on its side; ROTATE 1 brings it back upright.

setRotation() is one command: MADCTL with its MY, MX and MV bits. Rotations 0 and 2 are portrait, 1 and 3 landscape, and on this shield rotation 1 is upright. The touch film does not rotate with the picture: TouchScreen always reads the film's own x and y, so the sketch must map them for the rotation it uses. The demo's toScreen() does it for all four rotations, so the buttons work in every rotation.

TFT Shield Simple: The STATUS Panel

The Simple device keeps a live TFT SHIELD STATUS panel right under the board. The banner says READY, TOUCHED with the point, or what is wrong: NO POWER, WHITE SCREEN with its cause, STILL ASLEEP after a SLEEP OUT that came too early, RED / BLUE SWAPPED, COLOURS INVERTED, IN RESET or SUPPLY REVERSED. Ten readouts show DISPLAY, SLEEP, COLOURS, ORIENTATION, ID READ (what readID() got), VCC, BUS (the time a byte takes), FRAME (the time of a full screen), TOUCH and IGNORED, and the dark log lists the last 6 transfers. The red X closes the panel; PANEL on the strip opens it again.

TFT Shield Advance: The Pop-Up Window

Figure: TFT2 (Advance) on the sheet: the colour test (its UNO's A5 is tied to GND); the strip shows ADVANCE and OPEN PANEL.

The Advance device keeps only the shield on the schematic and opens a TEP pop-up window at Run, with the look of our serial monitor: the tabs Display, Bus log and Tests, Settings, Help and a theme switch.

The Display Page

Figure: The Display page: the glass, eight tiles, the frame memory as stored (240 x 320), and the supply, the glass type, the panel refresh, the full screens and the touch film with its pins.

The tiles read the controller: display, sleep, colour mode, orientation, colour order, inversion, touch and the ID that readID() got. The frame memory card shows the picture as the ILI9341 stores it, column 0 on the left and page 0 at the top: on the shield it is turned. Freeze holds the picture; the pixel grid adds x / y numbers.

The Bus Log Page

Figure: The Bus log: every command with its parameters, every read and every run of pixels with its window, newest first.

Every command, every read and every run of pixels: the time, the gap, the kind, the command byte or the pixel count and what it means. The filters show Commands, Pixels or only Problems.

The Tests Page: Five Test Tools

1. Init Check: Did begin() Do It Right?

Figure: Init check after tft.begin(tft.readID()): all green, and below it the start-up as the sketch sent it, readID()'s probes first.

The start-up against the datasheet and this glass: the supply, the ID the sketch read, the hardware and software reset, the waits, SLEEP OUT, the pixel format, MADCTL, the colour order, the display function and DISPLAY ON, each with a green, amber or red light and a verdict. Below it, the start-up as the sketch sent it, from power-on: first readID()'s reads of registers that belong to other controllers (they answer 00 here), then MCUFRIEND's ILI9341 list of power, VCOM, frame rate and gamma commands, each with its meaning.

2. 8-Bit Bus: Is the Sketch Talking to This TFT?

Figure: 8-bit bus: all 13 LCD signals wired, the write cycle and the strobes measured, readID() read register D3, and the last LCD_CS stretches.

Good for a white screen: which of the 13 LCD signals are connected, the command and data bytes (MCUFRIEND puts a 00 NOP before every command, and the tool counts them), the write cycle (the ILI9341 needs 66 ns, an UNO takes about 1 us a byte), the shortest LCD_WR and LCD_RD pulses, readID() with its read strobes and dummy bytes, the bytes per LCD_CS-low stretch, and the last CS stretches with their first bytes.

3. Speed: How Fast Can the Picture Change?

Figure: Speed after FILL: about 135.5 ms for a full screen (1.76 us a pixel), at best 7.4 full screens a second; below, what a redraw costs at this speed.

A full screen is 76,800 pixels, 153,600 bytes at 16-bit colour: on an UNO with this 8-bit bus about 135.5 ms, roughly twice as fast as the same ILI9341 on SPI. Each byte still needs a few instructions of the AVR, so a TFT sketch must redraw only what changes. The cost table shows why the demo's clock (a few ms) never flickers while a fillScreen would.

4. Pixels: Where Does a Pixel Live?

Figure: Pixels: a glass pixel, where it lives in the frame memory, its 18 bits, the drawPixel() line that writes it, and what getPoint() reads for a touch at that point.

Click a pixel: its colour, its frame-memory column and page, its 18 bits and its RGB565 value, the sketch's x / y in the current rotation and the drawPixel() line that writes it, what getPoint() reads for a touch at that point, and the pixels around it, magnified.

5. Touch: What Does getPoint() Read?

Figure: Touch, while TFT2's glass is held: the film in the circuit, the voltages and ADC values of the X, Y and Z reads, what getPoint() makes of them and the demo's screen point, the same as the pen's.

Good for touches in the wrong place or none at all: the film's wiring, the pen, whether the film is in the circuit right now (it joins the circuit when getPoint() starts and leaves it at the next LCD write), the voltages on A2 and A3 for each of the X, Y and Z reads with their ADC values, what getPoint() makes of them and whether it counts as a press, and what the demo's map() makes of them in the TFT's rotation.

TFT LCD Shield with Arduino in Proteus

Figure: The demo project: ARD1 + TFT1 (Simple, the touch dashboard) and ARD2 + TFT2 (Advance, the colour test), wired with net labels.

Open TFT-Shield-ArduinoUnoV4.pdsprj. Two Arduino UNO V4.0 boards from our Arduino UNO Library for Proteus V4.0 run the same sketch; ARD2's A5 is tied to GND, so it starts with the colour test. Each UNO has the serial monitor built in, so there is no Virtual Terminal to wire (see our Introduction to Arduino UNO for its pins).

Wiring

Figure: ARD1 and TFT1: the labels D2_1 ... D13_1, A0_1 ... A4_1, 5V_1 and 3V3_1 on both sides (the same name = connected).

On a real board the shield simply plugs on the UNO. In Proteus every shield pin goes to the same UNO pin through a net label: LCD_RD to A0, LCD_WR to A1, LCD_RS to A2, LCD_CS to A3, LCD_RST to A4, LCD_D0 and LCD_D1 to D8 and D9, LCD_D2 - LCD_D7 to D2 - D7, and the SD card pins to D10 - D13. A5 is the only analog pin left free.

The Arduino Code

The demo uses David Prentice's MCUFRIEND_kbv library (version 3.0.0) with the Adafruit GFX library (1.12.6) for the display, and the Adafruit TouchScreen library (1.1.6) for the film:

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>

The film's four wires are four LCD pins:

#define XP 8                                     // the touch film's four wires on the LCD pins
#define YP A3
#define XM A2
#define YM 9

The calibration: the raw values at the glass edges, read on the CAL screen, and the pressure range of a touch:

#define TS_MINX 120
#define TS_MAXX 900
#define TS_MINY 100
#define TS_MAXY 920
#define MINPRESSURE 200
#define MAXPRESSURE 1000

MCUFRIEND_kbv needs no pin numbers: it knows the shield's pins. TouchScreen gets the four film pins and the X plate's resistance:

MCUFRIEND_kbv tft;                               // LCD_CS A3, LCD_RS A2, LCD_WR A1, LCD_RD A0, LCD_RST A4, LCD_D0-D7
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);   // 300 ohm across the X plate

In setup(), the sketch reads the controller's ID, starts the TFT with it and turns the picture upright:

  id = tft.readID();                             // MCUFRIEND reads the controller's ID: 0x9341
  tft.begin(id);
  tft.setRotation(rotation);

Reading the touch: getPoint() drives and reads the film, then the sketch gives LCD_RS and LCD_CS back to the TFT. Forgetting these two lines is the classic bug of these shields: the next drawing call goes nowhere.

  TSPoint p = ts.getPoint();
  pinMode(XM, OUTPUT);                           // the film shares LCD_RS and LCD_CS: give them back to the TFT
  pinMode(YP, OUTPUT);
  const bool touched = p.z > MINPRESSURE && p.z < MAXPRESSURE;

map() turns the raw values into pixels. In rotation 1 the screen x comes from the raw y:

    case 1: x = map(p.y, TS_MINY, TS_MAXY, 0, 320); y = map(p.x, TS_MAXX, TS_MINX, 0, 240); break;

A button must act once per press, not on every loop while the finger stays on it:

    if (y >= 76 && y < 124) {                    // the buttons: once a press (holding a button does not repeat it)
      if (!first) return;

STATUS reads four registers back from the ILI9341 over LCD_D0 - LCD_D7:

  hex(F("Power mode 0x0A: "), tft.readReg(0x0A));
  hex(F("MADCTL 0x0B: "), tft.readReg(0x0B));

The most important trick for a TFT: redraw only what changes. The clock is printed with a background colour, so the new digits overwrite the old ones, with no fillRect and no flicker:

  tft.setTextColor(WHITE, BLUE);                 // with a background colour: the new digits overwrite the old ones

FILL times a full screen with millis(), so you can compare it with the Speed tool:

    const unsigned long t0 = millis();
    tft.fillScreen(BLUE);
    fillMs = millis() - t0;

To change the sketch, export a new HEX file and load it into the UNO; see How to get the HEX file from Arduino. New to Arduino? Start with our Arduino Tutorial for Beginners.

Serial Monitor Commands

Commands of the demo sketch, upper or lower case, typed in the UNO's built-in monitor
CommandWhat it does
HELP / STATUSThe command list / the ID, rotation, screen, text, bar, four registers read back, touches
TEXT <text>The big text (16 characters)
BAR <0-100>The slider (only its changed part is drawn)
DASH / TEST / CALThe touch dashboard / the colour test / the touch calibration
CLEARA black screen
FILLA timed fillScreen: "fillScreen took N ms"
ROTATE <0-3>setRotation(): 1 upright on the shield, 3 upside down, 0 / 2 portrait
INVERT ON / OFFinvertDisplay()
SLEEP / WAKESLPIN / SLPOUT: the glass goes white / comes back
TOUCHPressed or released, the raw x / y / z now and the last screen x / y

How to Run the Demo

  1. Press Run. Both monitor windows and TFT2's pop-up open; move them aside. The glasses are white for a moment, then show the dashboard and the colour test.
  2. Touch TFT1: click COLOUR, INVERT and CLEAR; press on the slider and drag; draw in the paint strip with the button held down. Watch ARD1's monitor and the TOUCH LED.
  3. Type STATUS, TEXT Hi TEP, BAR 25 and FILL in ARD1's monitor; then CAL and touch the crosses, ROTATE 0 and ROTATE 1, SLEEP and WAKE.
  4. On TFT2's pop-up, open the Tests and try the five tools; hold TFT2's glass while the Touch tool is open.

TFT LCD Shield Proteus Simulation Results

The Built-in Serial Monitor in Its Simple Interface

Each Arduino UNO V4.0 carries its own copy of our TEP Serial Monitor Advance, wired inside the board to D0 / D1 like the USB chip of a real UNO. Its window, "TEP Arduino UNO - ARD1", opens at Run, and a click on the board's USB port opens it again. The screenshots show its Simple interface: only the log and the line to send.

  • Switch to it: press Ctrl+Shift+U, or use the monitor's ... menu.
  • Back to the full view: press Esc; the full view has the Board, Monitor and Plotter tabs.

Read all about the monitor in TEP Serial Monitor Advance for Proteus.

ARD1: The Touches

Figure: ARD1's built-in monitor: every new touch with its screen point and pressure (the slider at x 29, the paint strip at x 24), and the button it pressed.
touch: button INVERT on
touch: x 160 y 100 z 352
touch: button INVERT off
touch: x 29 y 152 z 352
touch: x 24 y 211 z 351

ARD1: STATUS, With the Registers Read Back

Figure: STATUS: four registers read back over LCD_D0 - LCD_D7 - the power mode 0x9C (booster on, sleep out, normal mode, display on), MADCTL 0x28 (rotation 1, BGR), the pixel format 0x05 (16-bit) and the self-diagnostic 0xC0.
Power mode 0x0A: 0x9C
MADCTL 0x0B: 0x28
Pixel format 0x0C: 0x05
Self-diagnostic 0x0F: 0xC0
Touches 10, last x 160 y 150 z 352

ARD2: TOUCH and FILL

Figure: ARD2's built-in monitor: readID, TOUCH while TFT2's glass is held, FILL ("fillScreen took 135 ms") and TEST.
2.4" TFT LCD shield + touch V1.0 demo - The Engineering Projects
readID: 0x9341
TFT 240x320 ready, touch ready (4-wire film)
Type HELP for the commands
touch: x 99 y 150 z 353
TOUCH
Touch: pressed, raw x 410 y 356 z 353, last screen x 99 y 150
FILL
OK - fillScreen took 135 ms (76,800 pixels)
TEST
OK - the colour test

The sketch measures 135 ms with millis(), and the Speed tool 135.5 ms on the bus: the same fillScreen seen from both sides.

Troubleshooting

  • The glass stays dark and the PWR LED is off: no power. Check 5V and GND.
  • WHITE SCREEN - NOTHING ON THE BUS YET: check LCD_CS (A3), LCD_RS (A2), LCD_WR (A1) and LCD_D0 - LCD_D7, and that the sketch calls tft.begin(tft.readID()). The 8-bit bus tool lists the pins that are not connected.
  • readID() prints a wrong ID: LCD_RD (A0) or a data pin is not connected; MCUFRIEND reads the ID back over the data lines.
  • WHITE SCREEN - STILL IN SLEEP or DISPLAY OFF: SLEEP OUT (11) or DISPLAY ON (29) was never sent; begin() sends both.
  • STILL ASLEEP - SLPOUT CAME TOO EARLY: wait 120 ms after a reset before SLEEP OUT.
  • RED / BLUE SWAPPED or COLOURS INVERTED: the sketch's MADCTL or B6 does not fit this BGR, normally-white glass; MCUFRIEND's ILI9341 set-up gets both right.
  • The picture is on its side or upside down: use setRotation(1) on this shield.
  • Touches land in the wrong place: check the TS_MIN / TS_MAX values with CAL or the Touch tool, and map the axes for your rotation (in rotation 1 the screen x comes from the raw y).
  • No touch at all: TouchScreen must get XP 8, YP A3, XM A2, YM 9; hold the mouse button down on the glass: the touch lasts as long as you hold it.
  • The picture stops after the first touch: the sketch did not set A2 and A3 back to OUTPUT after getPoint().
  • The part or the UNO is not simulated, or no monitor window: TEPTFTSHIELD.DLL or TEPARDUINO.DLL is missing from MODELS and the project folder; a closed monitor opens again with a click on the UNO's USB port.
  • The Advance pop-up does not appear: click OPEN PANEL on the strip.

Things to Know Before Using a Real 2.4" TFT LCD Shield

The demo sketch uses only the MCUFRIEND_kbv, Adafruit GFX and TouchScreen libraries and Serial, so it runs on a real UNO and shield too. Keep in mind:

  • Which controller? The same red shield is sold with many controllers. Run the demo and read the ID it prints; MCUFRIEND_kbv supports most of them, our model is the ILI9341 (0x9341).
  • Plug and play: the shield has its own regulator and level shifters, so it sits on a 5 V UNO or Mega 2560 with no extra parts.
  • Calibrate your film: run CAL (or MCUFRIEND's TouchScreen_Calibr_native example) and put your raw edge values into TS_MINX / TS_MAXX / TS_MINY / TS_MAXY.
  • Give the pins back: after every getPoint(), set A2 and A3 to OUTPUT again.
  • Few pins left: the shield takes D2 - D9 and A0 - A4; D0 / D1 (Serial), D10 - D13 (the SD card) and A5 remain.
  • Speed: about 0.14 s for a full screen on an UNO; draw only what changes.
  • RAM: MCUFRIEND_kbv keeps no picture in RAM; the demo uses 749 bytes of the UNO's 2,048.

Limitations of the Simulation

  • Not modelled: the 16-bit, RGB and SPI interfaces of the ILI9341, the other controllers sold on the same board, the partial mode's non-display area, the effect of the gamma, power and VCOM settings on the picture, the panel's response time, timing violations shorter than the simulation's edges, the current draw, the backlight (always on), the shield's level shifters, more than one finger, the film's noise and drift, and the SD card.
  • The LEDs, the strip with the badge and the panel button, and the panels are TEP additions.
  • The model is our own implementation, written from the ILI9341 datasheet and the physics of a resistive film. ILI9341 is an ILI Technology part; this library is not made or endorsed by ILI Technology, mcufriend, David Prentice, Adafruit or Labcenter.
  • Licences: the demo sketch uses MCUFRIEND_kbv 3.0.0 (FreeBSD licence), Adafruit GFX 1.12.6 and Adafruit TouchScreen 1.1.6 (BSD licence) and Adafruit BusIO 1.17.4 (MIT licence). The HEX file contains them and the Arduino AVR core 1.8.6, which includes LGPL-licensed code; its source code is on GitHub. The README holds the licence texts.
  • Tested in Proteus 8.5 in October 2026 (the demo as shipped on two Arduino UNO V4.0 boards with their built-in monitors: readID, the dashboard and the colour test, touches with the real mouse - a tap, a held button and a drag in the paint strip - and with presses fed to the model at exact times for these screenshots, CAL, the Serial commands with the register reads, INVERT, ROTATE, SLEEP / WAKE, FILL, the panel, the pop-up and the five tools, and a 60-second hold that draws after every touch reading; about 0.3 x real time with the pop-up and both monitors open). Proteus 7 is not supported.

Looking for another display? Our TFT ILI9341 Library for Proteus V1.0 has the same ILI9341 as a 2.4" / 2.8" SPI module with an XPT2046 touch chip, our TFT ST7735 Library for Proteus V1.0 the smaller 1.8" colour TFT, and our LCD Keypad Shield Library for Proteus V1.0 another shield that plugs on the UNO.

So, that was all about the TFT LCD Shield Library for Proteus V1.0. I hope the 8-bit bus, readID(), the white screen and the shared touch pins are clear now, so your shield works the first time you plug a real one on your UNO. If you use the TFT LCD Shield Library for Proteus in a project, please share your feedback in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!