Skip to content
IslamSister IslamSister Est. 2017 · Faith · Family · Purpose

How to make a GUI on a 2.4 inch IPS screen?

a Written byadmin · A reading from IslamSister
You can build a graphical user interface (GUI) on a 2.4 inch IPS screen by pairing it with a microcontroller like the ESP32 or STM32, using a graphics library such as LVGL or TFT_eSPI, and driving the display via SPI (Serial Peripheral Interface). The 2.4 inch 240x320 ips display is a common choice because its 240x320 pixel resolution, 16-bit color depth (65K colors), and 178-degree viewing angle make it viable for showing buttons, sliders, text, and simple animations. The display uses the ILI9341 or ST7789 driver IC, both of which are well-documented and supported by open-source libraries. For a functional GUI, you need to wire the display’s CS (Chip Select), DC (Data/Command), RESET, MOSI, MISO, and SCK pins to your microcontroller’s SPI pins, plus a backlight pin for brightness control. The typical SPI clock speed is 20 MHz to 40 MHz, which gives a frame rate of around 30 to 60 frames per second depending on the complexity of the GUI elements. On an ESP32, you can achieve 40 MHz SPI without issues, while an Arduino Uno might max out at 8 MHz due to its 16 MHz clock. The power consumption of the display is roughly 80 mA at 3.3V with the backlight on, so you need a 3.3V regulator if your microcontroller runs at 5V.

Hardware setup and pin mapping

Start by connecting the display to your microcontroller. The 2.4 inch IPS screen typically has 8 pins: VCC (3.3V), GND, CS, RESET, DC, MOSI, SCK, and LED (backlight). Some modules include an MISO pin for reading data, but most GUI applications only write to the display, so you can leave MISO unconnected. For an ESP32 DevKit V1, a standard pin mapping looks like this: CS to GPIO5, DC to GPIO17, RESET to GPIO16, MOSI to GPIO23, SCK to GPIO18, and LED to GPIO4 (PWM-capable for brightness control). The backlight pin should be connected to a PWM output to adjust brightness between 0 and 255, which reduces power consumption by up to 50% when dimmed. The display’s VCC requires a stable 3.3V supply; using a 3.3V regulator like the AMS1117-3.3 ensures the display doesn’t draw more than 100 mA during peak operation. If you’re using an Arduino Uno, you’ll need a level shifter for the SPI lines because the Uno runs at 5V and the display expects 3.3V logic. A 74HC4050 level shifter or a simple voltage divider with 1k and 2k resistors works for each signal line.

Choosing the right graphics library

The two most popular libraries for this display are TFT_eSPI (for Arduino and ESP32) and LVGL (Light and Versatile Graphics Library). TFT_eSPI is lightweight and optimized for SPI displays, using about 30 KB of flash and 2 KB of RAM for basic drawing. It supports primitives like lines, circles, rectangles, and text with custom fonts. For a GUI with buttons and sliders, you can write your own event handling loop. LVGL, on the other hand, is a full-featured GUI framework that requires 32 KB of RAM and 64 KB of flash for the core library. It includes widgets like buttons, labels, drop-down lists, charts, and a touchscreen driver if you add a touch overlay. The 2.4 inch IPS screen has a pixel density of 167 PPI (pixels per inch), which is enough for 12-point fonts to be readable without anti-aliasing. LVGL uses a frame buffer of 240x320x2 bytes (153.6 KB) for 16-bit color, but you can reduce this to a partial frame buffer of 240x40 lines (19.2 KB) to save RAM on microcontrollers with limited memory. The ESP32 with 520 KB SRAM can handle the full frame buffer, while an STM32F103C8 (64 KB SRAM) needs the partial buffer approach.

Writing the GUI code

Here’s a practical example using TFT_eSPI on an ESP32. First, install the library via the Arduino Library Manager and configure the User_Setup.h file to match your pin mapping. Set the display driver to ILI9341 (or ST7789 if your module uses it), and define the SPI frequency as 40 MHz. Then, initialize the display in your setup() function:

#include
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(1); // Landscape orientation
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.drawString("Hello GUI", 60, 150, 4);
}

For a button, draw a filled rectangle with a border and check if the touch coordinates (if you have a resistive touch panel) fall within its bounds. Without touch, you can use physical buttons connected to the microcontroller. The display’s SPI bus can share the same pins as other SPI devices, but you need to manage the CS pin for each device. The 2.4 inch IPS screen’s response time is 25 ms (typical), so you can update the GUI at 40 Hz without ghosting. The color gamut covers 65% of the sRGB spectrum, which is adequate for most UI elements like blue buttons and green indicators.

Performance optimization and data handling

