Adafruit 2.4" TFT FeatherWing
Created by lady ada
https://learn.adafruit.com/adafruit-2-4-tft-touch-screen-featherwing
Last updated on 2022-09-16 05:09:03 PM EDT
©Adafruit Industries
Page 1 of 30
Table of Contents
Overview
3
Pinouts
5
•
•
•
•
•
Power Pins
SPI Pins
TFT Control Pins
Touch Screen control pins
SD Card control pins
TFT Graphics Test
11
• Install Libraries
• Install Adafruit ILI9341 TFT Library
• Basic Graphics Test
Adafruit GFX Library
14
Resistive Touch Screen
15
• Touchscreen Paint Demo
Drawing Bitmaps
19
CircuitPython Displayio Quickstart
20
•
•
•
•
•
•
•
Parts
Required CircuitPython Libraries
Code Example Additional Libraries
CircuitPython Code Example
Code Details
Using Touch
Where to go from here
Troubleshooting
28
Downloads
29
• Datasheets & More
• Schematic
• Fabrication Print
©Adafruit Industries
Page 2 of 30
Overview
A Feather board without ambition is a Feather board without FeatherWings! Spice up
your Feather project with a beautiful 2.4" touchscreen display shield with built in
microSD card socket. This TFT display is 2.4" diagonal with a bright 4 white-LED
backlight. You get 240x320 pixels with individual 16-bit color pixel control. It has way
more resolution than a black and white 128x64 display. As a bonus, this display
comes with a resistive touchscreen attached to it already, so you can detect finger
presses anywhere on the screen.
©Adafruit Industries
Page 3 of 30
This FeatherWing uses a SPI display, touchscreen and SD card socket so it works nice
and fast on all our Feathers (including nRF52, ESP8266, 32u4, 328p, M0, M4,
WICED and Teensy 3.x) We also include an SPI resistive touchscreen controller so you
only need one additional pin to add a high quality touchscreen controller. One more
pin is used for an optional SD card that can be used for storing images for display.
This Wing comes fully assembled with dual sockets for your Feather to plug into. You
get two sockets per pin so you can plug in wires if you want to connect to Feather
pins. Alternatively, each pin has a large square pad on the PCB for direct soldering.
©Adafruit Industries
Page 4 of 30
Four mounting holes make it easy to attach this Wing anywhere. We also include a big
reset button and an on/off switch connected to the Feather Enable pin (note that the
Teensy 3.x Feather does not use the Enable pin so the switch will not do anything
with that type).
Pinouts
Unlike most FeatherWings, the TFT FeatherWing is fully assembled and has a dual
socket set for your Feather to plug into.
This makes it really easy to use, but a little different to change if you don't want the
default setup
Power Pins
All power for the FeatherWing comes from the 3.3V and GND pins. That includes the
backlight (which can draw up to 100mA)!
©Adafruit Industries
Page 5 of 30
You can turn off the 3.3V power supply with the EN pin or the switch attached to that
pin. Note that on the Teensy 3x Feather Adapter, this pin doesn't do anything and on
the FONA feather, this will not disable the VBAT power supply which is used to power
the cellular module
©Adafruit Industries
Page 6 of 30
SPI Pins
The TFT display, SD card and touch screen use the SPI interface to communicate.
That means MISO, MOSI and SCK are used whenever either are accessed.
©Adafruit Industries
Page 7 of 30
TFT Control Pins
In addition, for the TFT display there is are D/C (Data/Command) and CS (Chip Select)
pins. These are used to select the display and tell it what kind of data is being sent.
These pins can theoretically be changed by cutting the jumper trace and soldering a
small wire from the right-hand pad to the pin you'd like to use.
On the ESP8266, TFT_CS is pin #0, TFT_DC is pin #15
On the ESP32, TFT_CS is pin #15, TFT_DC is pin #33
On theAtmega32u4, ATmega328P, SAMD21 M0, nRF52840 or SAMD51 M4 Feather,
TFT_CS is pin #9, TFT_DC is pin #10
On the Teensy Feather, TFT_CS is pin #4, TFT_DC is pin #10
On the WICED Feather, TFT_CS is PA15 and TFT_DC is PB4
On the nRF52832 Feather, TFT_CS is #31 and TFT_DC is #11
©Adafruit Industries
Page 8 of 30
There is also LITE pin which is not connected to any pads but you can use to control
the backlight. Pull low to turn off the backlight. You can connect it to a PWM output
pin.
Note: Pin 9 is used for communication with the SIM800 chip on the Feather
Fona. You will have to remap pin 9 to an unused pin when using with a Feather
Fona.
Touch Screen control pins
The touch screen also has a Chip Select line, labeled RT. This pin can theoretically be
changed by cutting the jumper trace and soldering a small wire from the right-hand
pad to the pin you'd like to use.
On the ESP8266, RT is pin #16
On the ESP32, RT is pin #32
On theAtmega32u4, ATmega328P, nRF52840 SAMD21 M0 or SAMD51 M4 Feather, RT
is pin #6
On the Teensy Feather, RT is pin #3
©Adafruit Industries
Page 9 of 30
On the WICED Feather, RT is PC7
On the nRF52832 Feather, RT is #30
There is also an IRQ pin which is not connected to any pads but you can use to detect
when touch events have occured.
SD Card control pins
The SD Card also has a Chip Select line, labeled SD. This pin can theoretically be
changed by cutting the jumper trace and soldering a small wire from the right-hand
pad to the pin you'd like to use.
On the ESP8266, SD is pin #2
On the ESP32 SD is pin #14
On the Atmega32u4, ATmega328P, nRF52840, SAMD21 M0 or SAMD51 M4 Feather,
SD is pin #5
On the Teensy Feather, SD is pin #8
©Adafruit Industries
Page 10 of 30
On the WICED Feather, SD is PC5
On the nRF52 Feather, SD is pin #27
There is also an Card Detect (CD) pin which is not connected to any pads but you can
use to detect when a microSD card has been inserted have occured. It will be shorted
to ground when a card is not inserted.
TFT Graphics Test
The TFT FeatherWing is basically a combination of our 2.4" TFT Breakout (https://
adafru.it/sjD) with the STMPE610 resistive touch-screen breakout attached (http://
adafru.it/1571).
Install Libraries
You'll need a few libraries to use this FeatherWing!
Install Adafruit ILI9341 TFT Library
We have example code ready to go for use with these TFTs.
From within the Arduino IDE, open up the Library Manager...
Search for ILI9341 and install the Adafruit ILI9341 library that pops up!
©Adafruit Industries
Page 11 of 30
Next up, search for Adafruit GFX and locate the core library. A lot of libraries may pop
up because we reference it in the description so just make sure you see Adafruit GFX
Library in bold at the top.
Install it!
If using an earlier version of the Arduino IDE (pre-1.8.10), locate and install Adafruit_Bu
sIO (newer versions handle this prerequisite automatically).
Repeat the search and install steps for the Adafruit_ImageReader library.
For more details about this process, we have a tutorial introducing Arduino library
concepts and installation (https://adafru.it/aYM).
Basic Graphics Test
After installing these libraries, you should see a new example folder called Adafruit_IL
I9341 and inside, an example called graphicstest_featherwing.
Upload that sketch to your Feather. You should see a collection of graphical tests
draw out on the TFT.
©Adafruit Industries
Page 12 of 30
If you're having difficulties, check the serial console.The first thing the sketch does is
read the driver configuration from the TFT, you should see the same numbers as
below. That will help you determine if the TFT is found, if not, check your Feather
soldering!
©Adafruit Industries
Page 13 of 30
Once you've got the demo working, check out the detailed documentation over at htt
p://learn.adafruit.com/adafruit-gfx-graphics-library (https://adafru.it/aPx) for more
information on how to use the GFX library to draw whatever you like!
Adafruit GFX Library
The Adafruit_GFX library for Arduino provides a common syntax and set of graphics
functions for all of our TFT, LCD and OLED displays. This allows Arduino sketches to
easily be adapted between display types with minimal fuss…and any new features,
performance improvements and bug fixes will immediately apply across our complete
offering of color displays.
©Adafruit Industries
Page 14 of 30
The GFX library is what lets you draw points, lines, rectangles, round-rects, triangles,
text, etc.
Check out our detailed tutorial here http://learn.adafruit.com/adafruit-gfx-graphicslibrary (https://adafru.it/aPx)
It covers the latest and greatest of the GFX library. The GFX library is used in both 8bit and SPI modes so the underlying commands (drawLine() for example) are identical!
Resistive Touch Screen
The LCD has a 4-wire resistive touch screen glued onto it. You can use this for
detecting finger-presses, stylus', etc. Normally, you'll need 4 pins to talk to the touch
panel but we decided to go all snazzy and put a dedicated touch screen driver onto
the shield. The driver shares the SPI pins with the TFT and SD card, so only one extra
pin is needed. This allows you to query the controller when you're ready to read
touchscreen data, and saves 3 pins.
To control the touchscreen you'll need one more library (https://adafru.it/d4f) - the
STMPE610 controller library which does all the low level chatting with the STMPE610
driver chip. Use the library manager to install the Adafruit STMPE610 library
©Adafruit Industries
Page 15 of 30
Touchscreen Paint Demo
Now that you've got the basic TFT graphics demo working, let's add in the
touchscreen. Run and upload the touchpaint_featherwing demo
• If you have the 2.4" TFT Featherwing, run the Adafruit ILI9341>touchpaint_featherwing demo
• If you have the 3.5" TFT Featherwing, run the Adafruit HX8357>touchpaint_featherwing demo
Upload to your Feather and have fun!
©Adafruit Industries
Page 16 of 30
The touch screen is made of a thin glass sheet, and its very fragile - a small crack
or break will make the entire touch screen unusable. Don't drop or roughly
handle the TFT and be especially careful of the corners and edges. When
pressing on the touchscreen, sometimes people can use the tip of their fingers,
or a fingernail. If you don't find the touchscreen responds well to your fingers,
you can use a rounded stylus which will certainly work. Do not press harder and
harder until the screen cracks!
Getting data from the touchscreen is fairly straight forward. Start by creating the
touchscreen object with
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
We're using hardware SPI so the clock, mosi and miso pins are not defined here.
Then you can start the touchscreen with
ts.begin()
Check to make sure this returns a True value, which means the driver was found. If it
wasn't, make sure you have the Feather soldered right and the correct CS pin!
Now you can call
if (! ts.bufferEmpty())
©Adafruit Industries
Page 17 of 30
to check if there's any data in the buffer. The touchscreen driver will store touchpoints
at all times. When you're ready to get the data, just check if there's any data in the
buffer. If there is, you can call
TS_Point p = ts.getPoint();
To get the oldest point from the buffer. TS_Point has .x .y and .z data points. The x and
y points range from 0 to 4095. The STMPE610 does not store any calibration data in it
and it doesn't know about rotation. So if you want to rotate the screen you'll need to
manually rotate the x/y points! The z point is 'pressure' and ranges from 0 to 255, we
don't use it here but you can experiment with it on your own, the harder you press,
the lower the number.
Since data from the STMPE610 comes in 0-4095 but our screen is 320 pixels by 240
pixels, we can use map to convert 0-4095 to 0-320 or 0-240. Something like
p.x = map(p.x, 0, 4095, 0, tft.width());
p.y = map(p.y, 0, 4095, 0, tft.height());
However, the touchscreen is a bit bigger than the screen, so we actually need to
ignore presses beyond the touchscreen itself. We found that these numbers reflected
the true range that overlaps the screen
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000
So we use
p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
instead.
One last point (pun intended!) since the touchscreen driver stores points in a buffer,
you may want to ask the driver "is the touchscreen being pressed RIGHT NOW?" You
can do that with
if (ts.touched())
©Adafruit Industries
Page 18 of 30
Drawing Bitmaps
There is a built-in microSD card slot on the FeatherWing, and we can use that to load
bitmap images! You will need a microSD card formatted FAT16 or FAT32 (they almost
always are by default), and an SD card reader on whatever computer you’re currently
reading this with.
Its really easy to draw bitmaps. Lets start by downloading this image of pretty flowers:
Download these two smaller images as well:
The files should be renamed (if needed) to “purple.bmp”, “parrot.bmp” and “wales.bm
p”, respectively, and copied to the base directory of the microSD card (not inside a
folder).
©Adafruit Industries
Page 19 of 30
(If it’s easier, you can also find these images in the “images” folder within the
Adafruit_ImageReader library folder.)
Insert the microSD card into the socket in the shield. Now select the sketch file→exam
ples→Adafruit_ImageReader→FeatherWingILI9341 and upload this example to your
Feather + Wing. You will see the flowers appear! (Plus parrots…and if you’re using one
of the more powerful Feather boards, a whole lot of dragons.)
The Adafruit_ImageReader library, which is being used here to display .BMP images,
is fully explained in its own page of the Adafruit_GFX guide (https://adafru.it/DpM).
CircuitPython Displayio Quickstart
We'll start with the 2.4" TFT FeatherWing which has an ILI9341 display on it. If you
would like more information on this display, be sure to check out our Adafruit 2.4" TFT
FeatherWing guide (https://adafru.it/vvE).
Parts
To use this display with displayio, you will only need two main parts. First, you will
need the TFT FeatherWing itself.
©Adafruit Industries
Page 20 of 30
TFT FeatherWing - 2.4" 320x240
Touchscreen For All Feathers
A Feather board without ambition is a
Feather board without FeatherWings!
Spice up your Feather project with a
beautiful 2.4" touchscreen display shield
with built in microSD card...
https://www.adafruit.com/product/3315
And second, you will need a Feather such as the Feather M0 Express or the Feather
M4 Express. We recommend the Feather M4 Express because it's much faster and
works better for driving a display.
Adafruit Feather M4 Express - Featuring
ATSAMD51
It's what you've been waiting for, the
Feather M4 Express featuring ATSAMD51.
This Feather is fast like a swift, smart like
an owl, strong like a ox-bird (it's half ox,...
https://www.adafruit.com/product/3857
For this guide, we'll assume you have a Feather M4 Express. The steps should be
about the same for the Feather M0 Express. To start, if you haven't already done so,
follow the assembly instructions for the Feather M4 Express in our Feather M4
Express guide (https://adafru.it/EEm). We'll start by looking at the back of the 2.4" TFT
FeatherWing.
©Adafruit Industries
Page 21 of 30
After that, it's just a matter of inserting the Feather M4 Express into the back of the
TFT FeatherWing.
Required CircuitPython Libraries
To use this display with displayio , there is only one required library.
Adafruit_CircuitPython_ILI9341
https://adafru.it/EGe
©Adafruit Industries
Page 22 of 30
First, make sure you are running the latest version of Adafruit CircuitPython (https://
adafru.it/Amd) for your board.
Next, you'll need to install the necessary libraries to use the hardware--carefully
follow the steps to find and install these libraries from Adafruit's CircuitPython library
bundle (https://adafru.it/zdx). Our introduction guide has a great page on how to
install the library bundle (https://adafru.it/ABU) for both express and non-express
boards.
Remember for non-express boards, you'll need to manually install the necessary
libraries from the bundle:
• adafruit_ili9341
Before continuing make sure your board's lib folder or root filesystem has the adafruit
_ili9341 file copied over.
Code Example Additional Libraries
For the Code Example, you will need an additional library. We decided to make use of
a library so the code didn't get overly complicated.
Adafruit_CircuitPython_Display_Text
https://adafru.it/FiA
Go ahead and install this in the same manner as the driver library by copying the adaf
ruit_display_text folder over to the lib folder on your CircuitPython device.
CircuitPython Code Example
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
This test will initialize the display using displayio and draw a solid green
background, a smaller purple rectangle, and some yellow text. All drawing is done
using native displayio modules.
Pinouts are for the 2.4" TFT FeatherWing or Breakout with a Feather M4 or M0.
"""
import board
import terminalio
import displayio
from adafruit_display_text import label
import adafruit_ili9341
©Adafruit Industries
Page 23 of 30
# Release any resources currently in use for the displays
displayio.release_displays()
spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10
display_bus = displayio.FourWire(
spi, command=tft_dc, chip_select=tft_cs, reset=board.D6
)
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)
# Make the display context
splash = displayio.Group()
display.show(splash)
# Draw a green background
color_bitmap = displayio.Bitmap(320, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00 # Bright Green
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)
# Draw a smaller inner rectangle
inner_bitmap = displayio.Bitmap(280, 200, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0xAA0088 # Purple
inner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=20,
y=20)
splash.append(inner_sprite)
# Draw a label
text_group = displayio.Group(scale=3, x=57, y=120)
text = "Hello World!"
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFF00)
text_group.append(text_area) # Subgroup for text scaling
splash.append(text_group)
while True:
pass
Code Details
Let's take a look at the sections of code one by one. We start by importing the board
so that we can initialize SPI , displayio , terminalio for the font, a label , and
the adafruit_ili9341 driver.
import board
import displayio
import terminalio
from adafruit_display_text import label
import adafruit_ili9341
Next we release any previously used displays. This is important because if the
Feather is reset, the display pins are not automatically released and this makes them
available for use again.
©Adafruit Industries
Page 24 of 30
displayio.release_displays()
Next, we set the SPI object to the board's SPI with the easy shortcut function
board.SPI() . By using this function, it finds the SPI module and initializes using the
default SPI parameters. Next we set the Chip Select and Data/Command pins that will
be used.
spi = board.SPI()
tft_cs = board.D9
tft_dc = board.D10
In the next line, we set the display bus to FourWire which makes use of the SPI bus.
The reset parameter is actually not needed for the FeatherWing, but was added to
make it compatible with the breakout displays. You can either leave it or remove it if
you need access to an additional GPIO pin.
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs,
reset=board.D6)
Finally, we initialize the driver with a width of 320 and a height of 240. If we stopped
at this point and ran the code, we would have a terminal that we could type at and
have the screen update.
display = adafruit_ili9341.ILI9341(display_bus, width=320, height=240)
©Adafruit Industries
Page 25 of 30
Next we create a background splash image. We do this by creating a group that we
can add elements to and adding that group to the display. The display will
automatically handle updating the group.
splash = displayio.Group()
display.show(splash)
Next we create a Bitmap which is like a canvas that we can draw on. In this case we
are creating the Bitmap to be the same size as the screen, but only have one color.
The Bitmaps can currently handle up to 256 different colors. We create a Palette with
one color and set that color to 0x00FF00 which happens to be green. Colors are
Hexadecimal values in the format of RRGGBB. Even though the Bitmaps can only
handle 256 colors at a time, you get to define what those 256 different colors are.
color_bitmap = displayio.Bitmap(320, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x00FF00 # Bright Green
With all those pieces in place, we create a TileGrid by passing the bitmap and palette
and draw it at (0, 0) which represents the display's upper left.
bg_sprite = displayio.TileGrid(color_bitmap,
pixel_shader=color_palette,
x=0, y=0)
splash.append(bg_sprite)
This creates a solid green background which we will draw on top of.
©Adafruit Industries
Page 26 of 30
Next we will create a smaller purple rectangle. The easiest way to do this is the create
a new bitmap that is a little smaller than the full screen with a single color and place it
in a specific location. In this case we will create a bitmap that is 20 pixels smaller on
each side. The screen is 320x240, so we'll want to subtract 40 from each of those
numbers.
We'll also want to place it at the position (20, 20) so that it ends up centered.
inner_bitmap = displayio.Bitmap(280, 200, 1)
inner_palette = displayio.Palette(1)
inner_palette[0] = 0xAA0088 # Purple
inner_sprite = displayio.TileGrid(inner_bitmap,
pixel_shader=inner_palette,
x=20, y=20)
splash.append(inner_sprite)
Since we are adding this after the first rectangle, it's automatically drawn on top.
Here's what it looks like now.
Next let's add a label that says "Hello World!" on top of that. We're going to use the
built-in Terminal Font and scale it up by a factor of three. To scale the label only, we
will make use of a subgroup, which we will then add to the main group.
Labels are centered vertically, so we'll place it at 120 for the Y coordinate, and around
57 pixels make it appear to be centered horizontally, but if you want to change the
text, change this to whatever looks good to you. Let's go with some yellow text, so
we'll pass it a value of 0xFFFF00 .
©Adafruit Industries
Page 27 of 30
text_group = displayio.Group(scale=3, x=57, y=120)
text = "Hello World!"
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFF00)
text_group.append(text_area) # Subgroup for text scaling
splash.append(text_group)
Finally, we place an infinite loop at the end so that the graphics screen remains in
place and isn't replaced by a terminal.
while True:
pass
Using Touch
We won't be covering how to use the touchscreen on the shield with CircuitPython in
this guide, but the library required for enabling resistive touch is the Adafruit_CircuitP
ython_STMPE610 (https://adafru.it/Fsz) library.
Where to go from here
Be sure to check out this excellent guide to CircuitPython Display Support Using
displayio (https://adafru.it/EGh)
Troubleshooting
©Adafruit Industries
Page 28 of 30
Display does not work on initial power but does work
after a reset.
The display driver circuit needs a small amount of time to be ready after initial
power. If your code tries to write to the display too soon, it may not be ready. It will
work on reset since that typically does not cycle power. If you are having this issue,
try adding a small amount of delay before trying to write to the display.
In Arduino, use delay() to add a few milliseconds before calling tft.begin(). Adjust
the amount of delay as needed to see how little you can get away with for your
specific setup.
Downloads
Datasheets & More
• Fritzing object in Adafruit Fritzing Library (https://adafru.it/c7M)
• STMPE610 Touch Controller Datasheet (https://adafru.it/d4k)
• ILI9341 (TFT controller) Datasheet (https://adafru.it/d4l)
• Datasheet for TFT module itself (https://adafru.it/zAj)
• EagleCAD PCB files on GitHub (https://adafru.it/ska)
• 3D Models on GitHub (https://adafru.it/Z1A)
Schematic
©Adafruit Industries
Page 29 of 30
Fabrication Print
©Adafruit Industries
Page 30 of 30