Hello all, i bought a 3,5'' TFT screen a long, long time ago online, but i never got used it. I found a neat project where i need to use my screen however, when i tried to calibrate it, it fails saying that was "unable to read the position of the press...". I've searched through this forum and ran all the exemples getting the following results: `e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction
Testing : (A1, D7) = 24
ID = 0x0099
TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction
MISSING TOUCHSCREEN
ID = 0x0099
Read Special Registers on MCUFRIEND UNO shield
controllers either read as single 16-bit
e.g. the ID is at readReg(0)
or as a sequence of 8-bit values
in special locations (first is dummy)
graphic test:
Serial took 0ms to start
ID = 0x99
`
This is my first true project and thus im very new at this so please don't get too technical (although i know that sometimes it's necessary) but from what i could understand, my screen has the ILI9488 controller however. Im also able to run all codes from the examples except the SD card ones and when i upload the buttons exemple, i can use the button however, far down from the button rectangle. Any idea how can i fix this?
PS: i forgot to mention, but im using and Arduino MEGA
Thank you all!
That makes sense, on a Mega the SPI pins are different than on an UNO and the SD card uses them
UNO | MEGA
MISO 12 | 50
MOSI 11 | 51
SCK 13 | 52
SS 10 | 53
you will need to disconnect those pins on the shield from pins 10 - 13 and connect them to pins 50 - 53
here is a link to someone who had calibration issues before and the calibration program i use.
Hello @Deva_Rishi, thanks for dedicate some of your time to my problem. I get that error when i run the "TouchScreen_Calibr_native under the MCUFRIEND_kbv library. Regarding the SD card exemple, i though it didn't run since i had no SDcard inserted to begin with (and my project doesn't need one).
Hello Deva, running the GLUE code (480x320), i use the following configuration
UTFTGLUE myGLCD(0,A2,A1,A3,A4,A0);
I also tried
`UTFTGLUE myGLCD(0x99,A2,A1,A3,A4,A0);`
which seems to work aswell
Regarding the plus and minus points, i don't know which i should use since i cannot run the calibration and i think that's one of the main reasons that sketch exists, to get those points. Finally, i can't find that commentary you've repplied, i thought it was under the calibration sketch, but i couldn't find it. Could the failed calibration be caused by my controller?
i found only the 'TouchScreen_Calibr_kbv' in my examples, but i am probably running an outdated version of the library.
Those shields are made of leftover old TFT screens usually (unless you get adafruit originals) and the orientation may differ per batch, and also the touchscreen orientation may differ (and differ from the tft screen) and mainly the edges of the TS screen are different per particular screen (not just per batch) that is what the calibration sketch is for, so the TFT screen and the TS screen are matched and pressing the TS on the spot where you do relates to what is printed on the TFT.
Hello again, thanks for the explanation about how those TFT's came to be, so, ignoring the fact that the calibration sketch doesn't work, is it possible to, by trial and error, get calibration's info? IF not, what may be wrong with my calibration? ILI9488 controller, could it be corrupted or something?
I forgot to mention, but looking at the TFT screen and where each pin connect into the arduino, i got this: LCD_RD = A0 LCD_WR = A1 LCD_RS = A2 LCD_CS = A3 LCD_RST = A4
And also, there was one time when i left him alone and he got into the calibration points, but that never happened again.
I noticed, right now that, when i press that ribbon cable, the code works. I cannot see any damage whatsoever, what could it be?
It is possible, basically you will be looking for the edge of the TS and match that to the TFT. This will provide you with the TS orientation in relation to the TFT. As stated before i use a sketch that let's you swipe to the edges and then store these values in EEPROM so you can read them later when you upload a different sketch.
Most important is that you get these pins correctly
const uint8_t YP = A1; // must be an analog pin, use "An" notation!
const uint8_t XM = A2; // must be an analog pin, use "An" notation!
const uint8_t YM = 7; // can be a digital pin
const uint8_t XP = 6; // can be a digital pin
since these pins need to be switched back to OUTPUT after a TS.getPoint() or the TFT screen will crash.
poor quality.
also in the ts constructor there is a 5th value which is actually a resistance you should measure between (pff i hardly remember it says somewhere in one of the examples) 2 points and is screen specific, and usually somewhere between 300 & 500 Ohms. you measure this when the shield not connected to the Arduino.
ts = TouchScreen(XP, YP, XM, YM, 455);
It's not all the important, but it does make the TS work better.
Hello Deva, Do you think the screen will work just fine or should i try to put a small piece of cotton to help with the ribbon contact?
Also, i know that the nature of this topic is solely related to a error/"malfunction", but i have a code in which i have to adapt a code to be used with an TFT, maybe you could give me some hints on what should i look/learn in order to get the code working. The code i have is to be ran with an ESP8266 and a XPT2046 screen and i plan to use a MEGA and the screen we've been talking about. Were's the sketch i want to adapt
Since i don't know much about coding, i've been looking around and trying different things and i came to this:
#include <TouchScreen.h>
MCUFRIEND_kbv tft(ILI9488, A3, A2, A1, A0, A4);
#define CS=A3
#define RS=A2
#define WR=A1
#define RD=A0
#define RST=A4
const uint8_t YP = A1; // must be an analog pin, use "An" notation!
const uint8_t XM = A2; // must be an analog pin, use "An" notation!
const uint8_t YM = 7; // can be a digital pin
const uint8_t XP = 6;
TouchScreen ts = ts(pinXP, pinYP, pinXM, pinYM, 300) // still have to measure the resistance and i still need to add the limit (x,y) points
But i still don't know what does the following line does nor how to adapt it:
That line declares the object 'tft' of the screen type you have, including some of the pins that have been defined.
That declares the Touchscreen. You must understand that the screen you have actually consists of 2 parts, the TFT to which you write date to make it visible, and the Touchscreen that reads where and how much pressure is applied to a point. Again the first 4 parameters are pin numbers, and the fifth is the amount of resistance between XM & XP that you need to measure with a multimeter. Most of the screens will work with inaccurate values already, it is the least important of the parameters.
Just a simple question before we continue,
can you upload my calibration sketch ?
i will post it here again.
/* TFT Touchscreen Calibrateter
*/
#include <EEPROM.h> // for storage of the settings
#include <Adafruit_GFX.h> // Core graphics library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft; // hard-wired for UNO shields anyway.
#include <TouchScreen.h>
#if defined(__SAM3X8E__)
#undef __FlashStringHelper::F(string_literal)
#define F(string_literal) string_literal
#endif
// most mcufriend shields use these pins and Portrait mode:
const uint8_t YP = A1; // must be an analog pin, use "An" notation!
const uint8_t XM = A2; // must be an analog pin, use "An" notation!
const uint8_t YM = 7; // can be a digital pin
const uint8_t XP = 6; // can be a digital pin
uint8_t SwapXY = 1; // depends on the TFT shield
uint16_t TS_LEFT = 930;
uint16_t TS_RT = 175;
uint16_t TS_TOP = 175; // this is actually the usb end at the start of the program
uint16_t TS_BOT = 920;
volatile uint16_t TFT_X_RANGE = 240; // making these variables volatile solves the issue that when changing
volatile uint16_t TFT_Y_RANGE = 320; // their value (or even keeping it the same but writing to them)
// caused an incorrect memory write with black area's on screen.
// 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, 455);
TSPoint tp;
#define MINPRESSURE 5
#define MAXPRESSURE 1000
#define RELEASECYCLES 200
#define EEPROM_OFFSET 448 // set this to a matching value in the program
// depending on the calibrated values, do not use
// the low Eeprom adddresses since the graphics library
// appears to be using them.
#define SWAP(a, b) {uint16_t tmp = a; a = b; b = tmp;}
uint16_t identifier;
uint8_t orientation = 0; //Portrait
// 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
void setup() {
tft.begin(9600);
tft.reset();
identifier = tft.readID();
tft.begin(identifier);
tft.setRotation(orientation); // we use orientation here to set the TFT rotation
// TS_Rotation(orientation);
ts = TouchScreen(XP, YP, XM, YM, 455); // call the constructor
while (!TitleScreen()) Change_TFTXY_Settings();
CalibrationScreen();
}
void loop() {
}
void CalibrationScreen() {
tft.fillScreen(BLUE);
tft.setTextSize(2);
tft.setTextColor(BLACK);
const char * title = "TFT Calibrater"; // header text
tft.setCursor((TFT_X_RANGE/2) - strlen(title)*6,20);
tft.print(title);
tft.setCursor((TFT_X_RANGE/2) - 54,40);
tft.print(String(TFT_X_RANGE)+" X "+String(TFT_Y_RANGE));
tft.fillRect(TFT_X_RANGE/4,TFT_Y_RANGE/4,TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);
tft.setTextSize(1);
const char * order = "Press the red rectangle";
tft.setCursor((TFT_X_RANGE/2) - strlen(order)*3,TFT_Y_RANGE-50);
tft.print(order);
tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,RED);
WaitReleaseReadPress(true);
tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,YELLOW);
while (!ConfirmRelease());
tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,RED);
uint16_t minx=500,miny=500,maxx=500,maxy=500;
uint8_t minxq=4,minyq=4,maxxq=4,maxyq=4,i=0;
tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,BLUE);
tft.fillRect(0, 0, TFT_X_RANGE, TFT_Y_RANGE/4, BLUE);
tft.fillRect(0, (TFT_Y_RANGE/4)*3 ,TFT_X_RANGE, TFT_Y_RANGE/4, BLUE);
tft.fillRect((TFT_X_RANGE/8),(TFT_Y_RANGE/8),(TFT_X_RANGE/4)*3,(TFT_Y_RANGE/4)*3,RED);
EdgeLookText();
WaitReleaseReadPress(true);
tft.fillScreen(BLUE);
tft.fillRect(TFT_X_RANGE/4,TFT_Y_RANGE/4,TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);
DrawArrow(0);
FillQuad(i,CYAN);
while (i<4) {
tp = ts.getPoint();
ResetPins();
if (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) continue;
tft.setTextColor(YELLOW,BLUE);
tft.setTextSize(2);
tft.setCursor((TFT_X_RANGE/4)+20,(TFT_Y_RANGE/4)*(3-(i/2)*3)+20);
tft.print("tp.x=" + String(tp.x));
tft.setCursor((TFT_X_RANGE/4)+20,(TFT_Y_RANGE/4)*(3-(i/2)*3)+50);
tft.print("tp.y=" + String(tp.y));
tft.setTextSize(1);
if (tp.x>maxx) {
maxx=tp.x;
maxxq=i;
tft.setCursor((TFT_X_RANGE/4)*3+10,40);
tft.print("MaxX="+String(maxx));
}
if (tp.x<minx) {
minx=tp.x;
minxq=i;
tft.setCursor(10,40);
tft.print("MinX="+String(minx));
}
if (tp.y>maxy) {
maxy=tp.y;
maxyq=i;
tft.setCursor((TFT_X_RANGE/4)*3+10,(TFT_Y_RANGE/4)*3+40);
tft.print("MaxY="+String(maxy));
}
if (tp.y<miny) {
miny=tp.y;
minyq=i;
tft.setCursor(10,(TFT_Y_RANGE/4)*3+40);
tft.print("MinY="+String(miny));
}
if (tp.x > 450 && tp.x < 570 && tp.y > 450 && tp.y < 570) { // exit
FillQuad(i,BLUE);
i++;
tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,YELLOW);
while (!ConfirmRelease());
tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);
DrawArrow(i);
FillQuad(i,CYAN);
}
}
tft.fillScreen(YELLOW);
tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,BLUE);
tft.setTextColor(BLACK,YELLOW);
tft.setTextSize(2);
SetCursorInQuad(minxq,0);
tft.print("MinX");
SetCursorInQuad(minxq,2);
tft.print(String(minx));
SetCursorInQuad(maxxq,0);
tft.print("MaxX");
SetCursorInQuad(maxxq,2);
tft.print(String(maxx));
SetCursorInQuad(minyq,0);
tft.print("MinY");
SetCursorInQuad(minyq,2);
tft.print(String(miny));
SetCursorInQuad(maxyq,0);
tft.print("MaxY");
SetCursorInQuad(maxyq,2);
tft.print(String(maxy));
EepromSaveScreen();
WaitReleaseReadPress(true);
StoreInVar(minxq,minx-3);
StoreInVar(maxxq,maxx+3);
StoreInVar(minyq,miny-3);
StoreInVar(maxyq,maxy+3);
StoreValues();
ReadValues();
PrintValues();
}
void StoreInVar(uint8_t side,uint16_t value) {
switch(side) {
case 0:
TS_TOP=value;
break;
case 1:
TS_RT=value;
break;
case 2:
TS_BOT=value;
break;
case 3:
TS_LEFT=value;
break;
}
}
void EepromSaveScreen() {
tft.setTextColor(YELLOW,BLUE);
tft.setTextSize(1);
const char * line1 = "The Values found";
const char * line2 = "Will be stored in";
const char * line3 = "The Eeprom as 16";
const char * line4 = "bit U-integers";
const char * line5 = "Press to continue";
tft.setCursor((TFT_X_RANGE/2) - strlen(line1)*3,((TFT_Y_RANGE/2)-24));
tft.print(line1);
tft.setCursor((TFT_X_RANGE/2) - strlen(line2)*3,((TFT_Y_RANGE/2)-12));
tft.print(line2);
tft.setCursor((TFT_X_RANGE/2) - strlen(line3)*3,((TFT_Y_RANGE/2)));
tft.print(line3);
tft.setCursor((TFT_X_RANGE/2) - strlen(line4)*3,((TFT_Y_RANGE/2)+12));
tft.print(line4);
tft.setCursor((TFT_X_RANGE/2) - strlen(line5)*3,((TFT_Y_RANGE/2)+30));
tft.print(line5);
}
void StoreValues() {
Write16bitEeprom(EEPROM_OFFSET,TFT_X_RANGE);
Write16bitEeprom(EEPROM_OFFSET+2,TFT_Y_RANGE);
Write16bitEeprom(EEPROM_OFFSET+4,TS_TOP);
Write16bitEeprom(EEPROM_OFFSET+6,TS_RT);
Write16bitEeprom(EEPROM_OFFSET+8,TS_BOT);
Write16bitEeprom(EEPROM_OFFSET+10,TS_LEFT);
}
void Write16bitEeprom(uint16_t location, uint16_t uinteg) {
EEPROM.write(location,lowByte(uinteg));
EEPROM.write(location+1,highByte(uinteg));
}
void ReadValues() { //copy the following 2 functions into your program
TFT_X_RANGE=Read16bitEeprom(EEPROM_OFFSET);
TFT_Y_RANGE=Read16bitEeprom(EEPROM_OFFSET+2);
TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}
uint16_t Read16bitEeprom(uint16_t location) {
return( ((uint16_t) EEPROM.read(location+1)<<8) | (uint16_t) EEPROM.read(location));
}
void PrintValues() {
tft.fillScreen(GREEN);
tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,WHITE);
tft.setTextColor(BLACK);
tft.setTextSize(2);
SetCursorInQuad(0,1);
tft.print(String(TS_TOP));
SetCursorInQuad(1,1);
tft.print(String(TS_RT));
SetCursorInQuad(2,1);
tft.print(String(TS_BOT));
SetCursorInQuad(3,1);
tft.print(String(TS_LEFT));
tft.setCursor(TFT_X_RANGE/2-15,TFT_Y_RANGE/2-24);
tft.print(String(TFT_X_RANGE));
tft.setCursor(TFT_X_RANGE/2-3,TFT_Y_RANGE/2-6);
tft.print("X");
tft.setCursor(TFT_X_RANGE/2-15,TFT_Y_RANGE/2+12);
tft.print(String(TFT_Y_RANGE));
}
void SetCursorInQuad(uint8_t quad, uint8_t line) {
switch(quad) {
case 0:
tft.setCursor((TFT_X_RANGE/8)*3+line*7,20+line*15);
break;
case 1:
tft.setCursor((TFT_X_RANGE/4)*3+5+line*7,(TFT_Y_RANGE/8)*3+20+line*15);
break;
case 2:
tft.setCursor((TFT_X_RANGE/8)*3+line*7,(TFT_Y_RANGE/4)*3+20+line*15);
break;
case 3:
tft.setCursor(5+line*7,(TFT_Y_RANGE/8)*3+20+line*15);
break;
}
return;
}
void FillQuad(uint8_t quad,uint16_t color) {
switch (quad) {
case 0:
tft.fillRect(TFT_X_RANGE/4,0,TFT_X_RANGE/2,TFT_Y_RANGE/4,color);
break;
case 1:
tft.fillRect((TFT_X_RANGE/4)*3,TFT_Y_RANGE/4,TFT_X_RANGE/4,TFT_Y_RANGE/2,color);
break;
case 2:
tft.fillRect(TFT_X_RANGE/4,(TFT_Y_RANGE/4)*3,TFT_X_RANGE/2,TFT_Y_RANGE/4,color);
break;
case 3:
tft.fillRect(0,TFT_Y_RANGE/4,TFT_X_RANGE/4,TFT_Y_RANGE/2,color);
}
}
void DrawArrow(uint8_t direct) {
if (direct>3) return;
if (direct%2) { // horizontal
for (uint8_t i=0; i<10; i++) {
if ((i) && (i<9)) tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i, BLACK);
if (direct/2) { // to left
tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
TFT_X_RANGE/2, TFT_Y_RANGE/2-5+i-(TFT_Y_RANGE/16)*2,BLACK);
tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
TFT_X_RANGE/2, TFT_Y_RANGE/2-5+i+(TFT_Y_RANGE/16)*2,BLACK);
}
else { // to right
tft.drawLine(TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
TFT_X_RANGE/2, TFT_Y_RANGE/2-5+i-(TFT_Y_RANGE/16)*2,BLACK);
tft.drawLine(TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
TFT_X_RANGE/2, TFT_Y_RANGE/2-5+i+(TFT_Y_RANGE/16)*2,BLACK);
}
}
}
else { // vertical
for (uint8_t i=0; i<10; i++) {
if ((i) && (i<9)) tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3,
TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3, BLACK);
if (!(direct/2)) { // to Bottom
tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3,
TFT_X_RANGE/2-5+i-(TFT_X_RANGE/16)*2, TFT_Y_RANGE/2, BLACK);
tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3,
TFT_X_RANGE/2-5+i+(TFT_X_RANGE/16)*2, TFT_Y_RANGE/2, BLACK);
}
else { // to Top
tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3,
TFT_X_RANGE/2-5+i-(TFT_X_RANGE/16)*2, TFT_Y_RANGE/2, BLACK);
tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3,
TFT_X_RANGE/2-5+i+(TFT_X_RANGE/16)*2, TFT_Y_RANGE/2, BLACK);
}
}
}
}
void EdgeLookText() {
tft.setTextColor(BLACK,RED);
tft.setTextSize(1);
const char * line1 = "Look for the edge's";
const char * line2 = "extreme value in the";
const char * line3 = "lightblue area, using";
const char * line4 = "a toothpick, and when";
const char * line5 = "done press the center";
const char * line6 = "of this red square for";
const char * line7 = "the next edge.";
const char * line8 = "Press to continue";
tft.setCursor((TFT_X_RANGE/2) - strlen(line1)*3,((TFT_Y_RANGE/2)-48));
tft.print(line1);
tft.setCursor((TFT_X_RANGE/2) - strlen(line2)*3,((TFT_Y_RANGE/2)-36));
tft.print(line2);
tft.setCursor((TFT_X_RANGE/2) - strlen(line3)*3,((TFT_Y_RANGE/2)-24));
tft.print(line3);
tft.setCursor((TFT_X_RANGE/2) - strlen(line4)*3,((TFT_Y_RANGE/2)-12));
tft.print(line4);
tft.setCursor((TFT_X_RANGE/2) - strlen(line5)*3,((TFT_Y_RANGE/2)));
tft.print(line5);
tft.setCursor((TFT_X_RANGE/2) - strlen(line6)*3,((TFT_Y_RANGE/2)+12));
tft.print(line6);
tft.setCursor((TFT_X_RANGE/2) - strlen(line7)*3,((TFT_Y_RANGE/2)+24));
tft.print(line7);
tft.setCursor((TFT_X_RANGE/2) - strlen(line8)*3,((TFT_Y_RANGE/2)+48));
tft.print(line8);
}
bool TitleScreen() {
tft.fillScreen(WHITE);
tft.setTextSize(2);
tft.setTextColor(BLACK);
const char * title = "TFT Calibrater";
tft.setCursor((TFT_X_RANGE/2) - strlen(title)*6,20);
tft.print(title);
delay(1000);
tft.setTextSize(1);
const char * story1 = "Your screen should be";
const char * story2 = "in Portait mode, where";
const char * story3 = "the USB-end is the top.";
const char * story4 = "And this text should be";
const char * story5 = "centered, left to right,";
const char * story6 = "and top to bottom, with";
const char * story7 = "a frame around it.";
const char * story8 = "If so, press the screen,";
const char * story9 = "if not, press and hold";
const char * story10 = "for 3 seconds";
tft.setCursor((TFT_X_RANGE/2) - strlen(story1)*3,((TFT_Y_RANGE/2)-54));
tft.print(story1);
tft.setCursor((TFT_X_RANGE/2) - strlen(story2)*3,((TFT_Y_RANGE/2)-42));
tft.print(story2);
tft.setCursor((TFT_X_RANGE/2) - strlen(story3)*3,((TFT_Y_RANGE/2)-30));
tft.print(story3);
tft.setCursor((TFT_X_RANGE/2) - strlen(story4)*3,((TFT_Y_RANGE/2)-18));
tft.print(story4);
tft.setCursor((TFT_X_RANGE/2) - strlen(story5)*3,((TFT_Y_RANGE/2)-6));
tft.print(story5);
tft.setCursor((TFT_X_RANGE/2) - strlen(story6)*3,((TFT_Y_RANGE/2)+6));
tft.print(story6);
tft.setCursor((TFT_X_RANGE/2) - strlen(story7)*3,((TFT_Y_RANGE/2)+18));
tft.print(story7);
tft.setCursor((TFT_X_RANGE/2) - strlen(story8)*3,((TFT_Y_RANGE/2)+30));
tft.print(story8);
tft.setCursor((TFT_X_RANGE/2) - strlen(story9)*3,((TFT_Y_RANGE/2)+42));
tft.print(story9);
tft.setCursor((TFT_X_RANGE/2) - strlen(story10)*3,((TFT_Y_RANGE/2)+54));
tft.print(story10);
tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,BLACK);
WaitReleaseReadPress(true);
uint32_t moment=millis();
while (!ConfirmRelease()) if ((millis()-moment)>3000) return false;
return true;
}
void Change_TFTXY_Settings() {
tft.fillScreen(RED);
delay(3000);
}
bool ConfirmRelease() {
uint8_t prs=0;
while (prs<RELEASECYCLES) {
tp = ts.getPoint();
ResetPins();
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) return false ;
delay(1);
prs++;
}
return true;
}
void WaitReleaseReadPress(bool waitrelease) {
if (waitrelease) {
while (!ConfirmRelease());
}
while (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) {
tp = ts.getPoint();
ResetPins();
}
delay (100);
}
void ResetPins(){
pinMode(XM, OUTPUT); // reset the pins after use.
pinMode(YP, OUTPUT);
pinMode(XP, OUTPUT);
pinMode(YM, OUTPUT);
}
Now could you also remove the shield from the MEGA, turn it over and take a picture of the bottom, where hopefully there will be some silk-print of the pinout for your particular shield ?
Regarding what you wrote about "my"code, i still need it to read carefully since i never programmed with an Arduino + C (i had python in my Bsc degree and im currently using learning how to model with it).
Well great, that means that the declarations for the TFT i used, match the ones for your screen, and that goes for the TS as well.
Now to get the correct 5th value for the TS declaration (455 in the calibration sketch) measure the resistance between the XM & XP pins of the TS, that is pin 7 & A2. I'll come back to this later, gotta go to work now.
that sounds like a lot, thoiugh on the 1 shield i still have unused in my box, it also had 614 Ohms (though i didn't have to press it all. Just to confirm the pins are marked LCD_RS & LCD_D7
anyway, that means that the declaration for the touchscreen would be
Now the we have the calibration values, and they are actually stored in EEPROM as well, and you can read them from it within the sketch that you want to create to use the TFT-TS.
Still it might be better to run the calibration sketch one more time with that resistance value.
Regardless, you now have the edges of the Touchscreen and you can relate these to the edges of the TFT , which are ranging from 0 - 240 & 0 - 320. You can now use the map() function to convert the readings from the ts point to what you have printed on screen, so you can display a button and see if it is being pressed.
a few notes on the code.
the ConfirmRelease() is a function that deals with the small dropouts of the TS results, basically it checks 200 times to make sure that there is no press. Some shields may work with a smaller amount of cycles. I use my shield to drag faders across the screen, so any incorrect release of the screen will cause issues, as it will regardless.
every time you call
tp = ts.getPoint();
you will need to switch the pins back to output mode, i do that using
void ResetPins(){
pinMode(XM, OUTPUT); // reset the pins after use.
pinMode(YP, OUTPUT);
pinMode(XP, OUTPUT);
pinMode(YM, OUTPUT);
}
these 2 functions read the values back from the EEPROM, although you can also manually copy them to your own sketch
void ReadValues() { //copy the following 2 functions into your program
TFT_X_RANGE=Read16bitEeprom(EEPROM_OFFSET);
TFT_Y_RANGE=Read16bitEeprom(EEPROM_OFFSET+2);
TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}
uint16_t Read16bitEeprom(uint16_t location) {
return( ((uint16_t) EEPROM.read(location+1)<<8) | (uint16_t) EEPROM.read(location));
}
Oh yeah is that the correct orientation for the screen you have in mind ? or do you want to change that ?
Hello Deva, thanks for taking some of your time for helping me. I have a lot to digest, thus give me some time to learn what those lines do so i can adapt them to "my" code.
Thanks!
Yes i do, since that is the TFT X & Y range , either 320 x 240 or 240 x 320 or for bigger size screens 320 x 480 etc.
It declares the 'tft' object that you use to write to the tft screen with.
All the calls to tft.setTextSize(2); and any other calls to functions depends on it.
Does python not use any object oriented programming ?
Hello Deva thanks for your time, my rodeo with python is more related to find roots or fuctions aproximations using several methods (Newton, Runge-Kutta, Bisec, trapezoidal, etc...) which envolves quite "easy" codes, but indeed python has OOP (i've only scretch this surface by using some classes). Python at geology is more like a tool to help us analizing field data however, there is some colleges that use python on a more "hardcore" level but im more into geochemestry rather than tectonics, hence the Geiger.
I will rectify the code tomorow as soon as i have time.
Yeah good. I mean the main thing to understand is that create a working tft-touch sketch, you create 2 objects, one for the tft and one for the ts.
you use the tft object to draw on the screen and you use the ts object to read if and where there is pressure applied to the screen.
unfortunately the X & Y resolutions of these 2 parts do not match, so whatever values you get from the ts, need to be converted to the values that relate to the tft.
if the tft Y range runs between 0 - 320 and the corresponding ts range is 1023 - 195 and coming in as an x coordinate, you will need to map the result using the map() function.
so it would be something like
Ypoint = map(TSX, 1023, 195, 0, 320);
and when i say something like that, i mean exactly that.
It all really depends on the orientation of the tft screen,, how you want it and on the orientation of the TS.
Of course this is not really a beginners project due to the nature of these screens (more like intermediate) and there are some anomalies with the library. The best thing you can do to make sure you understand what you are doing is to create a sketch yourself, that reads a touch and draws a smal object (dop or circle or square) where you have read that touch on the screen. Then you know you have done the conversion correctly.
Hello Deva, you said that the X/Y resolutions don't match, would they match if the screen was a square (it's obvious in terms of lenghts but don't know in terms of resolution). I pretend to use the screen in a portrait/vertical orientation. I've googled the function map() and i found it depends on 5 parameters, value, Fromlow, Fromhigh, Tolow, Tohigh, but i can't understand where you got those values from and you use that particular function to correct the screen true (x,y) coordenates with the ones you get by touching, correct? And that function corresponds to the value of TFT_X/Y_Range, right?
Also, do i need to run the void comands you've wrote a few repplies ago inside the void loop or can i leave it "outside"?