Skip to content
Vol. XIV · No. 287
Festival Dispatch Issue
Tuesday Edition Reviews·Interviews·Festivals·Awards Sundance ’25 · TIFF · Berlinale
Subscribe to the Newsletter
Festival still · Independent Film Blog
Independent Film Blog

How to use a 2.4 inch resistive TFT display with a joystick?

How to Use a 2.4 Inch Resistive TFT Display with a Joystick

To use a 2.4 inch resistive TFT display with a joystick, you need to wire the display module to a microcontroller like an Arduino Uno or ESP32, connect the joystick’s analog outputs to analog input pins, and write code that reads joystick movements to update the screen. The 2.4 inch resistive tft display typically uses the ST7789V driver with a 240x320 pixel resolution, SPI interface, and a resistive touch layer that requires an ADC for touch detection. The joystick, usually a two-axis analog stick with a select button, outputs voltage values between 0 and 5V (or 0-3.3V for 3.3V logic) on its X and Y axes. When you move the joystick, these voltages change, and the microcontroller’s ADC converts them to digital values (0-1023 for 10-bit ADC on Arduino). You can then map these values to cursor positions or menu selections on the display.

First, understand the hardware specs. The ST7789V driver supports a 4-wire SPI interface (SCLK, MOSI, DC, CS) plus a reset pin. The resistive touch panel uses four wires: X+, X-, Y+, Y-. You need to connect these to analog pins on the microcontroller to measure voltage drops. For the joystick, connect its VCC to 5V (or 3.3V if your logic level matches), GND to ground, VRx to an analog pin (e.g., A0), VRy to another analog pin (e.g., A1), and SW (the select button) to a digital pin (e.g., D2) with a pull-up resistor. The joystick’s resting position outputs around 2.5V (midpoint of 0-5V), which reads as 512 on a 10-bit ADC. Moving it to the extremes gives 0 or 1023. The resistive touch panel works similarly: when you press the screen, the resistance changes, and you can read the touch coordinates by measuring voltage on the X and Y layers.

For wiring, use a breadboard and jumper wires. Connect the display’s VCC to 5V (or 3.3V if your module supports it—check the datasheet), GND to ground, SCL to pin 13 (Arduino Uno’s SPI clock), SDA to pin 11 (MOSI), DC to pin 9, CS to pin 10, and RST to pin 8. For the resistive touch, connect X+ to A2, X- to A3, Y+ to A4, and Y- to A5. The joystick connects to A0, A1, and D2. Use a 10kΩ pull-up resistor on the joystick’s SW pin to VCC to avoid floating inputs. The display’s backlight pin (LED) can connect to a PWM pin (e.g., D6) for brightness control, or directly to 5V through a 100Ω resistor to limit current. The typical backlight current is 20mA, so a 100Ω resistor drops 2V at 20mA, leaving 3V for the LED, which is safe.

Now, the software part. Install the Adafruit ST7789 and Adafruit GFX libraries in your Arduino IDE. These libraries handle the SPI communication and provide functions like fillScreen(), drawPixel(), and setCursor(). For the joystick, you don’t need a library—just read analog pins with analogRead(). For the resistive touch, you can use the Adafruit STMPE610 library if your touch controller is that chip, but many 2.4-inch resistive displays use a generic four-wire panel that requires manual ADC reading. Here’s a basic code structure: initialize the display, read joystick values, map them to screen coordinates, and draw a cursor. For example, map the joystick X (0-1023) to display X (0-239) using map(analogRead(A0), 0, 1023, 0, 239). Do the same for Y (0-319). Update the cursor position every 50ms to avoid flicker. Use fillRect() to erase the old cursor and fillCircle() to draw the new one.

