Resistive touch screen with Analog pins - How does it work ?

I am aware about the subject as two planes of conductive material separated by an inert layer and touching makes contact at that point which is read as a X,Y co-ordinate. In one such shield they are defining one pair X,Y pins as Analog and the next pair X1,Y1 as digital pins. Would like to know how this one works ? Any link to an article will help !

Also in the code below if I want to make the orientation as landscape what changes need to be done ? I tried some but ended up totally confused :frowning:

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>

#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin

// For 0 Rotation ( Portrait mode )
#define TS_MINX 125     //  Right                
#define TS_MAXX 910     //  Left
#define TS_MINY 70      //  Top
#define TS_MAXY 910     //  Bottom

// 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, 330);            // Actually measured . RR_17Aug2020

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

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

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#define BOXSIZE 40
#define PENRADIUS 2
int oldcolor, currentcolor;

void setup(void) {
  Serial.begin(9600);
  Serial.println(F("Paint!"));

  tft.reset();

  uint16_t identifier = tft.readID();

  tft.begin(identifier);
  tft.setRotation(0);
  tft.fillScreen(BLACK);
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); // For 0 Rotation, Top Left is 0,0. Bottom right is 240 x 320
  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);   // x,y,w,h,c
  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.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
  currentcolor = RED;

  pinMode(13, OUTPUT);
}

#define MINPRESSURE 200
#define MAXPRESSURE 1000

