Andology
Member
Teensy 3.1 vs FT6206 Capacitance Touch Driver (2.8" TFT)
Hiya fellow Teensy Fans
I've been battling with my new Adafruit 2.8" TFT with Capacitance Touch.
I've got it working perfectly with the optimised ILI9341 T3 Library which takes full advantage of the Teensy's super fast SPI. Stunning speed difference so thanks so much for the work put in to that guys! (all my projects rely on non-blocking / max speed for animations etc so essential for me!)
However...
Really can't seem to get the capacitance touch screen side of it working. And what's more, there doesnt seem to be anything at all about this combination of teensy and FT6206working together. I've scoured the net (including YouTube), so here I am, asking for help
Anyone know why the Teensy won't play ball with it? I've got the shield version of this display so I've tested it on my UNO with seamless (but slow) success so the touch & display are all working as normal with the UNO..
Here is the default touch test sketch running on the UNO with some love
And this is showing the screen running on the Teensy (I made up a custom UNO proto-shield matching the UNO pins).
Obviously I'm running my own test sketch on the Teensy above just to get the library etc working for the display side of things (which is running great).. Just touch not happy, but here's the standard touch sketch you get for the capacitance version: (Please note, i'm using the optimised display drivers and sdFat libraries, but this sketch should run, but just can't get past the touch initiation part).
When I run it, I get this back through the Serial:
I'm just using standard pinouts and example straight outta the library so we'll assume everything is as it should be in terms of pinouts / connections and the like..
Also, note the use of the SdFat.h library. Took me ages to get that working, standard adafruit load bitmap also doesnt seem to work but after much experimentation, that library seems to work best for dealing with bitmaps on the teensy etc..
Most probably an i2C issue with this touch screen but not sure where to start. Thanks for any guidance or fixes or hints
Cheers
Andy
Hiya fellow Teensy Fans
I've been battling with my new Adafruit 2.8" TFT with Capacitance Touch.
I've got it working perfectly with the optimised ILI9341 T3 Library which takes full advantage of the Teensy's super fast SPI. Stunning speed difference so thanks so much for the work put in to that guys! (all my projects rely on non-blocking / max speed for animations etc so essential for me!)
However...
Really can't seem to get the capacitance touch screen side of it working. And what's more, there doesnt seem to be anything at all about this combination of teensy and FT6206working together. I've scoured the net (including YouTube), so here I am, asking for help
Anyone know why the Teensy won't play ball with it? I've got the shield version of this display so I've tested it on my UNO with seamless (but slow) success so the touch & display are all working as normal with the UNO..
Here is the default touch test sketch running on the UNO with some love
And this is showing the screen running on the Teensy (I made up a custom UNO proto-shield matching the UNO pins).
Obviously I'm running my own test sketch on the Teensy above just to get the library etc working for the display side of things (which is running great).. Just touch not happy, but here's the standard touch sketch you get for the capacitance version: (Please note, i'm using the optimised display drivers and sdFat libraries, but this sketch should run, but just can't get past the touch initiation part).
Code:
/***************************************************
This is our touchscreen painting example for the Adafruit ILI9341
captouch shield
----> http://www.adafruit.com/products/1947
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_GFX.h> // Core graphics library
#include <SPI.h> // this is needed for display
#include <SdFat.h>
#include <ILI9341_t3.h> // Hardware-specific library
#include <Wire.h> // this is needed for FT6206
#include <Adafruit_FT6206.h>
// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ctp = Adafruit_FT6206();
// TFT display and SD card will share the hardware SPI interface.
// Hardware SPI pins are specific to the Arduino board type and
// cannot be remapped to alternate pins. For Arduino Uno,
// Duemilanove, etc., pin 11 = MOSI, pin 12 = MISO, pin 13 = SCK.
#define TFT_DC 9
#define TFT_CS 10
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
#define SD_CS 4
const uint8_t spiSpeed = SPI_HALF_SPEED;
// Serial streams
Sd2Card card;
SdVolume volume;
SdFile root;
// Size of the color selection boxes and the paintbrush size
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
void setup(void) {
delay(2000);
Serial.begin(115200);
tft.begin();
tft.fillScreen(ILI9341_BLACK);
delay(1000);
Serial.print("Initializing SD card...");
if (!card.init(spiSpeed, SD_CS)) {
Serial.println("failed!");
}
Serial.println("OK!");
Serial.print("Initializing Volume...");
if (!volume.init(&card)) {
if (card.errorCode()) {
Serial.println("Can't read the card.");
} else {
Serial.println("Can't find a valid FAT16/FAT32 partition.");
}
}
Serial.println("OK!");
Serial.print("Open Root...");
if (!root.openRoot(&volume)) {
Serial.println("Can't open root directory.");
}
Serial.println("OK!");
tft.setRotation(3);
bmpDraw("andology.bmp", 0, 0);
delay(2000);
tft.fillScreen(ILI9341_BLACK);
if (! ctp.begin(40)) { // pass in 'sensitivity' coefficient
Serial.println("Couldn't start FT6206 touchscreen controller");
while (1);
}
Serial.println("Capacitive touchscreen started");
tft.fillScreen(ILI9341_BLACK);
// make the color selection boxes
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
// select the current color 'red'
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
currentcolor = ILI9341_RED;
}
void loop() {
// Wait for a touch
if (! ctp.touched()) {
return;
}
// Retrieve a point
TS_Point p = ctp.getPoint();
/*
// Print out raw data from screen touch controller
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print(" -> ");
*/
// flip it around to match the screen.
p.x = map(p.x, 0, 240, 240, 0);
p.y = map(p.y, 0, 320, 320, 0);
// Print out the remapped (rotated) coordinates
Serial.print("("); Serial.print(p.x);
Serial.print(", "); Serial.print(p.y);
Serial.println(")");
if (p.y < BOXSIZE) {
oldcolor = currentcolor;
if (p.x < BOXSIZE) {
currentcolor = ILI9341_RED;
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
} else if (p.x < BOXSIZE*2) {
currentcolor = ILI9341_YELLOW;
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
} else if (p.x < BOXSIZE*3) {
currentcolor = ILI9341_GREEN;
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
} else if (p.x < BOXSIZE*4) {
currentcolor = ILI9341_CYAN;
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
} else if (p.x < BOXSIZE*5) {
currentcolor = ILI9341_BLUE;
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
} else if (p.x <= BOXSIZE*6) {
currentcolor = ILI9341_MAGENTA;
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE);
}
if (oldcolor != currentcolor) {
if (oldcolor == ILI9341_RED)
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
if (oldcolor == ILI9341_YELLOW)
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW);
if (oldcolor == ILI9341_GREEN)
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN);
if (oldcolor == ILI9341_CYAN)
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN);
if (oldcolor == ILI9341_BLUE)
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE);
if (oldcolor == ILI9341_MAGENTA)
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA);
}
}
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
}
}
// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates. It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel). Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster. 20 pixels seems a
// good balance.
#define BUFFPIXEL 80
void bmpDraw(char *filename, uint8_t x, uint16_t y) {
SdFile bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
boolean goodBmp = false; // Set to true on valid header parse
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col;
uint8_t r, g, b;
uint32_t pos = 0, startTime = millis();
FatPos_t fatpos;
if((x >= tft.width()) || (y >= tft.height())) return;
Serial.println();
Serial.print(F("Loading image '"));
Serial.print(filename);
Serial.println('\'');
// Open requested file on SD card
if (!bmpFile.open(&root, filename, O_READ)) {
Serial.print(F("File not found"));
return;
}
// Parse BMP header
if(read16(bmpFile) == 0x4D42) { // BMP signature
Serial.print(F("File size: ")); Serial.println(read32(bmpFile));
(void)read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
// Read DIB header
Serial.print(F("Header size: ")); Serial.println(read32(bmpFile));
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
if(read16(bmpFile) == 1) { // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth);
if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
goodBmp = true; // Supported BMP format -- proceed!
Serial.print(F("Image size: "));
Serial.print(bmpWidth);
Serial.print('x');
Serial.println(bmpHeight);
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// If bmpHeight is negative, image is in top-down order.
// This is not canon but has been observed in the wild.
if(bmpHeight < 0) {
bmpHeight = -bmpHeight;
flip = false;
}
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
if((x+w-1) >= tft.width()) w = tft.width() - x;
if((y+h-1) >= tft.height()) h = tft.height() - y;
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x+w-1, y+h-1);
for (row=0; row<h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
bmpFile.getpos(&fatpos); // Need seek?
if(fatpos.position != pos) { // Need seek?
bmpFile.seekSet(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col=0; col<w; col++) { // For each pixel...
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
}
// Convert pixel from BMP to TFT format, push to display
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
tft.pushColor(tft.color565(r,g,b));
} // end pixel
} // end scanline
Serial.print(F("Loaded in "));
Serial.print(millis() - startTime);
Serial.println(" ms");
} // end goodBmp
}
}
bmpFile.close();
if(!goodBmp) Serial.println(F("BMP format not recognized."));
}
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t read16(SdFile &f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
uint32_t read32(SdFile &f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
When I run it, I get this back through the Serial:
Code:
Initializing SD card...OK!
Initializing Volume...OK!
Open Root...OK!
Loading image 'andology.bmp'
File size: 230454
Image Offset: 54
Header size: 40
Bit Depth: 24
Image size: 320x240
Loaded in 623 ms
Couldn't start FT6206 touchscreen controller
I'm just using standard pinouts and example straight outta the library so we'll assume everything is as it should be in terms of pinouts / connections and the like..
Also, note the use of the SdFat.h library. Took me ages to get that working, standard adafruit load bitmap also doesnt seem to work but after much experimentation, that library seems to work best for dealing with bitmaps on the teensy etc..
Most probably an i2C issue with this touch screen but not sure where to start. Thanks for any guidance or fixes or hints
Cheers
Andy
Last edited: