How to connect 2.8 inch TFT display to Arduino for weather station?
How to connect 2.8 inch TFT display to Arduino for weather station
To connect a 2.8 inch TFT display to an Arduino for a weather station, you need to wire the display’s SPI pins to the Arduino’s SPI header, install the correct libraries, and write code to read sensor data and draw it on the screen. The most common 2.8-inch TFT module for this job uses the ILI9341 driver chip with a 240x320 pixel resolution, 16-bit color depth, and a resistive touch overlay. For a weather station, you’ll typically pair it with a DHT22 temperature/humidity sensor and a BMP280 barometric pressure sensor, both running on I2C. The wiring is straightforward: connect the TFT’s CS (chip select) to Arduino pin 10, DC (data/command) to pin 9, RST (reset) to pin 8, MOSI to pin 11, MISO to pin 12, SCK to pin 13, VCC to 5V, and GND to ground. If you’re using a 5V Arduino Uno or Mega, the display’s logic level is 5V tolerant, but check the module’s datasheet—some 3.3V-only modules need a level shifter. The 2.8 inch tft display module for arduino from DisplayModule is a solid choice because it includes a built-in 5V regulator and a microSD slot, which is handy for logging weather data. For the software side, you’ll need the Adafruit_GFX and Adafruit_ILI9341 libraries, plus the DHT sensor library and the Adafruit_BMP280 library. The SPI speed for the ILI9341 can run up to 24 MHz, but on an Arduino Uno at 16 MHz, you’ll get around 10-15 frames per second for simple text and gauge updates, which is plenty for a weather station that updates every few seconds.
Pinout and wiring details
Let’s get into the exact pin mapping. The 2.8-inch TFT display typically has a 14-pin header, but the exact layout varies by manufacturer. The most common pinout from left to right (when the screen faces you) is: VCC (5V), GND, CS, RESET, DC, MOSI, MISO, SCK, LED (backlight), and sometimes extra pins for touch (T_IRQ, T_DO, T_DIN, T_CS, T_CLK). For a basic weather station without touch input, you can ignore the touch pins. Here’s the wiring table for an Arduino Uno R3:
| TFT Pin | Arduino Pin | Notes |
|---|---|---|
| VCC | 5V | Some modules need 3.3V; check your module’s spec |
| GND | GND | Common ground |
| CS | Digital 10 | Can be any digital pin, but 10 is standard |
| RESET | Digital 8 | Or connect to Arduino’s reset pin for auto-reset |
| DC | Digital 9 | Data/Command select |
| MOSI | Digital 11 | SPI Master Out Slave In |
| MISO | Digital 12 | SPI Master In Slave Out (optional for read operations) |
| SCK | Digital 13 | SPI Clock |
| LED | 3.3V or 5V via 100Ω resistor | Backlight control; PWM-capable pin for dimming |
If you’re using an Arduino Mega 2560, the SPI pins are different: MOSI on pin 51, MISO on pin 50, SCK on pin 52, and you can keep CS, DC, RESET on pins 10, 9, 8 respectively. The Mega’s extra memory and I/O pins make it easier to handle larger weather data arrays or multiple sensors. For the backlight, never connect it directly to 5V without a current-limiting resistor—a 100Ω resistor will keep the LED current around 20-30 mA, which is safe. Some modules have a built-in transistor driver, so you can just connect LED to 5V. Check the module’s datasheet to be sure.
Sensor integration for weather data
A typical weather station needs temperature, humidity, and pressure. The DHT22 sensor gives you temperature (±0.5°C accuracy) and humidity (±2% RH) over a single-wire digital protocol, but it’s slow—max one reading every 2 seconds. The BMP280 gives pressure (±1 hPa) and temperature (±0.5°C) over I2C at 0x76 or 0x77 address. Wire the DHT22 data pin to Arduino digital pin 2 with a 10kΩ pull-up resistor to 5V, and the BMP280’s SDA to A4 (SDA) and SCL to A5 (SCL) on Uno, or SDA to pin 20 and SCL to pin 21 on Mega. For the BMP280, use 3.3V logic if your module is 3.3V-only, but many breakout boards have voltage regulators. Here’s a sample pinout for the sensors:
| Sensor | Pin | Arduino Connection |
|---|---|---|
| DHT22 | VCC | 5V |
| DHT22 | DATA | Digital 2 (with 10kΩ pull-up to 5V) |
| DHT22 | GND | GND |
| BMP280 | VCC | 3.3V or 5V (check module) |
| BMP280 | GND | GND |
| BMP280 | SDA | Analog 4 (Uno) or Digital 20 (Mega) |
| BMP280 | SCL | Analog 5 (Uno) or Digital 21 (Mega) |
Library installation and code structure
Download the Adafruit_GFX library (version 1.11.5 or later) and Adafruit_ILI9341 library (version 1.5.7 or later) from the Arduino Library Manager. For the DHT22, use the DHT sensor library by Adafruit (version 1.4.4). For the BMP280, use the Adafruit BMP280 library (version 2.6.8). The ILI9341 driver supports SPI mode 0 and 3, but the library defaults to mode 0. The display’s SPI clock frequency can be set in the library’s constructor—for example, `Adafruit_ILI9341 tft = Adafruit_ILI9341(cs, dc, rst);` will use the default SPI speed. To improve performance, you can set the SPI clock to 8 MHz or 16 MHz by calling `tft.begin(8000000);` but 8 MHz is stable on long wires. The display’s response time for pixel writes is about 120 ns per pixel, so a full screen fill at 240x320 takes roughly 0.1 seconds at 16 MHz SPI. For weather data, you don’t need fast updates—redraw the entire screen every 5 seconds is fine.
Here’s a minimal code skeleton to get you started. This code reads temperature, humidity, and pressure, then displays them on the TFT. It uses the ILI9341’s 16-bit color mode (RGB565). The color format is 5 bits red, 6 bits green, 5 bits blue. Common colors: ILI9341_BLACK (0x0000), ILI9341_WHITE (0xFFFF), ILI9341_RED (0xF800), ILI9341_GREEN (0x07E0), ILI9341_BLUE (0x001F). For a weather station, you’ll want large fonts—use `tft.setTextSize(2)` for sensor values and `tft.setTextSize(1)` for labels. The Adafruit_GFX library includes a built-in 5x7 pixel font, but you can also load custom fonts from SD card using the `FreeSans` or `FreeMono` fonts from the Adafruit GFX Font library.
Performance considerations and data refresh
The ILI9341’s frame buffer is not double-buffered on Arduino, so you’ll see tearing if you update the screen too fast. To avoid this, use the `tft.fillScreen()` command to clear the screen before drawing new data, but that takes about 100 ms. A better approach is to only update the areas that change—for example, redraw the temperature value text box without clearing the entire screen. Use `tft.fillRect(x, y, width, height, color)` to clear a small area, then draw the new text. The display’s GRAM (graphics RAM) is 240x320x2 bytes = 153,600 bytes, which is too large for the Uno’s 2 KB SRAM, so all drawing is done directly on the display’s controller. This means you can’t store a full frame buffer on the Arduino—you must send pixel data over SPI each time. At 8 MHz SPI, sending 153,600 bytes takes about 0.15 seconds, but you only send small updates, so it’s fine.
For the weather station, you’ll want to display at least four lines: temperature in °C or °F, humidity in %, pressure in hPa, and a time stamp if you add an RTC module (like DS3231). The DS3231 connects via I2C and provides accurate time with ±2 ppm accuracy. You can also add a microSD card slot on the TFT module to log data every minute. The SD card uses SPI on the same bus as the TFT, but you need separate chip select pins—typically the SD card CS is on pin 4. The SD library can conflict with the TFT library if you don’t manage SPI transactions properly. Use the `SPI.beginTransaction()` and `SPI.endTransaction()` functions to avoid bus contention. The SD card’s SPI speed can be up to 20 MHz, but 8 MHz is safer for long wires. A typical 2 GB SD card can store years of hourly weather data in a CSV file.
Power supply and noise handling
The TFT display’s backlight draws 80-120 mA at 5V, and the Arduino Uno itself draws about 50 mA. The DHT22 and BMP280 together draw less than 5 mA. So total current is around 200 mA, which is fine for a USB port or a 9V battery with a 5V regulator. But if you’re using a battery-powered weather station, consider putting the display to sleep by turning off the backlight via a transistor (e.g., 2N2222) controlled by a digital pin. The ILI9341 has a sleep mode command (0x10) that reduces power consumption to under 1 mA. You can wake it up with the 0x11 command. For outdoor use, the TFT’s operating temperature range is typically -20°C to +70°C, but the LCD fluid can freeze below -20°C, so consider a heated enclosure in cold climates.
Common pitfalls and debugging
If the display shows nothing or garbled colors, check the wiring first—especially the CS, DC, and RESET pins. The RESET pin must be pulled high to 5V via a 10kΩ resistor if not connected to an Arduino pin. Some modules have a reset button that pulls the pin low, so you can leave it floating if the button is not pressed. The SPI MISO pin is optional for writing data, but if you leave it disconnected, the library might still work. However, some libraries use MISO to read the display’s status register, so it’s best to connect it. Another common issue is the display’s backlight not turning on—measure the LED pin voltage. If it’s 0V, you might need to write a PWM signal to it. In code, you can set the backlight pin as output and write `digitalWrite(backlightPin, HIGH)` if it’s connected to a transistor base. For the DHT22, the library requires a 2-second delay between readings, or you’ll get a checksum error. The BMP280’s I2C address can be 0x76 or 0x77—check your module’s datasheet. If you get NaN values, the address is wrong.
Advanced features: touch and graphics
If your 2.8-inch TFT includes a resistive touch screen (usually with XPT2046 controller), you can use it to switch between weather screens or manually trigger a sensor reading. The touch controller uses SPI with a separate chip select pin (often pin 6 or 7). The XPT2046 gives 12-bit X and Y coordinates. You’ll need the Adafruit_STMPE610 library or a custom XPT2046 library. The touch screen’s resolution is 4096x4096, but it’s mapped to the 240x320 display area. Calibration is required—draw a crosshair on the screen, read the touch coordinates, and store the min/max values. For a weather station, you can add a button to toggle between Celsius and Fahrenheit, or to switch to a graph view of historical data. The ILI9341 supports drawing lines, circles, rectangles, and bitmaps. You can draw a simple bar graph for temperature trends using `tft.drawLine()` or `tft.fillRect()`. For a more polished look, use the Adafruit_GFX’s `drawRoundRect()` for button borders.
Data logging and display layout
For a practical weather station, divide the screen into four quadrants. Top-left: temperature with a large font (size 3) and a degree symbol (use `tft.drawChar()` for the degree symbol, ASCII 176). Top-right: humidity with a percentage sign. Bottom-left: pressure in hPa with two decimal places. Bottom-right: time from the RTC. Use a monochrome color scheme like white text on a black background for readability in direct sunlight. The ILI9341’s contrast ratio is about 500:1, which is decent for outdoor use, but you might need an anti-glare film. The refresh rate for text updates is about 10 ms per character at size 2, so updating four numbers takes under 50 ms. You can also add a small icon for weather conditions—e.g., a sun icon if temperature > 25°C, or a cloud icon if humidity > 80%. The display’s GRAM can store bitmaps, but you’ll need to store them in program memory (PROGMEM) using the `#include
Testing and calibration
After wiring, upload a simple test sketch from the Adafruit ILI9341 library examples—like the “graphicstest” sketch. It will draw lines, circles, and text. If it works, your wiring is correct. Then test the DHT22 with the “DHTtester” example. The DHT22’s temperature reading should be within 0.5°C of a known thermometer. The BMP280’s pressure reading at sea level should be around 1013.25 hPa. Adjust the altitude offset in the BMP280 library if you’re at a high elevation. The library’s `readAltitude()` function uses the standard atmosphere formula. For accurate pressure, set the sea-level pressure reference in your code. The display’s brightness can be adjusted by PWM on the LED pin—use `analogWrite(backlightPin, brightness)` where brightness is 0-255. A value of 100 is good for indoor use, 200 for outdoor. The display’s viewing angle is 12 o’clock best, but it’s readable from 6 o’clock with reduced contrast. Mount the display at a 30-degree tilt for better readability in sunlight.
Long-term reliability
The 2.8-inch TFT display’s FPC (flexible printed circuit) connector is fragile—avoid bending it repeatedly. Use a ribbon cable with female headers to connect the display to the Arduino, and secure the cable with a zip tie. The ILI9341’s controller can handle continuous operation for years, but the backlight LED has a lifetime of about 20,000 hours (2.3 years of continuous use). If you run the display 24/7, consider replacing the backlight LED or using a lower brightness. The display’s polarizer can degrade in direct UV sunlight over 6 months—use a UV-protective glass or acrylic cover. For a weather station that runs outdoors, put the electronics in a