void loop()
{
  TSPoint p = ts.getPoint();
  pinMode(XM, OUTPUT);
  pinMode(YP, 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);                // These are the touch co-ordinates
    //Serial.print("\tY = "); Serial.print(p.y);
    //Serial.print("\tPressure = "); Serial.println(p.z);

    if (p.y > (TS_MAXY - 25)) {                               // Corrected and works fine !
      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.x = tft.width()-map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
    p.y = (tft.height() - map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
    //p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);

    //Serial.print("("); Serial.print(p.x);                   // These are the Pixel co-ordinates
    //Serial.print(", "); Serial.print(p.y);
    //Serial.println(")");

    if (p.y < BOXSIZE) {
      oldcolor = currentcolor;                                  // Load the touched colour...

      if (p.x < BOXSIZE) {                                      // Sorround the touched colour with white border
        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 (((p.y - PENRADIUS) > BOXSIZE) && ((p.y + PENRADIUS) < tft.height())) {  // Trace the styus in the chosen colour !
      tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
    }
  }
}

God gave you Wikipedia. It answers most topics.

Apply a voltage across XP, XM pins. This will give a steady voltage gradient in the X direction.
If you touch the screen, you make contact at the x,y coordinate. Read the Analog voltage with the YP pin.

Make YP Digital. Apply voltage across YM, YP. Read Analog with XM pin.

It is wise to take several readings and choose the best one.

David.

david_prentice:
God gave you Wikipedia. It answers most topics.

Apply a voltage across XP, XM pins. This will give a steady voltage gradient in the X direction.
If you touch the screen, you make contact at the x,y coordinate. Read the Analog voltage with the YP pin.

Make YP Digital. Apply voltage across YM, YP. Read Analog with XM pin.

It is wise to take several readings and choose the best one.

David.

Thanks. The clarity with which you made the subject clear in that four lines can never be matched by any Wiki.

Yes most times in forums people are guided to refer to Wikis and Google. Of course one can do that but in general, one is overwhelmed by the responses ....and many times an article of Resistive touch screen may delve more on the material used and so on so forth. However responses in forums tend to be focussed on the use case of these. And of course code can be discussed.

Located a short article on the subject....

Resistive Touch Screen

I don't know if the following code is the right way to turn the display 90 Deg CW to Landscape mode. But it works !!

I just changed the Rotation to 1 ( earlier it was 0) and swapped the tft.height() and tft.width(). It is working :slight_smile:

    //TFT Rotation = 0
    // p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);             // Portrait. Top Left = 0,0
    // p.y = (tft.height()-map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
    
    //TFT Rotation = 1
    int a  = map(p.x, TS_MINX, TS_MAXX, 0, tft.height());            // Landscape. Top Left = 0,0
    int b  = map(p.y, TS_MINY, TS_MAXY, 0, tft.width());
    p.x = b;
    p.y = a;

    Serial.print("("); Serial.print(p.x);                   // These are the Pixel co-ordinates
    Serial.print(", "); Serial.print(p.y);
    Serial.println(")");

I am gobsmacked by the MINX, MAXX style.
Surely it is more intuitive to fetch the Portrait TS_LEFT, TS_RT values from TouchScreen.h library.

You will always map() in a logical way for Portrait.
And if you want PORTRAIT_REV, LANDSCAPE, LANDSCAPE_REV it is obvious which arguments to use in map() when calculating pixel coordinates.

Hey-ho. It is your choice. You might change the logical screen Rotation. The TouchPanel is always going to be fixed.

Note that the map() function is perfectly happy with ADC value for LEFT > RT
Or with mapping 12-bit ADC values.

David.

@David

That was valid point on the MINX definitions. I am developing on Sample code and hence these remain… !

I am right now working on a project which uses three pages of the TFT. The first one is the main page and from there I can go to Page 2 or Page 3. The partially developed code is below …

It was easy to get this done with the Adafruit_GFX Buttons library. But what I find is if I go to Page 2 the Page 1 buttons are still effective ( though not visible ). Like if I press on the location where Button 3 is , it shows up !!

How to remove the references to the pages that are not in view ?

#include <Adafruit_GFX.h>        // Core graphics library
#include <Adafruit_TFTLCD.h>     // Hardware-specific library for 8 bit TFT 
#include <TouchScreen.h>

#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin

// For 0 Rotation ( Portrait mode )
#define TS_MINX 125     //  Right                
#define TS_MAXX 910     //  Left
#define TS_MINY 70      //  Top
#define TS_MAXY 910     //  Bottom

// 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, 330);            // Actually measured . RR_17Aug2020

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

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

#define MINPRESSURE 10
#define MAXPRESSURE 1000

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;


int oldcolor, currentcolor;
Adafruit_GFX_Button mainButton[3];
int pixel_x, pixel_y;

//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

void setup(void) {
  Serial.begin(9600);
  Serial.println(F("Paint!"));

  tft.reset();

  uint16_t identifier = tft.readID();

  tft.begin(identifier);
  tft.setRotation(1);
  tft.fillScreen(BLACK);

  Serial.print( "Width = " );
  Serial.println(tft.width());
  Serial.print( "Height = " );
  Serial.println(tft.height());

  mainButton[0].initButtonUL(&tft,  10, 180, 80, 40, BLACK, YELLOW, BLACK, "PAGE1", 2);
  mainButton[0].drawButton();
  mainButton[1].initButtonUL(&tft,  100, 180, 80, 40, BLACK, YELLOW, BLACK, "PAGE2", 2);
  mainButton[1].drawButton();
  mainButton[2].initButtonUL(&tft,  190, 180, 80, 40, BLACK, YELLOW, BLACK, "PAGE3", 2);
  mainButton[2].drawButton();
}


//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

void loop()
{
  bool touch = getTouchXY(), currState, prevState, currState1, prevState1;  // Get valid Touch Coordinates

  for (byte i = 0; i < 3; i++) {                                            // FInd out which button is pressed or released
    bool pressed = touch && mainButton[i].contains(pixel_x, pixel_y);
    tft.setFont();
    currState = mainButton[i].isPressed();
    prevState = mainButton[i].justPressed() ? 0 : mainButton[i].justReleased() ? 1 : currState;
    mainButton[i].press(pressed);
    if (mainButton[i].justReleased()) {
      mainButton[i].drawButton(false);
    }
    if (mainButton[i].justPressed()) {
      mainButton[i].drawButton(true);
    }
  }

  if (mainButton[0].justPressed()) {                  // Button for Page 2 pressed. Show that page !
    tft.fillScreen(BLUE);
    tft.fillRect(0, 0, 320, 25, YELLOW);
    tft.setTextSize (2);
    tft.setTextColor(BLACK);
    print_at(85, 5, "THIS IS PAGE 2");
  }
  delay(100);
}

//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO

bool getTouchXY() {
  TSPoint p = ts.getPoint();
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
  if (pressed) {
    int a  = map(p.x, TS_MINX, TS_MAXX, 0, tft.height());    // Rotation = 1; Landscape. Top Left = 0,0
    int b  = map(p.y, TS_MINY, TS_MAXY, 0, tft.width());
    pixel_x  = b;
    pixel_y  = a;
    //Serial.print("("); Serial.print(pixel_x);              // These are the Pixel co-ordinates
    //Serial.print(", "); Serial.print(pixel_y);
    //Serial.println(")");
  }
  return pressed;
}


void print_at(int x, int y, const char *msg)
{
  tft.setCursor(x, y);
  tft.print(msg);
}

I suggest that you run the MCUFRIEND_kbv examples. MCUFRIEND_kbv supports many more controllers than Adafruit_TFTLCD

I have posted Button demos to this Forum. e.g. attached to this message

You don't need to use MCUFRIEND_kbv in your project but it is a lot easier to see how the examples work.

David.