For the resistive touch, you need to read the X and Y coordinates when the screen is pressed. The typical method: set X+ to high, X- to low, and read the voltage on Y+ (or Y-). Then swap roles for Y. This requires toggling pins between output and input modes. Here’s a practical approach: connect X+ to a digital pin (e.g., D3) and X- to D4, both as outputs. Y+ to A2 (analog input), Y- to A3 (analog input). To read X: set D3 high, D4 low, read A2. To read Y: set D3 and D4 as inputs (high impedance), then set Y+ high (via a digital pin, say D5), Y- low, and read A2 again. This is simplified; you may need to use analog pins for both drive and sense for accuracy. The touch resolution is typically 8-bit (0-255) due to the ADC noise, but you can oversample to get 10-bit. Expect a touch pressure threshold: if the ADC value is below 50 (out of 1023), it’s likely a false touch.

Combine joystick and touch for a rich interface. For example, use the joystick to navigate a menu and the touch to select items. The joystick’s select button (SW) can act as a confirm key. In your code, check if the joystick button is pressed (digitalRead(D2) == LOW, assuming pull-up) and then execute an action. The display’s resistive touch can detect taps, so you can also implement a button on the screen. To avoid ghost touches, debounce both the joystick button and the touch input with a 50ms delay. The joystick’s analog readings will have noise; apply a moving average filter (e.g., average of 5 readings) to smooth the cursor movement. The display’s refresh rate is about 60Hz with SPI clock at 8MHz, so you can update the cursor at 20Hz without lag.

Power considerations: the display draws about 20mA for backlight plus 10mA for the driver, total 30mA. The joystick draws negligible current (microamps). The Arduino Uno can supply 5V at up to 500mA, so it’s fine. If you use an ESP32, which runs at 3.3V logic, you need a level shifter for the display’s SPI lines (3.3V to 5V) or use a 3.3V-compatible display module. The ST7789V can work at 3.3V, but the resistive touch panel’s voltage divider may give lower ADC readings; you can compensate by adjusting the map() function. The joystick also works at 3.3V, but its output range is 0-3.3V, giving ADC values 0-4095 on ESP32’s 12-bit ADC.

For a real-world example, build a simple game: a maze where the joystick moves a dot through the maze. Use the display’s resistive touch to reset the game. Code the maze as a 2D array of walls (0 for path, 1 for wall). Read joystick X and Y, map to a grid cell, and check if the next cell is a wall. If not, move the dot. Use drawRect() for walls and fillCircle() for the dot. The resistive touch can detect a press on a “reset” button area (e.g., top-left corner). The joystick’s select button can also reset. This project uses all features: display, joystick, and touch. The total code size is about 10KB, fitting on an Arduino Uno’s 32KB flash.

Performance tuning: use hardware SPI for faster screen updates. The standard Arduino SPI library runs at 4MHz, but you can increase it to 8MHz by setting the SPI clock divider to 2 (SPI.setClockDivider(SPI_CLOCK_DIV2)). This reduces the time to draw a full screen from 200ms to 100ms. For the joystick, use analogRead() which takes 100μs per reading. With 5 readings per axis, that’s 1ms per update, negligible. The resistive touch reading is slower because you need to toggle pins and read twice; it takes about 2ms per touch point. If you need faster touch response, use an external ADC like the ADS1115 with I2C, but that adds cost.

Common issues: floating touch pins cause false triggers. Always set unused touch pins to input with pull-down resistors (10kΩ to ground). The joystick may have a dead zone near the center (around 512±20). Implement a dead zone check: if abs(reading - 512) < 20, treat it as no movement. The display’s SPI bus may conflict with other SPI devices; use separate CS pins. The resistive touch panel’s accuracy degrades at the edges; calibrate by mapping the touch coordinates to the display coordinates using a linear formula: touchX = (displayX * touchMaxX) / displayMaxX. You can do a two-point calibration: touch the top-left and bottom-right corners, record the ADC values, and compute the scale and offset.

Data table for typical joystick readings:

