Reading the touch screen and writing to the TFT are both slow processes with the supplied software libraries.
The square buttons can go anywhere on the screen, with 16 bit colors and text overlays in color of your choice. |
The test application helps find the limits of the touch screen for calibrating the library call to get the mapping right. |
Getting the SD Card to work alongside the TFT and Touch Screen
Adafruit provides an example for copying bitmap files to the screen from a uSD card, that doesn't use the touch screen. They also provide an example for a really simple paint program that uses the TFT and the touch screen, but not the uSD. I wanted to be able to use the TFT and the touch screen and record data from the program to the uSD for a log of what happened. I found that really hard to accomplish because I wasn't paying enough attention to the hardware conflicts. In addition to getting the pin directions right, the status of the SPI control register has to be preserved separately for TFT operations and uSD operations. The sketch below is a copy of the Adafruit paint example that does that to record a log file to the uSD. I hope the insight saves you some time.
Testing also shows that you can open multiple files for output simultaneously by following the obvious steps in parallel. (1 SD object, two separate File objects.) Watch out because these three libraries together take a lot of code space, putting you up against the 32K barrier on the UNO.
Testing also shows that you can open multiple files for output simultaneously by following the obvious steps in parallel. (1 SD object, two separate File objects.) Watch out because these three libraries together take a lot of code space, putting you up against the 32K barrier on the UNO.
// Paint example specifically for the TFTLCD Arduino shield.
// If using the breakout board, use the tftpaint.pde sketch instead!
//************************************************************
// Modified by RWS to record data to a log file on the SD card
// Crucial stuff about saving the SPI control register state
// marked with asterisks like these ones....
//************************************************************
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>
#include <SD.h>
#define SD_CS 5 // Card select for shield use
// These are the pins for the shield!
#define YP A1 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 7 // can be a digital pin
#define XP 6 // can be a digital pin
#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
//#define LCD_CS A3 // these defines don't seem to be needed in the sketch
//#define LCD_CD A2 // although they are a hint that the TFTLCD may use those pins
//#define LCD_WR A1
//#define LCD_RD A0
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
Adafruit_TFTLCD tft;
uint8_t spi_save_tft,spi_save_sd;
#define BOXSIZE 40
#define PENRADIUS 4
int oldcolor, currentcolor;
File logfile;
void setup(void) {
Serial.begin(9600);
progmemPrintln(PSTR("Paint!"));
tft.reset();
uint16_t identifier = tft.readID();
if(identifier == 0x9325) {
progmemPrintln(PSTR("Found ILI9325 LCD driver"));
} else if(identifier == 0x9328) {
progmemPrintln(PSTR("Found ILI9328 LCD driver"));
} else if(identifier == 0x7575) {
progmemPrintln(PSTR("Found HX8347G LCD driver"));
} else {
progmemPrint(PSTR("Unknown LCD driver chip: "));
Serial.println(identifier, HEX);
return;
}
tft.begin(identifier);
tft.fillScreen(BLACK);
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
// tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE);
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
currentcolor = RED;
//*******************************************************************
spi_save_tft = SPCR; // save the state of the SPI control register for TFT before SD stuff
//*******************************************************************
progmemPrint(PSTR("Initializing SD card...")); //*****************************************************
if (!SD.begin(SD_CS)) { // SD code from the Adafruit data logger shield example
progmemPrintln(PSTR("failed!")); //*****************************************************
return;
}
progmemPrintln(PSTR("OK!"));
// create a new file
char filename[] = "TSTLOG00.TXT";
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
Serial.println("bad file");
}
else{
Serial.print("Log to: ");
Serial.println(filename);
}
//**********************************************************
spi_save_sd = SPCR; // save the state of the SPI control register after SD stuff
//**********************************************************
pinMode(13, OUTPUT); // maybe this pin 13 stuff has something to do with the SD card on SPI?
// or maybe it's just about blinking
}
#define MINPRESSURE 10
#define MAXPRESSURE 1000
void loop()
{
digitalWrite(13, HIGH);
Point p = ts.getPoint();
digitalWrite(13, LOW);
// if sharing pins, you'll need to fix the directions of the touchscreen pins
// the touchscreen swaps them back and forth between input and output multiple times
pinMode(XP, OUTPUT);
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
pinMode(YM, OUTPUT);
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
/*
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
*/
//********************************************************
SPCR = spi_save_sd; // reset to the SD saved state of the SPI control register
//********************************************************
logfile.print("X = "); logfile.print(p.x);
logfile.print("\tY = "); logfile.print(p.y);
logfile.print("\tPressure = "); logfile.println(p.z);
logfile.flush();
//************************************************************
SPCR = spi_save_tft; // reset to the non-SD saved state of the SPI control register
//************************************************************
if (p.y < (TS_MINY-5)) {
Serial.println("erase");
// press the bottom of the screen to erase
tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
}
// scale from 0->1023 to tft.width
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
/*
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 = RED;
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (p.x < BOXSIZE*2) {
currentcolor = YELLOW;
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (p.x < BOXSIZE*3) {
currentcolor = GREEN;
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (p.x < BOXSIZE*4) {
currentcolor = CYAN;
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (p.x < BOXSIZE*5) {
currentcolor = BLUE;
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (p.x < BOXSIZE*6) {
currentcolor = MAGENTA;
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE);
}
if (oldcolor != currentcolor) {
if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
}
}
if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
}
}
}
// Copy string from flash to serial port
// Source string MUST be inside a PSTR() declaration!
void progmemPrint(const char *str) {
char c;
while(c = pgm_read_byte(str++)) Serial.print(c);
}
// Same as above, with trailing newline
void progmemPrintln(const char *str) {
progmemPrint(str);
Serial.println();
}
Sir,
ReplyDeletei am working on a touch LCD ...it is an arduino compatible touch + sd card lcd ....
when i run it ...it runs fine initially ...but after 4,5 seconds ,...graphics sort of diminish and scatter and it becomes impossible to see anything on it.....do u know where might be the problem ...programming or hardware ??
I had a similar problem along the way, and it had to do with the pinMode not getting reset for the shared pins. I'm not sure of why, but making sure they were reset in my main program (not just in a library function) was essential to fixing the problem. It's right near the top of the loop function in the code above.
Delete