Bodmer / TFT_Touch

Arduino touch screen library for XPT2046
31 stars 13 forks source link

Some lighter touches cause error, you need to use pressure measurement #3

Closed rtek1000 closed 5 years ago

rtek1000 commented 5 years ago

Hi,

Some lighter touches cause error, you need to use pressure measurement too.

XPT2046 pressure

Source: https://www.buydisplay.com/download/ic/XPT2046.pdf

The Z coordinate represents the amount of pressure applied to the screen.

Source: https://github.com/PaulStoffregen/XPT2046_Touchscreen

rtek1000 commented 5 years ago

A great library for using resistive touch without controller is this, it serves as a basis for comparison:

https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/libraries/Touch-Screen-Library_STM/TouchScreen_STM.cpp


uint16_t TouchScreen::pressure(void) {
  // Set X+ to ground
  pinMode(_xp, OUTPUT);
  digitalWrite(_xp, LOW);

  // Set Y- to VCC
  pinMode(_ym, OUTPUT);
  digitalWrite(_ym, HIGH); 

  // Hi-Z X- and Y+
  digitalWrite(_xm, LOW);
  pinMode(_xm, INPUT);
  digitalWrite(_yp, LOW);
  pinMode(_yp, INPUT);

  int z1 = analogRead(_xm); 
  int z2 = analogRead(_yp);

  if (_rxplate != 0) {
    // now read the x 
    float rtouch;
    rtouch = z2;
    rtouch /= z1;
    rtouch -= 1;
    rtouch *= readTouchX();
    rtouch *= _rxplate;
#if !defined (__STM32F1__)
     rtouch /= 1024;
#else
     rtouch /= 4095;
#endif

    return rtouch;
  } else {
#if !defined (__STM32F1__)
    return (1023-(z2-z1));
#else
    return (4095-(z2-z1));
#endif
  }
}

Thank you.

rtek1000 commented 5 years ago

Example of use of pressure measurement:

https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/libraries/Touch-Screen-Library_STM/examples/touchscreendemoshield/touchscreendemoshield.ino

// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// This demo code returns raw readings, public domain

#include <stdint.h>
#include <TouchScreen_STM.h>

// These are the pins for the shield!
#define YP 8  // must be an analog pin
#define XM 9  // must be an analog pin
#define YM 10   // can be a digital pin
#define XP 11   // can be a digital pin

#define MINPRESSURE 10
#define MAXPRESSURE 1000

// 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);

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  // a point object holds x y and z coordinates
  TSPoint p = ts.getPoint();

  // 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);
  }
}
rtek1000 commented 5 years ago

Hi,

I've adapted a code based on other libraries, if anyone wants to test it, it's attached.

Tested on 7-inch display with SSD1963 + XPT2064, log taken in the modified TFT_Touch_Raw.ino example:

(Now we have pressure ;) )

Raw x, y, z, status = 2909, 1912, 236, pressed Raw x, y, z, status = 0, 4095, 65535, not pressed

TFT_Touch.zip

Thank you.

rtek1000 commented 5 years ago

Hi,

If someone has a 7-inch screen with SSD1963 + XPT2046, try using this code below:

(This code should work better than the example provided with the display because it should not draw points in a distant place)

/* FILE:    TFT_Touch_Example1
   DATE:    10/06/14
   VERSION: 0.1
   ORIGINAL AUTHOR:  Andrew Davies

  This is an example of how to use the TFT_Touch library. It does not display
  anything on the screen!

  Open up the Serial Monitor Window from the IDE and set to 38400 baud to see the
  information from screen contacts

  By using a stylus at the screen extremes or touch zone limits this sketch can be
  used to check tha calibration values.

  IMPORTANT: The 2.4" screen orientation used for calibration is with the SD Card slot on the left!

  The library provides the ability to read the current status of the touch screen.
  It does not provide any graphics drawing functions for controlling the TFT screen itself
  it is intended for providing touch screen support to any graphics sketches and libraries.
  However the library will work standalone as this example sketch will demonstrate.

  The example will read the current state of the touch screen and output it to the serial
  port as raw X and Y coordinates.

  No information will be displayed on the TFT screen itself whilst this example is running.

  You may copy, alter and reuse this code in any way you like, but please leave
  reference to HobbyComponents.com in your comments if you redistribute this code.
  This software may not be used directly for the purpose of selling products that
  directly compete with Hobby Components Ltd's own range of products.

  THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER
  EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE.
  HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES,
  INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY
  REASON WHATSOEVER.

  Adapted by Rowboteer 13/5/15
*/

// These are the pins used to interface between the 2046 touch controller and Arduino Mega
#define DOUT 3  /* Data out pin (T_DO) of touch screen */
#define DIN  4  /* Data in pin (T_DIN) of touch screen */
#define DCS  5  /* Chip select pin (T_CS) of touch screen */
#define DCLK 6  /* Clock pin (T_CLK) of touch screen */
//URTouch  myTouch(/* tclk */ 6,/* tcs */ 5,/* din */ 4,/* dout */ 3,/* irq */ 2);  //byte tclk, byte tcs, byte din, byte dout, byte irq

