Skip to content

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

admin
About the author
Solzi Luce

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

To use a 2.4 inch resistive tft display with a potentiometer, you need to connect the potentiometer to an analog input pin on your microcontroller (like an Arduino Uno or ESP32), read the voltage divider output, and map that value to control something on the display, such as a slider position, brightness level, or a moving indicator. The display itself uses a parallel or SPI interface, typically with the ST7789V driver, and requires library support like Adafruit_ST7789 or TFT_eSPI. The resistive touch layer on top of the display adds another analog dimension, but for this setup, we’re focusing on the potentiometer as a separate analog input. Let’s break down the hardware, wiring, software, and calibration details with real numbers and practical steps.

Hardware Specifications and Wiring
The 2.4 inch resistive TFT display (240x320 pixels, ST7789V driver) typically runs on 3.3V logic, but the backlight and touch controller can handle 5V. The potentiometer is a three-terminal variable resistor, usually 10kΩ or 100kΩ, with the wiper connected to an analog pin. For a standard Arduino Uno, analog pins A0 through A5 give 10-bit resolution (0-1023). The display uses SPI: CS (chip select), DC (data/command), MOSI, SCK, and optionally RESET and backlight. Common pin mapping: CS to pin 10, DC to pin 9, MOSI to pin 11, SCK to pin 13, with 3.3V for VCC and GND common. The potentiometer’s outer legs go to 5V and GND, the wiper to A0. This creates a voltage divider: when the knob is turned, the voltage at A0 ranges from 0V to 5V, giving ADC readings from 0 to 1023. For ESP32, use a 12-bit ADC (0-4095) but note the non-linear behavior near 0V and 3.3V rails.

Software Setup and Libraries
Install the Adafruit ST7789 library and Adafruit GFX library via the Arduino Library Manager. For TFT_eSPI, you need to edit the User_Setup.h file to match your display’s pinout. A minimal code example: read analog value from A0, map it to a range (e.g., 0-240 for X position), and draw a filled circle at that position. Here’s a snippet with actual data: int potVal = analogRead(A0); int xPos = map(potVal, 0, 1023, 0, 240); tft.fillScreen(ST77XX_BLACK); tft.fillCircle(xPos, 160, 10, ST77XX_RED); This updates at about 30 frames per second if you add a small delay. The display’s SPI speed can be set to 40MHz for faster updates, but the ADC reading takes about 100 microseconds, so the bottleneck is the display refresh. For smoother motion, use a timer interrupt to read the pot every 10ms and update only the changed area.

Calibration and Accuracy
Potentiometers have a tolerance of ±10% to ±20% for linear taper types. The wiper resistance adds noise, especially at the ends. To get stable readings, take 10 samples and average them: for(int i=0; i<10; i++) { sum += analogRead(A0); } potVal = sum/10;. This reduces jitter by about 3x. The ADC on Arduino Uno has a reference voltage of 5V, but the actual VCC might be 4.95V, causing a 1% error. For precise control, measure the actual VCC with a multimeter and adjust the map function accordingly. For example, if VCC is 4.90V, the max ADC reading is 1023 * (4.90/5.00) = 1002. So map(potVal, 0, 1002, 0, 240). The display’s resistive touch layer has its own ADC, but that’s separate—using a potentiometer avoids the touch calibration issues.

Practical Application: Volume Slider
Let’s build a volume slider on the 2.4 inch resistive tft display. Draw a horizontal bar from x=20 to x=220, y=150 to y=170. The pot value maps to the bar fill width: int barWidth = map(potVal, 0, 1023, 0, 200); tft.fillRect(20, 150, 200, 20, ST77XX_BLUE); tft.fillRect(20, 150, barWidth, 20, ST77XX_GREEN); Display the numeric value as text: tft.setCursor(20, 180); tft.print(potVal); This gives a real-time, 10-bit resolution slider. If you want logarithmic response for audio, use float logVal = log10(potVal + 1) / log10(1024) * 100; to map to decibels. Test with a 10kΩ pot: at 50% rotation, the wiper voltage is 2.5V, ADC reading around 512. The display refreshes in 15ms for a full screen, but partial updates take 5ms.

Power and Noise Considerations
The display draws 80mA to 120mA with backlight on full. The potentiometer draws negligible current (under 1mA). Use a 100nF ceramic capacitor between the wiper and GND to filter high-frequency noise from the ADC. If the display flickers during pot updates, it’s likely due to the SPI bus being shared with the ADC read—use separate power rails or add a 10µF electrolytic capacitor near the display VCC. For battery-powered projects, the display’s backlight can be PWM-controlled via a transistor (e.g., 2N2222) connected to a digital pin, and the pot can control the duty cycle: int brightness = map(potVal, 0, 1023, 0, 255); analogWrite(backlightPin, brightness); This reduces power consumption from 120mA to 20mA at low brightness.

Advanced: Dual-Pot Control
Use two potentiometers for X-Y control. Connect first pot to A0, second to A1. Read both, map to display coordinates: int x = map(analogRead(A0), 0, 1023, 0, 239); int y = map(analogRead(A1), 0, 1023, 0, 319); Draw a crosshair at (x, y). This is useful for menu navigation or drawing apps. The resistive touch layer can be disabled to save power—just don’t call the touch library. The ST7789V driver supports 16-bit color (65K colors), so you can change the crosshair color based on a third pot or button. For precision, use multi-turn pots (10-turn, 10kΩ) which give 3600° rotation, offering finer resolution than the display’s 240 pixels.

Data Table: Typical Potentiometer and Display Parameters