The SPI bandwidth for a 240x320 display at 16-bit color is 240 * 320 * 2 = 153,600 bytes per frame. At 40 MHz SPI clock, the theoretical transfer time is 153,600 / (40,000,000 / 8) = 30.72 ms per frame, but overhead from the library and microcontroller reduces this to about 40 ms, giving a 25 FPS refresh rate. To improve this, you can use DMA (Direct Memory Access) on the ESP32, which offloads SPI transfers from the CPU and achieves 35 FPS. The TFT_eSPI library supports DMA on ESP32 when you enable the TFT_SPI_DMA option in User_Setup.h. For LVGL, you can enable the “LV_USE_DMA2D” option on STM32 microcontrollers with a hardware DMA controller. The display’s pixel format is RGB565, where each pixel uses 5 bits for red, 6 bits for green, and 5 bits for blue. This gives 32 shades of red, 64 shades of green, and 32 shades of blue, which is sufficient for smooth gradients and anti-aliased fonts. The viewing angle of 178 degrees means the GUI remains readable from the side, which is important for handheld devices or dashboards.

Memory management and data tables

When designing a GUI with multiple screens, you need to manage the microcontroller’s RAM carefully. The table below shows the memory requirements for common GUI elements on this display:

Element | Memory (RAM) | Flash (for bitmaps)
Full-screen background (240x320) | 153.6 KB | 153.6 KB (if stored as bitmap)
Button (80x40 pixels) | 6.4 KB | 6.4 KB
Slider (200x20 pixels) | 8 KB | 8 KB
Text label (16x16 font) | 0.5 KB | 2 KB per 100 characters
Icon (32x32 pixels) | 2 KB | 2 KB

For a GUI with 5 buttons, 2 sliders, and 3 text labels, the total RAM usage is around 50 KB for the elements plus the frame buffer. On an ESP32 with 520 KB SRAM, this leaves plenty of room for network stacks or sensor data. On an STM32F103 with 20 KB SRAM, you must use a partial frame buffer and store bitmaps in flash (program memory). The display’s SPI command set includes the “Memory Write” command (0x2C) for sending pixel data and “Column Address Set” (0x2A) and “Page Address Set” (0x2B) for defining a window. You can use these commands to update only a portion of the screen, like a button that changes color when pressed, which reduces SPI traffic by 90% compared to redrawing the whole screen.

Touch integration and user input

If you add a resistive touch panel (common on 2.4 inch IPS modules), the touch controller is typically an XPT2046. This chip communicates via SPI and provides 12-bit X and Y coordinates. The touch panel has a resolution of 2048x2048, which you map to the 240x320 display using calibration. The calibration process involves reading the touch coordinates at three corners of the screen and calculating a linear transformation matrix. The touch response time is 10 ms, so you can detect taps and drags at 100 Hz. For a GUI, you can implement a button press by checking if the touch coordinate falls within the button’s rectangle. The XPT2046 draws 1.5 mA during operation, so you can power it from the same 3.3V rail as the display. The touch SPI bus can share the same MOSI, MISO, and SCK lines as the display, but you need a separate CS pin for the touch controller, typically GPIO2 on the ESP32.

Real-world application examples

A common use case for this display is a weather station GUI. The 240x320 resolution allows you to show a temperature value in large 48-point font, a humidity bar graph, and a small icon for weather conditions. The color depth of 65K colors means you can use a blue gradient for the sky and yellow for the sun. The display’s brightness of 400 cd/m² (typical) is readable indoors and in shaded outdoor areas. For a battery-powered device, the display’s backlight consumes 80 mA at full brightness, so you can use a PWM duty cycle of 50% to reduce it to 40 mA, extending battery life from 4 hours to 8 hours with a 2000 mAh LiPo battery. The SPI interface allows the microcontroller to enter deep sleep mode while the display is off, drawing only 10 µA. The display’s driver IC supports a sleep command (0x10) that cuts power to the display controller, reducing current to 5 µA.

Debugging and common pitfalls

One frequent issue is incorrect SPI pin mapping. If the display shows a white screen or garbled pixels, check that the CS pin is pulled low before sending commands and high after. The display’s reset pin should be held low for 10 ms during initialization, then set high. The backlight pin should be set to HIGH for full brightness; if it’s LOW, you’ll see a black screen. Another issue is the SPI clock speed being too high for the wiring. With long jumper wires (over 20 cm), the signal degrades at 40 MHz, causing pixel corruption. Use shielded wires or keep the connections under 10 cm. The display’s operating voltage is 3.3V, and applying 5V to any pin will damage the driver IC. Always use a multimeter to verify the voltage before connecting. The display’s refresh rate drops to 10 FPS if you use the library’s default software SPI instead of hardware SPI, so always configure the library to use the microcontroller’s hardware SPI pins.

Advanced techniques for better visuals