// These are the default min and maximum values, set to 0 and 4095 to test the screen
#define HMIN 0
#define HMAX 4095
#define VMIN 0
#define VMAX 4095
#define XYSWAP 0 // 0 or 1

// This is the screen size for the raw to coordinate transformation
// width and height specified for landscape orientation
#define HRES 800 /* Default screen resulution for X axis */
#define VRES 480 /* Default screen resulution for Y axis */

#include <TFT_Touch.h> // https://github.com/Bodmer/TFT_Touch

/* Create an instance of the touch screen library */
TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT);

#include <UTFT.h>

UTFT myGLCD(SSD1963_800480, 38, 39, 40, 41); //(byte model, int RS, int WR, int CS, int RST, int SER)

extern uint8_t BigFont[];

//word colorlist[] = {VGA_WHITE, VGA_BLACK, VGA_RED, VGA_BLUE, VGA_GREEN, VGA_FUCHSIA, VGA_YELLOW, VGA_AQUA};

unsigned int X_Raw;
unsigned int Y_Raw;
int Z_Raw;

#define MaxPressure 300
#define MinPressure 10

bool isPressed = false;

unsigned int X_Rel;
unsigned int Y_Rel;

int X_MIN = 80;
int Y_MIN = 265;
int X_MAX = 3975;
int Y_MAX = 3975;

void setup()
{
  Serial.begin(115200);
  touch.setCal(HMIN, HMAX, VMIN, VMAX, HRES, VRES, XYSWAP); // Raw xmin, xmax, ymin, ymax, width, height
  touch.setRotation(0);

  myGLCD.InitLCD(1);
  myGLCD.clrScr();
  myGLCD.setFont(BigFont);

  myGLCD.setColor(VGA_WHITE);
  myGLCD.drawLine(30, 0, 30, 60);
  myGLCD.drawLine(0, 30, 60, 30);

  myGLCD.drawLine(myGLCD.getDisplayXSize() - 31, 0, myGLCD.getDisplayXSize() - 31, 60);
  myGLCD.drawLine(myGLCD.getDisplayXSize() - 1, 30, myGLCD.getDisplayXSize() - 61, 30);

  myGLCD.drawLine(myGLCD.getDisplayXSize() - 31, myGLCD.getDisplayYSize() - 1, myGLCD.getDisplayXSize() - 31, myGLCD.getDisplayYSize() - 61);
  myGLCD.drawLine(myGLCD.getDisplayXSize() - 1, myGLCD.getDisplayYSize() - 31, myGLCD.getDisplayXSize() - 61, myGLCD.getDisplayYSize() - 31);

  myGLCD.drawLine(0, myGLCD.getDisplayYSize() - 31, 60, myGLCD.getDisplayYSize() - 31);
  myGLCD.drawLine(30, myGLCD.getDisplayYSize() - 1, 30, myGLCD.getDisplayYSize() - 61);

  myGLCD.drawLine((myGLCD.getDisplayXSize() / 2) - 1, (myGLCD.getDisplayYSize() / 2) + 29, (myGLCD.getDisplayXSize() / 2) - 1, (myGLCD.getDisplayYSize() / 2) - 31);
  myGLCD.drawLine((myGLCD.getDisplayXSize() / 2) + 29, (myGLCD.getDisplayYSize() / 2) - 1, (myGLCD.getDisplayXSize() / 2) - 31, (myGLCD.getDisplayYSize() / 2) - 1);
}

/* Main program */
void loop()
{
  /* Check if the touch screen is currently pressed*/
  // Raw and coordinate values are stored within library at this instant
  // for later retrieval by GetRaw and GetCoord functions.
  // This avoids getting duff values returned
  isPressed = touch.Pressed(); //isTouched();

  //if (isTouched()) // Note this function updates coordinates stored within library variables
  //{
  /* Read the current X and Y axis as raw co-ordinates at the last touch time*/
  // The values returned were captured when Pressed() was called!

  X_Raw = touch.RawX();
  Y_Raw = touch.RawY();
  Z_Raw = touch.RawZ();

  //    map(value, fromLow, fromHigh, toLow, toHigh)
  X_Rel = map(X_Raw, X_MIN, X_MAX, 0, HRES);
  Y_Rel = map(Y_Raw, Y_MIN, Y_MAX, 0, VRES);

  if ((Z_Raw < MaxPressure) && (Z_Raw > MinPressure)) {
    myGLCD.setColor(VGA_WHITE);
    myGLCD.drawPixel(X_Rel, Y_Rel);
  }

  /* Output the results to the serial port */
  Serial.print("Raw x, y, z, Pressed = ");
  Serial.print(X_Raw);
  Serial.print(",\t");
  Serial.print(Y_Raw);
  Serial.print(",\t");
  Serial.print(Z_Raw);
  Serial.print(",\t");
  if (isPressed) {
    Serial.print("Is Pressed");
  } else {
    Serial.print("Is not Pressed");
  }

  Serial.print("; Rel x, y = ");
  Serial.print(X_Rel);
  Serial.print(",\t");
  Serial.println(Y_Rel);

  delay(10);
  //}
  //delay(10);
}

7-7-0-polegada-Display-TFT-LCD-800-480-do-Painel-de-Toque-M-dulo-xpt2046

Arduino DUE test

IMG_20190426_114107337_1 1