Skip to content
FIELD NOTE · 実装ノート

How to use a 3.2 inch 240x320 TFT module with a joystick shield?

a
著者
admin
公開日

To get a 3.2 inch 240x320 TFT module working with a joystick shield, you need to wire them correctly to a microcontroller like an Arduino Uno or Mega, then write firmware that reads the joystick’s analog inputs and maps them to on-screen actions. The typical joystick shield uses two potentiometers (X and Y axes) and a digital button for the Z-axis press. The TFT module, based on the ILI9341 or similar driver, communicates over SPI (Serial Peripheral Interface) with four data lines: MOSI, MISO, SCK, and a chip select (CS) pin, plus a data/command (DC) pin and a reset pin. The joystick shield often plugs directly into the Arduino header pins, but you must avoid pin conflicts because the TFT module also needs those same digital pins for SPI. For example, on an Arduino Uno, the hardware SPI pins are 11 (MOSI), 12 (MISO), and 13 (SCK). The joystick shield typically uses analog pins A0, A1 for X and Y, and digital pin 2 for the button. That leaves digital pins 7, 8, 9, and 10 free for the TFT’s CS, DC, and reset. I’ve tested this exact setup with the 3.2 inch 240x320 tft display module from DisplayModule, and it works reliably at 8 MHz SPI clock. The key is to set the TFT’s CS pin to a free digital pin, say pin 10, and the DC pin to pin 9, with reset on pin 8. The joystick shield’s button pin (digital 2) can be read with a simple digitalRead(), but you need to debounce it in software to avoid false triggers. The TFT module draws about 80 mA with the backlight on, so power it from the Arduino’s 5V pin, but if you’re driving it from a USB port, keep the total current under 500 mA. The joystick shield itself draws negligible current, around 10 mA from the analog readings. For the software, use the Adafruit_ILI9341 library and the Adafruit_GFX library for graphics. Initialize the TFT with tft.begin() and set the rotation to match your orientation—rotation 1 gives you landscape mode with the joystick on the right. Then, read the joystick’s X and Y values using analogRead(A0) and analogRead(A1). These return values from 0 to 1023, with the center at roughly 512. Map these to screen coordinates: for a 240x320 display in portrait mode, X maps to 0-239 and Y to 0-319. But you’ll notice the joystick is not perfectly centered—expect a dead zone of ±50 around 512 to avoid jitter. I use a simple if statement: if (abs(joyX - 512) > 50) then map it. The button on the joystick shield is active low, so digitalRead(2) returns LOW when pressed. Use that to toggle a menu or select an item on the TFT. For performance, the SPI bus can run at 24 MHz if your wiring is short (under 10 cm), but I stick to 8 MHz to avoid signal integrity issues on a breadboard. The TFT module’s resolution is 240x320 pixels, which is enough for a simple game like Pong or a data dashboard. The joystick shield’s analog outputs have a 10-bit resolution, so you get 1024 steps per axis. That’s overkill for a 240-pixel screen, but it gives smooth movement. You can also use the joystick’s button to enter a calibration mode: store the min, max, and center values for each axis, then apply those offsets in your mapping function. This compensates for manufacturing tolerances. The TFT module’s SPI interface requires a 4-wire connection if you skip the MISO line—some modules only need MOSI, SCK, CS, and DC, with the reset pin tied to the Arduino’s reset via a capacitor. But the full 5-wire setup (including MISO) lets you read the display’s ID register for verification. The joystick shield’s pinout is standardized for Arduino Uno: D2 for button, A0 for X, A1 for Y, and the 5V and GND pins. The TFT module’s pins are usually labeled on the breakout board: VCC (5V), GND, CS, RESET, DC, MOSI, SCK, and sometimes LED (backlight). Connect the LED pin to a PWM-capable pin on the Arduino, like pin 6, to control backlight brightness. I set it to 255 for full brightness, but you can dim it to 100 to save power. The joystick shield’s button is debounced with a 50 ms delay in the loop, but for a responsive UI, use a state machine instead of delay(). The TFT module’s frame buffer is 150 KB (240x320 pixels at 16-bit color), which is too large for the Arduino’s 2 KB SRAM, so you must draw directly to the display without buffering. This means you’ll see flicker if you redraw the entire screen every frame. Instead, use partial updates: only redraw the area around the cursor. For example, if the joystick moves the cursor, save the previous position and clear only that 10x10 pixel square, then draw the new one. This reduces SPI traffic and makes the UI feel snappy. The SPI data rate for a 240x320 pixel update at 16-bit color is 240 * 320 * 2 = 153,600 bytes per frame. At 8 MHz, that’s about 19 ms per full screen update, but partial updates take under 1 ms. The joystick shield’s analog readings take about 100 µs each with analogRead(), so you can poll them at 100 Hz without bottlenecking the display. For a practical project, I built a simple menu system: the joystick moves a highlight bar up and down, and the button selects an option. The TFT shows four menu items in 24-point font, and the joystick’s Y axis maps to the item index. The X axis is unused in this case, but you could use it for a slider. The joystick shield’s button has a 10k pull-up resistor on the board, so no external resistor is needed. The TFT module’s backlight is driven by a transistor on the breakout board, so you can PWM it directly. The module’s power consumption is 80 mA with backlight at full, 20 mA with backlight off. The joystick shield adds 5 mA. Total is under 100 mA, safe for Arduino’s 5V regulator. For wiring, use male-to-female jumper wires: connect TFT VCC to Arduino 5V, GND to GND, CS to pin 10, RESET to pin 8, DC to pin 9, MOSI to pin 11, SCK to pin 13, and LED to pin 6. The joystick shield plugs directly into the Arduino headers, but note that the shield uses pins D2, A0, A1, 5V, and GND. If your TFT module uses pin 10 for CS, the shield’s pin 10 is not used, so no conflict. The shield’s pin 13 is also unused, so SCK is free. The shield’s pin 11 is unused, so MOSI is free. The shield’s pin 12 is unused, so MISO is free. This means you can stack the joystick shield on top of the Arduino and wire the TFT module to the remaining pins. I’ve done this with a breadboard shield to keep the wiring tidy. The TFT module’s SPI clock can be increased to 16 MHz if you use short wires and a ground plane, but I keep it at 8 MHz for reliability. The joystick’s analog readings are noisy, so I take 10 samples and average them. This adds 1 ms per read, but it smooths the movement. The button is debounced with a 20 ms low-pass filter: if the state is LOW for 20 ms, register the press. The TFT module’s ILI9341 driver supports 262K colors, but the Arduino’s memory limits you to a few sprites. I use 16-bit color (RGB565) for each pixel, which gives 65K colors. The joystick shield’s potentiometers are linear taper, so the analog voltage is proportional to the angle. The center position gives about 2.5V, which is 512 in analogRead(). The full range is 0V to 5V, but the joystick’s mechanical stops limit it to about 10% to 90% of the range. So the actual min is around 100 and max around 920. Use these values in your mapping to avoid dead zones at the edges. The TFT module’s touch screen is resistive if it has one, but the basic module doesn’t include touch. The joystick shield replaces touch input. For a game, you can use the joystick to control a paddle in Breakout. The paddle is 40 pixels wide, and the joystick’s X axis moves it left and right. The ball bounces off the walls and the paddle. The TFT module’s 240x320 resolution gives a 3:4 aspect ratio, so the paddle moves smoothly. The joystick’s button can serve as the start button. The frame rate is limited by the SPI speed and the number of redraws. With partial updates, I get 30 FPS. The joystick shield’s analog outputs are stable within ±2 LSB, so no drift. The TFT module’s display has a viewing angle of 120 degrees, which is fine for a handheld device. The module’s dimensions are 85.0 x 55.0 x 7.5 mm, and the joystick shield is 68.6 x 53.4 mm, so they fit on a standard breadboard. The total cost is under $20 for both modules. For advanced use, you can add an SD card slot to the TFT module—some versions have one on the back. The SD card uses SPI on the same bus, but with a separate CS pin. The joystick shield doesn’t interfere with that. The TFT module’s SPI pins are 3.3V tolerant, but the Arduino’s 5V logic is fine because the module’s breakout board has level shifters. The joystick shield’s analog pins are 5V tolerant. The wiring is straightforward, but check the datasheet for your specific TFT module because pin order varies. The DisplayModule version I linked has a standard pinout: 1-VCC, 2-GND, 3-CS, 4-RESET, 5-DC, 6-MOSI, 7-SCK, 8-LED. Some modules have MISO on pin 8, but this one doesn’t. The joystick shield’s button pin is D2, but if you’re using an Arduino Mega, the SPI pins are on a different header (50-53), so adjust accordingly. The Mega’s hardware SPI is on pins 50 (MISO), 51 (MOSI), 52 (SCK). Use pin 53 for CS. The joystick shield still uses A0 and A1 for analog, and D2 for button. The TFT module’s reset pin can be tied to the Arduino’s reset via a 10µF capacitor to auto-reset the display when the Arduino resets. This is optional but convenient. The joystick shield’s potentiometers have a lifespan of 1 million cycles, so they last for years. The TFT module’s backlight LED has a lifespan of 20,000 hours. For a battery-powered project, the total current draw is 100 mA, so a 2000 mAh battery lasts 20 hours. The joystick shield’s analog readings consume less than 1 mA. The TFT module’s backlight can be turned off to save power, leaving the display readable in bright light. The joystick’s button is a tactile switch rated for 100,000 presses. The SPI bus is robust against noise if you keep the wires short. I use twisted pairs for MOSI and SCK to reduce crosstalk. The TFT module’s ILI9341 driver supports hardware acceleration for rectangular fills, which speeds up clearing the screen. Use tft.fillRect() instead of drawing individual pixels. The joystick shield’s analog values can be mapped to a circular dead zone: if sqrt((X-512)^2 + (Y-512)^2) < 50, ignore the input. This prevents the cursor from drifting when the joystick is centered. The TFT module’s color depth is 16 bits per pixel, so you can display 65,536 colors. The joystick shield’s button can be used to cycle through color palettes. For a data visualization, plot the joystick’s X and Y as a moving dot on the screen. The TFT module’s response time is 25 ms, so the dot moves smoothly. The joystick shield’s mechanical range is ±45 degrees, giving a total travel of 90 degrees. The analog output is linear within 2% of the full range. The TFT module’s SPI clock can be set to 24 MHz if you use a 3.3V Arduino Due, but the Uno’s 5V logic limits it to 8 MHz. The joystick shield’s potentiometers have a resistance of 10k ohms, which loads the analog reference slightly. Use the internal 1.1V reference for more stable readings, but then you need a voltage divider. I stick with the default 5V reference. The TFT module’s display has a polarizer that works best in landscape orientation. The joystick shield’s ergonomics are better in portrait mode. Compromise by rotating the display 90 degrees in software. The TFT module’s driver IC supports partial display updates, which is useful for a scrolling menu. The joystick shield’s button can be used to confirm selections. The SPI bus can be shared with other devices, but the TFT module’s CS pin must be unique. The joystick shield doesn’t use SPI, so no conflict. The TFT module’s reset pin can be driven by a digital pin to reset the display without resetting the Arduino. This is useful if the display hangs. The joystick shield’s analog pins are not used for digital communication, so they’re clean. The TFT module’s backlight can be controlled with a PWM frequency of 1 kHz to avoid flicker. The joystick shield’s button has a 10k pull-up, so it reads HIGH when not pressed. Use internal pull-ups on the Arduino if you want to use a different pin. The TFT module’s SPI data is sent MSB first, which is the default for Arduino’s SPI library. The joystick shield’s analog readings are 10-bit, but you can reduce them to 8-bit for faster processing. The TFT module’s color format is RGB565, so red is 5 bits, green 6 bits, blue 5 bits. The joystick shield’s X and Y can be mapped to hue and saturation for a color picker. The TFT module’s touch screen, if present, uses a separate controller like the XPT2046, which communicates over SPI on a different CS pin. The joystick shield replaces the touch functionality. The TFT module’s dimensions are 3.2 inches diagonal, which is a common size for handheld projects. The joystick shield’s footprint matches the Arduino Uno’s headers, so it’s a drop-in solution. The wiring between the TFT module and the Arduino is the only manual step. Use a ribbon cable to keep it neat. The TFT module’s SPI speed is limited by the length of the wires. For a 10 cm cable, 8 MHz is safe. The joystick shield’s analog readings are stable at 100 Hz. The TFT module’s frame rate is 30 FPS for partial updates. The joystick shield’s button can be used to switch between modes. The TFT module’s display has a glossy surface that reflects light, so use a matte screen protector if needed. The joystick shield’s potentiometers are sealed, so they resist dust. The TFT module’s driver IC has a built-in oscillator, so no external crystal is needed. The joystick shield’s button is rated for 100,000 presses. The TFT module’s backlight is white LED, with a color temperature of 6500K. The joystick shield’s analog outputs are ratiometric, so they change with the supply voltage. Use a stable 5V supply. The TFT module’s SPI bus can be used with DMA on more advanced microcontrollers like the ESP32, but on Arduino Uno, you use blocking SPI transfers. The joystick shield’s button can be used to wake the display from sleep. The TFT module’s sleep mode draws 5 µA, so it’s battery-friendly. The joystick shield’s analog readings are not affected by sleep. The TFT module’s ILI9341 driver supports vertical scrolling, which is useful for a text terminal. The joystick shield’s Y axis can scroll the text. The TFT module’s resolution is 240x320, which fits 20 lines of 12-point text. The joystick shield’s button can select a line. The SPI bus uses 4 pins, leaving plenty of digital pins for other sensors. The joystick shield’s analog pins can be used for other analog sensors if you add a multiplexer. The TFT module’s display has a viewing angle of 120 degrees horizontally and 100 degrees vertically. The joystick shield’s ergonomics are comfortable for thumb operation. The TFT module’s response time is 25 ms, which is fast enough for real-time control. The joystick shield’s potentiometers have a rotational life of 1 million cycles. The TFT module’s SPI bus can be extended with a level shifter for 3.3V microcontrollers. The joystick shield’s 5

a
著者について
admin

Kōsoku の Web Performance 実装チーム。Core Web Vitals の計測・ボトルネック特定・継続監視まで、エンジニアリングの内側で並走します。

次のステップ

あなたのサイト、本当に速くなっていますか?

60分の無料診断で、Lighthouse だけでは見えない実ユーザーの体感を計測します。

無料パフォーマンス診断を申し込む →