Teensy 3.1 vs FT2606 Capacitance Touch Driver (2.8" TFT)

Status
Not open for further replies.

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 ;)
photo 3.jpg

And this is showing the screen running on the Teensy (I made up a custom UNO proto-shield matching the UNO pins).
photo 4.jpg

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:
I got the Breakout Board version of the same capacitive touch screen and did manage to get it to work, however I was struggling a bit with it for a while. I am running a T3.1 with PJRC Audio board. After a little copy paste from various examples I was able to get the system running with the touch screen and graphics and sound. See the example below. I have only tried to access the SD card on the Audio board. It's definitely convenient to have a touch screen, now I need to get it all working smoothly.

To get touch working I used A5 (D19) for SCL and A4 (D18) for SDA, the display is connected with alternate pins for Audio / graphics devices per the webpage here:

http://www.pjrc.com/store/display_ili9341.html

Code:
/***************************************************
 This is a modified example to test the Teensy 3.1 with audioshield and the 
 2.8" TFT capactive touchscreen 
 https://www.adafruit.com/product/2090
 
 Still much to do however this demo will play a wav file and allows
 touch updates during song play (interrupts playback however)
 - Fretless_Kb
 
 
 // Original Text
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  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 <Audio.h>
#include <Wire.h>
#include <SD.h>
#include "SPI.h"
#include "ILI9341_t3.h"
#include <Adafruit_FT6206.h>


// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ctp = Adafruit_FT6206();


// For the Adafruit shield, these are the default.
#define TFT_DC  20 // 9 basic  20 alt for soundcard
#define TFT_CS 21 // 10 basic  21 alt for soundcard

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

// GUItool: begin automatically generated code
AudioPlaySdWav           playWav1;       //xy=154,78
AudioOutputI2S           i2s1;           //xy=334,89
AudioConnection          patchCord1(playWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
// GUItool: end automatically generated code


void setup() 
{
  SPI.setMOSI(7);
  SPI.setSCK(14);

  Serial.begin(115200);
  //while (!Serial) ; // wait for Arduino Serial Monitor

  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(3);

  if (! ctp.begin(40)) 
  {  // pass in 'sensitivity' coefficient
    Serial.println("Couldn't start FT6206 touchscreen controller");
    tft.println("Couldn't start FT6206 touchscreen controller");
    while (1);
  }
  
  tft.println("Touch Screen to Begin ...");
  while ( !ctp.touched() ) 
  {
    delay(10);
  } 
  
  if (!(SD.begin(10))) 
  {
    // stop here, but print a message repetitively
    tft.fillScreen(ILI9341_BLACK);
    tft.setTextColor(ILI9341_RED);
    tft.setTextSize(2);
  
    while (1) 
    {
      tft.println("Unable to access the SD card");
      delay(500);
    }
  }
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(2);

  AudioMemory(5);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
}

void touchView () 
{
  if ( ctp.touched()) 
  {
    // Retrieve a point  
    TS_Point p = ctp.getPoint();      
    // 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);
    tft.fillScreen(ILI9341_BLACK);
    if(p.x<50) p.x = 50;
    if(p.x>180) p.x=180;
    if(p.y>300) p.y=300;
    
    tft.setTextSize(2);
    tft.setTextColor(ILI9341_RED);
    tft.setCursor(180-p.x,300-p.y);
    tft.print("("); tft.print(p.x);
    tft.print(", "); tft.print(p.y);
    tft.println(")");
  }
}

int stepTime = 0;

void playFile(const char *filename) {
  tft.print("Playing file: ");
  tft.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playWav1.play(filename);

  // A brief delay for the library read WAV info
  delay(5);

  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying()) 
  {
    touchView ();
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    float vol = analogRead(15);
    vol = vol / 1024;
    sgtl5000_1.volume(vol);
  }
}


void loop(void) {
  // Wait for a touch
  playFile("SDTEST4.WAV");
  delay(25);

}

I was always double / triple checking my connections. often would have 1 wire out of place as I re-configured and tested with the various graphics displays I have.

I am interested to know if you got yours to work.
 
Hiya, thanks for your reply, and sorry for the delay in mine, holidays / illness and a little failing confidence in these support forums as I never seem to get replies or help for some reason no matter how specific I try to be (poor me) ;)

Anyway, yeah, I can get the screen working, that's no probs, with all the Spi hardware mods etc associated with the _t3 library..

But touch screen, still nothing on the teensy.. So it's specifically a teensy issue since uno / nano etc no probs..

I'm wondering if you ever got yours working with the sd card onboard tft loading bit maps? Coz that's where you'll perhaps see the issue..

I need to be able to use the sdfat library as I am now successfully to load bitmaps (the original adafruit library does not work on the teensy) and I also need to use the capacitance touch.. It seems since the sdfat uses i2c along with the touch, this is where things won't play together..

Unless I'm missing something..

Either gonna lose the screen, or lose the teensy. Since they won't play, and no one else seems to be able to get them working together either...

Very disappointing..

Thanks anyway for your help :)

Cheers

Andy
 
Where did you connect the SCL/SDA wires on the shield? A4/A5 or to the SCL/SDA pins. For A4 and A5 you have to close the two solder jumper.
 
... Wow... That was easy :)

Something about the adafruit support pages did / but didn't make that clear at all since I was sure the default config was A4/A5 off the shield... (None of my uno boards have those 2 pins up the top even labeled as SCL/SDA, so didn't even realise they were used!) learn something new every day, if not, it's been a wasted day!

Well pointed out, and despite having tried other pins in my frustration was chasing my tail with the jumper closed / up closed anyway... Yay. Thank you dude..

I've only briefly tested and looks like the touch isn't actually drawing where I'm touching but looks like it's just cords flipped 90 degrees so that's fine, as long as it can actually "see" the touch data, I can play! :)

Happy new year to all, and happy teensy'ing!

Cheers

Andy
 
Hi Andy
Please note;
The LCD has a 2.8" 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 (digital #8) This allows you to query the controller when you're ready to read touchscreen data, and saves 3 pins...
Read and test ; https://learn.adafruit.com/adafruit-2-8-tft-touch-shield-v2/touchscreen-paint-demo
Good luck !
Mike
 
Status
Not open for further replies.
Back
Top