Overview
Bedeck your Feather project with a beautiful Adafruit TFT FeatherWing, 3.5" 480x320 Capacitive Touchscreen. This TFT display is 3.5" diagonal with a bright white-LED backlight and a built-in microSD card socket. You get a massive 480x320 pixels with individual 16-bit color pixel control. It has way more resolution than a black and white 128x64 display, and twice as much as our 2.4" TFT FeatherWing. As a bonus, this display comes with a multi-touch capacitive touchscreen attached to it already, so you can detect up to 5 finger presses anywhere on the screen.
This FeatherWing uses a SPI display and SD card socket, with I2C touchscreen. It works with any and all Feather boards but given the large display it works best with our faster boards like the nRF52, RP2040, ESP32, M0 and M4 (basically anything that is > 32 MHz). It includes a capacitive touchscreen controller controlled over I2C so you only need one additional interrupt 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.
The TFT display is an HX8357D-chipset compatible, we have both Arduino and CircuitPython libraries for it. And the capacitive touch driver is FT5336, with 5-point multi-touch, with both Arduino and CircuitPython libraries as well.
Page last edited March 08, 2024
Text editor powered by tinymce.
Pinouts
The default I2C address for the FT5336 capacitive touch driver is 0x38.
STEMMA QT Connector
- STEMMA QT - This connector, located to the left of the on/off switch, allows you to connect to sensors and breakout boards with STEMMA QT / Qwiic connectors or to other things with various associated accessories.
- SDA/SCL - The I2C pins for the STEMMA QT connector are connected to the default I2C GPIO pins directly next to pin 5.
- 3.3V/GND - The power for the STEMMA QT connector is 3.3V. Ground is the common ground for power and logic.
Default SPI Pins
The TFT (connected to an HX8357 chipset) and microSD card on the FeatherWing are controlled via SPI.
- MOSI - This is the SPI MOSI (Microcontroller Out / Serial In) pin.
- MISO - This is the SPI MISO (Microcontroller In / Serial Out) pin.
- SCK - This is the SPI clock input pin.
TFT Control Pins and Jumpers
- DC - This is the display SPI data/command selector pin. By default, it is connected to pin 10. To change this, cut the jumper. Then, connect the signal pad (closest to the label on the board silk) to one of the available and compatible GPIO pads.
- TCS - This is the TFT SPI chip select pin. By default, is connected to pin 9. To change this, cut the jumper. Then, connect the signal pad (closest to the label on the board silk) to one of the available and compatible GPIO pads.
- LITE - This is the TFT backlight pad, located between the Feather headers and the TFT ribbon cable towards the top of the board. It is not connected to any pins by default. Pull this pin low to turn off the backlight.
microSD Card Slot
- On the back right edge of the FeatherWing is the microSD card slot. You can use any microSD card that supports SPI mode with one CS pin.
SD Card Pins and Jumper
- SCS - This is the SD card chip select pin. By default, it is connected to pin 5. To change this, cut the jumper. Then, connect the signal pad (closest to the label on the board silk) to one of the available and compatible GPIO pads.
- SDDET - This is the card detect pad, located to the left of the microSD card slot. It is not connected to any pins by default. This pin will read low when a card is not inserted.
Touch Screen Interrupt Jumper
- IRQ - This is the touchscreen interrupt pin for the FT5336. By default, it is connected to pin 6. To change this, cut the jumper. Then, connect the signal pad (closest to the label on the board silk) to one of the available and compatible GPIO pads.
Reset Button
- Reset - The reset button, located in the bottom left corner on the FeatherWing, is connected to the reset pin. It is mounted at a right angle so that it is easier to press.
Page last edited March 08, 2024
Text editor powered by tinymce.
CircuitPython
Using the 3.5" 320x480 Color TFT FeatherWing with CircuitPython involves plugging the FeatherWing into to your CircuitPython-compatible Feather microcontroller. Then, you load the code and necessary libraries onto your microcontroller.
This page uses the Feather RP2040 for demonstrating CircuitPython usage. You can use the same concepts to get going with any classic Feather board.
Plug your Feather into the FeatherWing. The Feather USB port will be above the FeatherWing microSD card slot.
CircuitPython Usage
To use with CircuitPython, you need to first install the necessary libraries, and their dependencies, into the lib folder on your CIRCUITPY drive. Then you need to update code.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file.
Connect the microcontroller to your computer via a known-good USB power+data cable. The board shows up as a thumb drive named CIRCUITPY. Copy the entire lib folder and the code.py file to your CIRCUITPY drive.
Your CIRCUITPY/lib folder should contain the following folders and files:
- /adafruit_bus_device
- /adafruit_register
- adafruit_ft5336.mpy
- adafruit_hx8357.mpy
Once you have copied over the necessary folders and files, your CIRCUITPY drive should resemble the following:
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
"""
Touch paint example for HX83570 + FT5336 TFT Breakout
"""
import board
import displayio
import fourwire
from adafruit_hx8357 import HX8357
import adafruit_ft5336
displayio.release_displays()
spi = board.SPI()
# for eyespi bff
# tft_cs = board.TX
# tft_dc = board.RX
# else:
tft_cs = board.D9
tft_dc = board.D10
display_bus = fourwire.FourWire(spi, command=tft_dc, chip_select=tft_cs)
# display is rotated to align x, y with touch screen x, y
display = HX8357(display_bus, width=320, height=480, rotation=90)
i2c = board.I2C() # uses board.SCL and board.SDA
touch = adafruit_ft5336.Adafruit_FT5336(i2c)
pixel_size = 10
palette_width = 45
palette_height = 320 // 8
splash = displayio.Group()
display.root_group = splash
bitmap = displayio.Bitmap(320, 480, 8)
color_palette = displayio.Palette(8)
color_palette[0] = 0x000000
color_palette[1] = 0xFF0000
color_palette[2] = 0xFFFF00
color_palette[3] = 0x00FF00
color_palette[4] = 0x00FFFF
color_palette[5] = 0x0000FF
color_palette[6] = 0xFF00FF
color_palette[7] = 0xFFFFFF
tile_grid = displayio.TileGrid(bitmap, pixel_shader=color_palette)
# tilegrid is flipped to align x, y with touch screen x, y
tile_grid.flip_y = True
tile_grid.flip_x = True
splash.append(tile_grid)
display.root_group = splash
current_color = 7
for i in range(palette_width):
for j in range(palette_height):
bitmap[j + palette_height, i] = 1
bitmap[j + palette_height * 2, i] = 2
bitmap[j + palette_height * 3, i] = 3
bitmap[j + palette_height * 4, i] = 4
bitmap[j + palette_height * 5, i] = 5
bitmap[j + palette_height * 6, i] = 6
bitmap[j + palette_height * 7, i] = 0
while True:
if touch.touched:
try:
for t in touch.points:
x = t[0]
y = t[1]
print(x, y)
if not 0 <= x < display.width or not 0 <= y < display.height:
continue # Skip out of bounds touches
if y < palette_width:
current_color = bitmap[x, y]
else:
for i in range(pixel_size):
for j in range(pixel_size):
x_pixel = x - (pixel_size // 2) + i
y_pixel = y - (pixel_size // 2) + j
if 0 <= x_pixel < display.width and 0 <= y_pixel < display.height:
bitmap[x_pixel, y_pixel] = current_color
except RuntimeError:
pass
Once everything is copied over, on your display, you should the touch paint example begin to run. You can touch the different colors on the side of the TFT and doodle on the screen.
Page last edited March 08, 2024
Text editor powered by tinymce.
Arduino
Using the 3.5" TFT FeatherWing with Arduino involves plugging the FeatherWing to your Arduino-compatible Feather microcontroller, installing the library for your display type and running the provided example code.
This page uses the Feather RP2040 for demonstrating Arduino usage. You can use the same concepts to get going with any Feather board.
Plug your Feather into the FeatherWing. The USB port on the Feather will be pointing towards the microSD card slot.
Library Installation
You can install the Adafruit FT5336 library for Arduino using the Library Manager in the Arduino IDE.
Click the Manage Libraries ... menu item, search for Adafruit FT5336, and select the Adafruit_FT5336 library:
If asked about dependencies, click "Install all".
If the "Dependencies" window does not come up, then you already have the dependencies installed.
/***************************************************
This is our touchscreen painting example for the Adafruit HX8357
with FT5336 captouch breakout
----> http://www.adafruit.com/products/5846
Check out the links above for our tutorials and wiring diagrams
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
****************************************************/
#include <Adafruit_HX8357.h>
#include <Adafruit_FT5336.h>
// The FT5336 uses hardware I2C (SCL/SDA)
Adafruit_FT5336 ctp = Adafruit_FT5336();
#define FT5336_MAXTOUCHES 5
// The display also uses hardware SPI, plus #9 & #10
#define TFT_CS 9
#define TFT_RST -1
#define TFT_DC 10
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC);
// Size of the color selection boxes and the paintbrush size
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
void setup(void) {
Serial.begin(115200);
//while (!Serial) delay(10); // pause the serial port
Serial.println("3.5 inch Cap Touch Paint!");
tft.begin();
if (! ctp.begin(FT53XX_DEFAULT_ADDR, &Wire)) { // pass in 'sensitivity' coefficient and I2C bus
Serial.println("Couldn't start FT5336 touchscreen controller");
while (1) delay(10);
}
Serial.println("Capacitive touchscreen started");
tft.fillScreen(HX8357_BLACK);
// make the color selection boxes
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, HX8357_RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, HX8357_YELLOW);
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, HX8357_GREEN);
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, HX8357_CYAN);
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, HX8357_BLUE);
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, HX8357_MAGENTA);
tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
tft.fillRect(BOXSIZE*7, 0, BOXSIZE, BOXSIZE, HX8357_BLACK);
// select the current color 'red'
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
currentcolor = HX8357_RED;
}
void loop() {
uint8_t touches = ctp.touched();
// Wait for a touch
if (! touches) {
return;
}
// Retrieve the points, up to 5!
TS_Point ps[FT5336_MAXTOUCHES];
ctp.getPoints(ps, FT5336_MAXTOUCHES);
for (int i=0; i<FT5336_MAXTOUCHES; i++) {
// Check if z (pressure) is zero, skip if so
if (ps[i].z == 0) continue;
/*
ps[i].x = map(ps[i].x, 0, 320, 0, 320);
ps[i].y = map(ps[i].y, 0, 480, 0, 480);
*/
// Print out the remapped/rotated coordinates
Serial.print("("); Serial.print(ps[i].x);
Serial.print(", "); Serial.print(ps[i].y);
Serial.print(")\t");
}
Serial.println();
if (ps[0].y < BOXSIZE) {
oldcolor = currentcolor;
if (ps[0].x < BOXSIZE) {
currentcolor = HX8357_RED;
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x < BOXSIZE*2) {
currentcolor = HX8357_YELLOW;
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x < BOXSIZE*3) {
currentcolor = HX8357_GREEN;
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x < BOXSIZE*4) {
currentcolor = HX8357_CYAN;
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x < BOXSIZE*5) {
currentcolor = HX8357_BLUE;
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x <= BOXSIZE*6) {
currentcolor = HX8357_MAGENTA;
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
} else if (ps[0].x <= BOXSIZE*7) {
currentcolor = HX8357_WHITE;
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, HX8357_RED);
} else {
// erase
tft.fillScreen(HX8357_BLACK);
// make the color selection boxes
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, HX8357_RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, HX8357_YELLOW);
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, HX8357_GREEN);
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, HX8357_CYAN);
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, HX8357_BLUE);
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, HX8357_MAGENTA);
tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
}
if (oldcolor != currentcolor) {
if (oldcolor == HX8357_RED)
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, HX8357_RED);
if (oldcolor == HX8357_YELLOW)
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, HX8357_YELLOW);
if (oldcolor == HX8357_GREEN)
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, HX8357_GREEN);
if (oldcolor == HX8357_CYAN)
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, HX8357_CYAN);
if (oldcolor == HX8357_BLUE)
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, HX8357_BLUE);
if (oldcolor == HX8357_MAGENTA)
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, HX8357_MAGENTA);
if (oldcolor == HX8357_WHITE)
tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, HX8357_WHITE);
}
}
for (int i=0; i<FT5336_MAXTOUCHES; i++) {
// Check if z (pressure) is zero, skip if so
if (ps[i].z == 0) continue;
if (((ps[i].y-PENRADIUS) > BOXSIZE) && ((ps[i].y+PENRADIUS) < tft.height())) {
tft.fillCircle(ps[i].x, ps[i].y, PENRADIUS, currentcolor);
}
}
}
Upload the sketch to your board and open up the Serial Monitor (Tools -> Serial Monitor) at 115200 baud. In the Serial Monitor, you should see the values from the touch screen being printed out. If you press with more than one point, you'll see multiple sets of coordinates. The first number is the X coordinate, the second number is the Y coordinate.
On the TFT, you'll be able to doodle with the different colors on the left side of the screen.
Page last edited March 08, 2024
Text editor powered by tinymce.
Downloads
Page last edited March 08, 2024
Text editor powered by tinymce.