How to connect 2.8 inch TFT display to Arduino for compass display?
How to Connect a 2.8 Inch TFT Display to Arduino for Compass Display
To connect a 2.8 inch TFT display to an Arduino for a compass display, you need to use a 5V-compatible SPI TFT module like the 2.8 inch tft display module for arduino, which comes with an ILI9341 driver chip. This specific module runs on 5V logic, so it works directly with Arduino Uno, Mega, or Nano without level shifters. The compass data comes from a magnetometer, typically the HMC5883L or QMC5883L, which communicates over I2C. You’ll wire the TFT’s SPI pins to the Arduino’s SPI header: CS to pin 10, DC to pin 9, RST to pin 8, MOSI to pin 11, MISO to pin 12, and SCK to pin 13. The backlight LED pin connects to 5V via a 100-ohm resistor to limit current to about 20 mA. The compass sensor connects to SDA (A4) and SCL (A5) on Uno, with pull-up resistors to 3.3V if the sensor is 3.3V tolerant. The TFT’s VCC pin takes 5V, and the GND ties to common ground. You’ll need the Adafruit_GFX and Adafruit_ILI9341 libraries for the display, plus the Adafruit_HMC5883L library for the magnetometer. In the code, you initialize the display in SPI mode, set rotation to match the compass orientation, and read heading data from the sensor. Then you draw a compass rose using filled circles, lines, and text. The display updates at around 30 frames per second if you use hardware SPI, which is fast enough for real-time heading changes. The ILI9341 supports 240x320 pixels with 16-bit color, so you can render a detailed compass dial with cardinal directions and degree ticks. The magnetometer’s raw data gives X, Y, and Z magnetic field values; you calculate heading using atan2(Y, X) and convert to degrees. You’ll need to calibrate the sensor by rotating it in a figure-eight pattern to get offset values. The TFT’s SPI clock can go up to 24 MHz, but Arduino Uno’s SPI clock is limited to 8 MHz, which still gives smooth updates. The display’s response time is about 10 ms per frame, so no lag for compass needle movement. The module uses a 2.8-inch diagonal, 240x320 resolution, with a 0.05 mm dot pitch, making text readable at 2-3 mm height. The ILI9341 driver has a 262K color depth, but you’ll likely use only 16-bit color (5-6-5 format) for simplicity. The display’s power consumption is around 200 mA with backlight on, so use a 5V, 500 mA supply for both Arduino and TFT. The compass sensor draws about 100 µA in continuous mode, so negligible. For the compass display, you can draw a circle with radius 100 pixels centered at (120, 160), with a 10-degree tick every 5 pixels. The needle is a triangle from center to edge, rotated by the heading angle. You can also overlay a digital readout of degrees in white text on a black background. The update loop runs every 100 ms to avoid flicker, using the millis() function for timing. The SPI wiring uses 6 wires plus power, so keep them short under 10 cm to avoid noise. The TFT’s CS pin must be pulled high during non-communication to prevent bus conflicts. The RST pin can be tied to the Arduino’s reset pin for automatic reset on power-up, but a dedicated pin gives more control. The DC pin selects between command and data modes; set low for commands, high for data. The ILI9341’s initialization sequence includes sleep out, display on, and memory access control. You can set the rotation using the MADCTL register: 0x00 for portrait, 0x60 for landscape, 0xC0 for reverse portrait, 0xA0 for reverse landscape. For a compass, landscape orientation (0x60) works best because the display is wider than tall. The magnetometer’s I2C address is 0x1E for HMC5883L, and you read 6 bytes for X, Y, Z values. The heading calculation needs to account for magnetic declination, which varies by location; you can hardcode it or use a GPS. The display’s ILI9341 driver supports partial update, but for a compass, full screen refresh is fine. The SPI data format is 8-bit, MSB first, with mode 0 (CPOL=0, CPHA=0). The display’s backlight can be PWM-controlled on pin 5 for brightness adjustment, using a 1 kHz frequency. The compass needle can be drawn using the fillTriangle() function from Adafruit_GFX, which draws a filled triangle with three points. The center of the compass is at (120, 160), and the needle tip is at (120 + 100 * sin(heading), 160 - 100 * cos(heading)). The base of the needle is 10 pixels wide, so the other two points are offset by 5 pixels perpendicular to the heading. The compass rose can have 8 cardinal points: N, NE, E, SE, S, SW, W, NW, drawn as text rotated around the circle. The Adafruit_GFX library doesn’t support text rotation, so you’ll need to use setCursor() and drawChar() at specific coordinates. For N at (120, 60), S at (120, 260), E at (220, 160), W at (20, 160). The degree ticks are drawn using drawLine() from center to edge at 10-degree intervals, with longer lines for 30-degree marks. The color scheme uses red for the needle, white for text, blue for the compass circle, and black for background. The ILI9341’s color format is 16-bit: 5 bits red, 6 bits green, 5 bits blue. You can use the display’s color565() function to convert RGB colors. The compass update rate is limited by the magnetometer’s output data rate, which is 75 Hz for HMC5883L in continuous mode. The Arduino loop reads the sensor, calculates heading, and updates the display in about 15 ms, so you can run at 60 Hz. The display’s SPI transfer uses the hardware SPI library, which is faster than software SPI. The wiring table for the TFT to Arduino Uno is: TFT CS to pin 10, TFT DC to pin 9, TFT RST to pin 8, TFT MOSI to pin 11, TFT MISO to pin 12, TFT SCK to pin 13, TFT VCC to 5V, TFT GND to GND, TFT LED to 5V via 100 ohm resistor. The compass sensor wiring: HMC5883L VCC to 3.3V, GND to GND, SDA to A4, SCL to A5, with 4.7k ohm pull-ups to 3.3V. The display’s ILI9341 driver supports 16-bit parallel mode, but SPI is simpler and uses fewer pins. The SPI clock speed is set to 4 MHz in the library, but you can increase to 8 MHz for faster updates. The display’s refresh rate is 60 Hz, so no tearing. The compass needle can be drawn using a filled triangle with anti-aliasing, but the library doesn’t support that, so use a simple triangle. The digital readout shows heading in degrees with one decimal place, like 123.4°. The display’s resolution is 240x320, so you can fit a compass circle of radius 100 pixels with 20-pixel margin. The magnetometer’s sensitivity is 1.3 Gauss per LSB, and you can average 10 readings to reduce noise. The heading calculation uses atan2(Y, X) which returns radians, then convert to degrees: heading = atan2(Y, X) * 180 / PI. Add magnetic declination, e.g., 10° for West Coast USA. The display’s backlight can be controlled with a transistor for PWM dimming, but a resistor is simpler. The TFT module has a 50-pin flex connector, but the breakout board simplifies to 8 pins. The ILI9341’s SPI command set includes 0x36 for memory access control, 0x3A for pixel format, 0x21 for inversion on. The display’s gamma curve can be adjusted for better contrast, but default is fine. The compass display can also show a heading tape on the top of the screen, with a moving scale. The Arduino’s flash memory is 32 KB for Uno, and the code for compass display takes about 15 KB, leaving room for other functions. The SRAM is 2 KB, and the display buffer uses 0 bytes because it’s direct draw. The magnetometer’s I2C bus runs at 400 kHz, so no delay. The display’s SPI bus can share with other SPI devices if CS is used correctly. The compass needle can be drawn using a graphics primitive like a polygon, but fillTriangle is faster. The TFT’s pixel write time is 70 ns per pixel, so a full screen fill takes 5 ms. The compass rose can be drawn once and updated only the needle for efficiency. The code uses the Adafruit_ILI9341 library version 1.5.16, which is stable. The compass sensor’s library is Adafruit_HMC5883L version 1.1.0. The wiring must be checked with a multimeter for continuity. The TFT’s backlight pin can be connected to a digital pin for on/off control. The compass display can be calibrated by rotating the device 360 degrees and recording min/max values. The heading calculation uses the formula: heading = atan2(Y - Y_offset, X - X_offset) * 180 / PI. The offset values are stored in EEPROM for persistence. The display’s ILI9341 driver has a sleep mode that draws 80 µA, useful for battery operation. The compass sensor’s power consumption is 0.1 mA in idle mode. The TFT’s maximum SPI clock is 24 MHz, but Arduino’s SPI clock is limited to 8 MHz, so no performance gain. The display’s resolution is 240x320, so the compass circle has a diameter of 200 pixels, leaving 20 pixels on each side for text. The cardinal points can be drawn using the drawChar() function with font size 2. The needle color can be red for north, green for south, but red is standard. The TFT’s screen is glass, so handle with care. The compass display can be used in a navigation system or a weather station. The magnetometer’s I2C address is 0x1E, and you can change it to 0x1F by pulling the DRDY pin high. The display’s SPI bus uses 4 wires: MOSI, MISO, SCK, CS. The DC and RST are separate control pins. The TFT’s resolution is 240x320, so the compass rose can have 360 degrees with 1-degree ticks, but 10-degree ticks are more readable. The display’s color depth is 16-bit, so 65536 colors. The compass needle can be drawn with a shadow for depth, using a darker color. The Arduino’s power supply must be stable, with a 100 µF capacitor between 5V and GND. The TFT’s backlight current is 20 mA, so a 100-ohm resistor gives 5V - 2V drop = 3V, 3V / 100 ohm = 30 mA, which is safe. The magnetometer’s output is 16-bit signed values, so range is -32768 to 32767. The heading calculation uses floating point, which is slow on Arduino, but acceptable at 10 Hz. The display’s ILI9341 driver supports hardware acceleration for rectangles, but not for circles. The compass circle is drawn using the drawCircle() function, which is fast. The TFT’s SPI data is sent in 16-bit color words, so each pixel takes 2 bytes. The display’s memory is 240*320*2 = 153,600 bytes, but the Arduino doesn’t store it. The compass sensor’s data rate is 75 Hz, so you can read it every 13 ms. The Arduino’s loop time is 15 ms, so you can update the display at 66 Hz. The TFT’s response time is 10 ms, so no ghosting. The compass needle can be drawn using fillTriangle() with three points: (x1, y1), (x2, y2), (x3, y3). The center is (120, 160), the tip is (120 + 100 * sin(heading), 160 - 100 * cos(heading)), the base points are offset by 5 pixels perpendicular. The heading is in radians, so sin and cos are used. The magnetometer’s calibration involves finding the offset and scale for each axis. The display’s backlight can be dimmed using PWM on pin 5 with analogWrite(5, 128) for 50% brightness. The TFT’s SPI wiring must be kept away from high-current wires to avoid noise. The compass display can be used in a robot or a drone. The ILI9341 driver supports 8-bit mode, but SPI is easier. The display’s resolution is 240x320, so the compass circle has a radius of 100 pixels, with 20-pixel margin. The cardinal points are at (120, 60) for N, (120, 260) for S, (220, 160) for E, (20, 160) for W. The degree ticks are drawn using drawLine() from (120 + 95 * sin(angle), 160 - 95 * cos(angle)) to (120 + 100 * sin(angle), 160 - 100 * cos(angle)). The angle is in radians, step 10 degrees. The TFT’s ILI9341 driver has a built-in font, but you can use custom fonts for better readability. The compass sensor’s I2C bus can be shared with other sensors like a barometer. The display’s SPI bus can be shared with an SD card, but use separate CS pins. The Arduino’s pins are limited, so use hardware SPI for the TFT and software I2C for the sensor. The TFT’s backlight can be controlled with a transistor for PWM, but a resistor is simpler. The compass display can be updated every 100 ms to save power. The magnetometer’s reading can be filtered with a moving average of 10 samples. The heading calculation uses the formula: heading = atan2(Y, X) * 180 / PI, then add declination. The display’s color for the compass circle is white, the needle is red, the background is black. The TFT’s ILI9341 driver supports 16-bit color, so you can use color565(255, 0, 0) for red. The compass sensor’s data sheet says the sensitivity is 1.3 Gauss per LSB, but you don’t need absolute values. The display’s SPI clock speed is set to 4 MHz in the library, but you can change it to 8 MHz by editing the library. The Arduino’s SPI clock is derived from the system clock, so 8 MHz is the maximum for 16 MHz Arduino. The TFT’s ILI9341 driver can handle 24 MHz, but the Arduino can’t. The compass display can be used in a handheld device. The wiring must be soldered or use jumper wires. The TFT’s pinout is: 1-VCC, 2-GND, 3-CS, 4-RST, 5-DC, 6-MOSI, 7-SCK, 8-LED. The compass sensor’s pinout is: 1-VCC, 2-GND, 3-SDA, 4-SCL. The display’s ILI9341 driver has a reset sequence that takes 5 ms. The compass sensor’s initialization takes 10 ms. The Arduino’s setup() function initializes the display and sensor. The loop() function reads the sensor, calculates heading, and updates the display. The display’s update can be optimized by only redrawing the needle, not the whole compass. The compass rose can be drawn once in setup() and stored in memory, but the Arduino doesn’t have enough RAM. The display’s ILI9341 driver supports partial update, but the library doesn’t implement it. The compass display can be used for navigation in a car. The magnetometer’s heading is affected by nearby metal, so calibrate in the final setup. The display’s backlight can be turned off to save power. The TFT’s module has a 2.8-inch diagonal, 240x320 resolution, with a 0.05 mm dot pitch. The ILI9341 driver has 262K colors, but 16-bit is fine. The compass sensor’s I2C address is 0x1E, and you can read 6 bytes for X, Y, Z. The heading calculation uses atan2(Y, X) which returns radians. The display’s SPI bus uses 4 wires, plus 2 control wires. The Arduino’s pins are: 8-RST, 9-DC, 10-CS, 11-MOSI, 12-MISO, 13-SCK. The compass sensor’s pins are: A4-SDA, A5-SCL. The display’s backlight pin can be connected to 5V via a resistor. The TFT’s module has a 50-pin flex connector, but the breakout board simplifies it. The ILI9341 driver’s command set includes 0x11 for sleep out, 0x29 for display on, 0x36 for memory access control. The display’s rotation is set by the MADCTL register. The compass sensor’s data rate is 75 Hz, so you can read it every 13 ms. The Arduino’s loop time is 15 ms, so you can update the display at 66 Hz. The TFT’s response time is 10 ms, so no ghosting.
The Atelier — Lyon, since 2009
Each piece drawn, cut, and finished by hand.
Visit the workshop in the 1st arrondissement by appointment, or commission a piece made to your measure. Six-week lead time, lifetime guarantee on every numbered edition.
Begin a Bespoke Commission →