You can use the display’s gamma correction feature to improve contrast. The ILI9341 driver has a gamma register (0xE0 to 0xE7) that you can adjust to boost the red and blue channels for a warmer look. The default gamma curve is linear, but you can set it to a sRGB curve for more accurate color reproduction. The display’s response time of 25 ms means you can show animations like a spinning progress indicator without motion blur. For anti-aliased fonts, you need to use a library that supports alpha blending, like LVGL, which uses 4-bit alpha for smooth edges. The display’s pixel density of 167 PPI means that a 10-point font is 13 pixels tall, which is readable but small. For a GUI with text, use at least 16-point fonts (20 pixels tall). The display’s color depth allows you to use 256-color palettes for icons, which reduces flash usage by 75% compared to 16-bit color bitmaps.

Power and thermal considerations

The display’s operating temperature range is -20°C to 70°C, so it’s suitable for indoor and outdoor use in moderate climates. The backlight LED has a lifespan of 50,000 hours, so it will last for years of continuous use. The display’s power consumption is 264 mW at 3.3V and 80 mA, which is low enough to run from a USB port or a battery. For a portable device, use a boost converter like the TPS61023 to provide 3.3V from a single Li-ion cell (3.7V to 4.2V). The converter’s efficiency of 90% means the display draws 90 mA from the battery. The display’s SPI interface can be isolated from the microcontroller using an optocoupler if you need electrical isolation for safety-critical applications. The display’s driver IC includes a built-in voltage regulator for the LCD panel, so you don’t need external capacitors beyond the 10 µF and 0.1 µF decoupling caps on the VCC pin.

Software tools and workflow

For GUI design, you can use the LVGL online simulator (SquareLine Studio) to create the UI visually and export the code as C arrays. The simulator generates code for buttons, labels, and sliders that you can copy-paste into your Arduino or PlatformIO project. The display’s 240x320 resolution means you can fit up to 4 buttons per row (60 pixels wide each) with 10 pixels of spacing. For a menu system, use a scrollable list with 10 items, each 30 pixels tall. The LVGL library supports animations with a frame rate of 60 FPS, but on the 2.4 inch IPS screen, you’ll get 30 FPS due to the SPI bandwidth. You can use the display’s “partial update” feature to redraw only the animated area, which keeps the frame rate at 60 FPS for small elements. The TFT_eSPI library supports sprite objects that you can draw off-screen and then push to the display, reducing flicker. The sprite size is limited by RAM; a 100x100 sprite uses 20 KB of RAM.

Testing and validation

To test the GUI, write a simple program that draws a red rectangle at coordinates (0,0) to (239,319) and a blue circle in the center. If the rectangle fills the entire screen and the circle is centered, the display is working correctly. The display’s pixel layout is RGB vertical stripe, so red, green, and blue subpixels are arranged in columns. This means that horizontal lines are sharper than vertical lines. For text, use a font that is designed for RGB subpixel rendering, like the FreeSans font, which improves readability. The display’s contrast ratio is 1000:1, so black text on a white background is very legible. The display’s viewing angle of 178 degrees means that the GUI remains readable even when the device is tilted, which is important for a handheld device. The display’s surface is glossy, so it reflects ambient light. For outdoor use, apply an anti-glare film to reduce reflections. The display’s thickness is 3.5 mm, so it can fit into a 5 mm thick enclosure.

Integration with other sensors

You can combine the GUI with a DHT22 temperature and humidity sensor, showing the data on the display. The sensor reads every 2 seconds, and you update the GUI with the new values. The display’s SPI bus can be shared with the sensor if it uses I2C, but you need separate I2C pins. The ESP32 has two I2C buses, so you can connect the sensor to I2C bus 0 (GPIO21, GPIO22) and the display to SPI bus 0 (GPIO18, GPIO23). The GUI can show a line chart of temperature over the last 10 minutes, using 10 data points. The display’s pixel resolution allows you to draw a chart with 240 pixels wide, so each data point is 24 pixels apart. The chart’s Y-axis can be scaled from 0 to 50°C, with 10°C increments. The display’s color depth allows you to use a gradient from blue to red for the temperature line. The chart updates every 2 seconds, and the SPI bandwidth is enough to redraw the chart area (240x100 pixels) in 20 ms.

Long-term reliability

The display’s IPS technology ensures that the colors don’t shift over time, unlike TN panels that degrade after 10,000 hours. The polarizer layer is coated with a hard coating that resists scratches. The display’s connector is a 0.5 mm pitch FPC (Flexible Printed Circuit) that is rated for 10,000 insertions. The display’s driver IC is soldered to the glass with ACF (Anisotropic Conductive Film), which is reliable for 5 years of daily use. The display’s backlight LED has a color temperature of 6500K, which is close to daylight. The display’s SPI interface uses 3.3V logic, which is compatible with most modern microcontrollers. The display’s operating humidity range is 10% to 90% non-condensing, so it’s suitable for indoor use. For