Joystick Position | X ADC (0-1023) | Y ADC (0-1023)
Left | 0 | 512
Right | 1023 | 512
Up | 512 | 1023
Down | 512 | 0
Center | 512 | 512

For the resistive touch, typical readings:

Touch Position | X ADC (0-1023) | Y ADC (0-1023)
Top-left | 100 | 100
Bottom-right | 900 | 900
Center | 500 | 500

These values vary with the touch pressure and panel quality. Use a 10-bit ADC for better resolution. The ST7789V display’s color depth is 16-bit (65K colors), so you can draw smooth gradients. The joystick’s analog output has a 0.1V noise, which translates to about 20 ADC steps. The moving average filter reduces this to 5 steps. The resistive touch panel has a 1% linearity error, meaning the reported position can be off by 2-3 pixels. This is acceptable for menu navigation but not for precise drawing.

For advanced use, integrate the joystick with the display’s touch to create a dual-input system. For example, use the joystick to control a cursor that highlights buttons, and the touch to confirm. The code can prioritize one input over the other: if touch is detected, ignore joystick for 100ms to avoid double actions. The display’s SPI clock can be set to 16MHz on an ESP32, giving a 60fps frame rate. The joystick’s select button can be used to toggle between modes (e.g., move mode and select mode). The resistive touch can be used for gestures like swipe to scroll, which requires reading the touch start and end positions. The joystick’s analog readings can be used for continuous scrolling with a threshold.

Power management: the display’s backlight can be PWM-controlled to save power. At 50% duty cycle, the current drops to 10mA. The joystick doesn’t consume power in idle. The microcontroller can enter sleep mode between updates, but that’s complex. For battery-powered projects, use an ESP32 with deep sleep and wake on joystick button press. The display’s resistive touch can wake the system if you connect the touch output to an interrupt pin. However, the resistive touch panel requires power to detect touches, so it’s not ideal for low-power systems. A better approach is to use the joystick’s button as a wake source.

Testing procedure: after wiring, run a test sketch that reads the joystick and displays the raw values on the screen. Move the joystick to all extremes and verify the values. Then test the resistive touch by pressing the screen and reading the coordinates. If the touch values are inverted (e.g., left is right), swap the X+ and X- connections or invert the mapping in code. The display’s orientation can be changed with the setRotation() function (0-3). The joystick’s orientation is fixed, so you may need to swap X and Y axes in code if the joystick is mounted sideways. The select button’s logic level can be inverted if you use a pull-down resistor instead of pull-up.

Error handling: if the display doesn’t show anything, check the SPI connections and the reset pin. The ST7789V requires a low pulse on the reset pin to initialize. If the joystick readings are stuck at 0 or 1023, check the VCC and GND connections. The resistive touch may show random values if the pins are not configured correctly. Use a multimeter to verify the voltage on the touch pins when pressed. The display’s backlight may not work if the LED pin is not connected or the resistor is too high. The typical forward voltage of the backlight LED is 3.2V, so a 100Ω resistor with 5V gives 18mA, which is safe. If you use 3.3V, omit the resistor or use a 10Ω resistor.

This approach gives you a functional 2.4-inch resistive TFT display with joystick control, suitable for menus, games, or data visualization. The combination of analog joystick and resistive touch provides redundancy and flexibility. The code is modular and can be extended to include graphics, text, and touch gestures. The library’s functions like drawBitmap() can display images stored in flash memory. The joystick’s analog output can be used for proportional control, like volume sliders. The resistive touch can be used for keyboard input. The display’s 240x320 resolution is enough for 20 lines of text (8x8 font) or 10 lines of large text (16x16 font). The joystick’s select button can be used for a context menu. The touch can be used for drag-and-drop. The total project cost is under $20 for the display and joystick, plus a microcontroller.

One long read in your inbox each Wednesday.

Reviews, interviews, and festival dispatches from working critics — read by 42,800+ subscribers. Free, no tracking.

Subscribe to the Newsletter