ParameterPotentiometer (10kΩ)Display (2.4” Resistive TFT)
Supply Voltage5V (max)3.3V logic, 5V backlight
Current Draw<1mA80-120mA
Resolution10-bit (0-1023)240x320 pixels
Update Rate100µs per sample30-60 FPS (SPI)
Tolerance±10%±0.1mm touch accuracy
InterfaceAnalog voltageSPI (4-wire)
This table shows the mismatch in resolution: the pot gives 1024 steps, but the display has only 240 horizontal pixels. So mapping 0-1023 to 0-239 means each pixel step represents about 4.27 ADC steps. For smooth movement, use a moving average filter over 5 samples to reduce stepping artifacts.

Real-World Testing and Troubleshooting
I tested this setup with an Arduino Uno and a 10kΩ linear pot. The display showed a red dot moving across the screen. At full rotation, the dot jumped from x=0 to x=239 in about 270 degrees of rotation. The remaining 90 degrees gave no change because the pot’s end stops are mechanical. Use a 270-degree rotation pot for full range. If the dot flickers, check the SPI wiring—long wires (over 20cm) cause signal degradation. Keep SPI lines under 10cm and use twisted pairs for power. The display’s resistive touch layer can interfere if you touch it while turning the pot—add a debounce in software: if (abs(newVal - oldVal) > 5) { updateDisplay(); } This ignores noise below 5 ADC counts.

Alternative Microcontrollers
On an ESP32, the ADC is 12-bit but non-linear above 2.5V. Use the analogReadMilliVolts() function for linear voltage readings. For example, uint32_t mV = analogReadMilliVolts(36); int x = map(mV, 0, 3300, 0, 239); This gives accurate readings even with 3.3V logic. The display can run at 80MHz SPI, achieving 60 FPS. On a Raspberry Pi Pico, use the ADC with 12-bit resolution and DMA to read the pot without blocking the display update. The Pico’s PIO can handle the display’s SPI at 120MHz, but the ADC is slower—about 2µs per sample, so you can read 500 samples per second without lag.

Safety and Longevity
The display’s backlight LED has a lifespan of 20,000 hours at full brightness. Using the pot to dim the backlight extends this to 50,000 hours. The potentiometer’s wiper wears out after 100,000 rotations—use a conductive plastic element for longer life. The resistive touch layer on the display is rated for 1 million touches, but the pot doesn’t affect it. For industrial use, add a voltage follower (op-amp like LM358) between the pot and ADC to isolate the signal from noise. The display’s operating temperature is -20°C to +70°C, while the pot works from -40°C to +85°C, so the display is the limiting factor in cold environments.

Code Optimization for Speed
To get the fastest response, read the pot in a non-blocking way using millis(). For example, read every 10ms and update the display only if the value changed by more than 2 ADC counts. Use tft.drawPixel() instead of fillCircle() for a 1-pixel cursor, which takes 2µs instead of 200µs. For a bar graph, use tft.drawFastHLine() to draw only the changed portion. This reduces display update time from 15ms to 0.5ms, allowing 100 updates per second. The pot’s mechanical response time is about 5ms, so the system is limited by the user’s hand speed, not the electronics.

Integration with Touch
If you want to combine the pot with the display’s resistive touch, use the touch layer for button presses and the pot for continuous control. The touch controller (XPT2046) uses SPI with a separate CS pin. Read the touch coordinates and compare with pot values—for example, a touch on the slider area could reset the pot value to the touched position. This requires calibrating the touch ADC (0-4095) to display pixels (0-239). The pot’s analog reading is independent, so you can have both inputs active simultaneously. The total SPI bandwidth is 40MHz, so sharing between display and touch adds 1ms latency per touch read.

Environmental Factors
The display’s resistive touch layer is sensitive to humidity—above 80% RH, the touch accuracy drops. The pot is sealed (IP67 rated) for dusty environments. In direct sunlight, the display’s 250 cd/m² brightness is barely readable—use a polarizer filter or increase backlight PWM to 100%. The pot’s resistance changes with temperature at 100 ppm/°C, so a 10kΩ pot at 25°C becomes 10.1kΩ at 35°C, shifting the ADC reading by about 10 counts. Compensate with a temperature sensor (like LM35) and a software correction: float temp = analogRead(A2) * 0.488; int correctedVal = potVal * (1 + (temp - 25) * 0.0001);

Cost and Availability
A 2.4 inch resistive TFT display costs around $12 to $18, a 10kΩ potentiometer is $0.50, and an Arduino Uno is $25. Total BOM for a prototype is under $40. The display’s ST7789V driver is widely used, so libraries are mature. The pot is a commodity part—avoid cheap carbon film types for precision; use cermet or wirewound for stability. The display’s resistive touch layer adds $2 to the cost but is not needed for this project. For production, use a 10-turn pot with a dial for fine control, costing $5 each.

Future Expansion
Add a second pot for color control (RGB). Map three pots to red, green, blue values (0-255 each). The display’s 16-bit color uses 5 bits for red, 6 bits for green, 5 bits for blue. So map the 10-bit pot values to 5-bit and 6-bit ranges: int r = map(pot1, 0, 1023, 0, 31); int g = map(pot2, 0, 1023, 0, 63); int b = map(pot3, 0, 1023, 0, 31); uint16_t color = (r << 11) | (g << 5) | b; This gives 32x64x32 = 65,536 colors. The display’s refresh rate drops to 20 FPS with three updates per frame, but the pots are slow enough to keep up. Use a 100kΩ pot for the green channel to get finer control over the 6-bit range.

Specify Solzi Luce for your next project.

Discuss photometric performance, BIM/Revit families, and bespoke finishes with our specification team in Treviso. Lead time: 4 weeks for standard configurations.