4-wire resistive touchscreen

I know someone has figured this out already, but I can't find them.

I'm trying to interface a 4-wire resistive touchscreen to the Arduino. A previous post said something like "just put each wire on an analog, one high one low read the other two, then reverse."

This sounds good, but it wouldn't work because the "read" will float if you don't tie it high or low with a high-impedance resistor (say, 100k).

And besides that, it still doesn't work. I've tried a number of things, but I can't get a read on the H and the V. I can hook it up with 5 on top, 0 at bottom, left or right floating and reading the other side to get the V (x) value, or I can hook up the 5 to the left, 0 to the right, and read top or bottom to get the H (y) value. But if I try to make the Arduino switch back and forth, I get nothing.

I figured out, I think, that I can tie bottom and left to ground with a resistor and a diode, so that when there is 5v on top or right it will (via the diode) go to ground and when there isn't (a read) the resistor will tie the opposite-of-read side down to ground until a press happens. See picture. (that I can't link to because it's my first post. It's at s245.photobucket.com , then albums/gg65/jermitts , then the file name is ats.jpg .)

But this doesn't work either. And I'm not sure why. The idea is, Top and Left are tied to analog 0 and 1. 0 is set to output, 1 to input, 0 high and read on 1. This should return a value between about 0 and 20 (no touch - resistor holds it near zero) or 20-990 for an actual touch. Then, I should be able to switch 0 to input, 1 to output, 1 high and read on 0. This should return a value between 0-20 for no touch, or 20-990 for an actual touch.

I'm using a display program I put together based on someone else's posting regarding reading a value from analog 0 and sending it over serial to a Processing sketch to show the value on the screen. My version (below) gets 6 values, one from each of the 6 analog inputs. I just modified the Arduino end of the program to do the analog input/output swap and read. The first code snippet is from the Arduino to read the touch screen, the Processing code that runs on a PC to show the data from Analog 0-5 won't fit in this message so I'm posting it next.

Any insight appreciated.

Jeremy

// Arduino code for swapping H and V to get an X and Y read:
#define H 0
#define V 1

void setup() {
 //   Serial.begin(115200); 
  Serial.begin(2400); 
}

void loop() {
  int x;
  int y;

  pinMode(H+14,OUTPUT);
  pinMode(V+14,INPUT);
  analogWrite(H, HIGH);
  x = analogRead(V);

  pinMode(H+14,INPUT);
  pinMode(V+14,OUTPUT);
  analogWrite(V, HIGH);
  y = analogRead(H);
  
  Serial.print( "A");
  Serial.print( x );   
  Serial.print( "B");
  Serial.print( y );
  Serial.print( "C");
  Serial.print( 512 );
  Serial.print( "D");
  Serial.print( 512 );          
  Serial.print( "E");
  Serial.print( 0 );
  Serial.print( "F");
  Serial.print( 0 );
  }

Thanks anyone,

Jeremy

the picture is here.

The processing code for the PC display of all six analog inputs is here:

(the original arduino code is at the bottom, commented out.)

import processing.serial.*;

Serial port;  // Create object from Serial class
int valA;
int valB;
int valC;
int valD;
int valE;
int valF;
// this should have been some kind of 2-diminsional array, I guess, but it works.
int[] valuesA;
int[] valuesB;
int[] valuesC;
int[] valuesD;
int[] valuesE;
int[] valuesF;

PFont fontA;
PFont fontB;

void setup() 
{
  // make sure you have these fonts made for Processing. Use Tools...Create Font.
  // "fontA" is a 48 pt font of some sort. It's what we use to show the "now" value.
  fontA = loadFont("CourierNewPSMT-48.vlw");
  
  // "fontB" is a 14 pt font of some sort. It's what we use to show the min and max values.
  fontB = loadFont("CourierNewPSMT-14.vlw"); 
  
  // I wouldn't change the size if I were you. There are some functions that don't use 
  // the actual sizes to figure out where to put things. Sorry about that.
  size(550, 600);
  
  // Open the port that the board is connected to and use the same speed
  // anything faster than 38.4k seems faster than the ADC on the Arduino can keep up with.
  // So, if you want it to be smooth, keep it at or below 38400. 28800 doesn't work at all,
  // I do not know why. If you turn on smooth() you need to drop the rate to 19.2k or lower.
  // You will probably have to adjust Serial.list()[1] to get your serial port.
  port = new Serial(this, Serial.list()[1], 2400);
  
  // These are 6 arrays for the 6 analog input channels.
  // I'm sure it could have just as well been a 2d array, but I'm not that familiar
  // with Processing yet and this was the easy way out.
  valuesA = new int[width-150];
  valuesB = new int[width-150];
  valuesC = new int[width-150];
  valuesD = new int[width-150];
  valuesE = new int[width-150];
  valuesF = new int[width-150];
  // the -150 gives us room on the side for our text values.
  
  // this turns on anti-aliasing. max bps is about 19.2k.
  // uncomment out the next line to turn it on. Personally, I think it's better left off.
  //smooth();
}

int getY(int val) {
  // I added -40 to this line to keep the lines from overlapping, to 
  // keep the values within their gray boxes.
  return (int)(val / 1023.0f * (height-40)) - 1;
}

void draw()
{ 
  String decoder = "";
  while (port.available() >= 3) 
  {
      // read serial until we get to an "A". 
      decoder = port.readStringUntil(65);
  }
  // delay(250);
  // sanity check. make sure the string we got from the Arduino has all the values inside.
  if ((decoder.indexOf("B")>=1) & (decoder.indexOf("C")>=1) & (decoder.indexOf("D")>=1) & (decoder.indexOf("E")>=1) & (decoder.indexOf("F")>=1))
  {
    // decoder string doesn't contain an A at the beginning. it's at the end.
    valA=int(decoder.substring(0,decoder.indexOf("B")));
    //println("A" + str(valA));
    valB=int(decoder.substring(decoder.indexOf("B")+1,decoder.indexOf("C")));
    //println("B" + str(valB));
    valC=int(decoder.substring(decoder.indexOf("C")+1,decoder.indexOf("D")));
    //println("C" + str(valC));
    valD=int(decoder.substring(decoder.indexOf("D")+1,decoder.indexOf("E")));
    //println("D" + str(valD));
    valE=int(decoder.substring(decoder.indexOf("E")+1,decoder.indexOf("F")));
    //println("E" + str(valE));
    valF=int(decoder.substring(decoder.indexOf("F")+1,decoder.indexOf("A")));
    //println("F" + str(valF));
  }
  
  //shift the new values into the array, move everything else over by one
  for (int i=0; i<width-151; i++) {
    valuesA[i] = valuesA[i+1];
    valuesB[i] = valuesB[i+1];
    valuesC[i] = valuesC[i+1];
    valuesD[i] = valuesD[i+1];
    valuesE[i] = valuesE[i+1];
    valuesF[i] = valuesF[i+1];                  
  }

// -151 because the array is 151 less than the width. remember we
// saved room on the side of the screen for the actual text values.
  valuesA[width-151] = valA;
  valuesB[width-151] = valB;
  valuesC[width-151] = valC;
  valuesD[width-151] = valD;
  valuesE[width-151] = valE;
  valuesF[width-151] = valF;
  
  background(0);
  
  textFont(fontA); 
  
  // I'm sure these c/should have been determined using height math, but I don't have the time really.
  // Draw out the now values with the big font.
  text(valA + 1, (width-140), 108-5); 
  text(valB + 1, (width-140), 206-5);
  text(valC + 1, (width-140), 304-5);
  text(valD + 1, (width-140), 402-5); 
  text(valE + 1, (width-140), 500-5);
  text(valF + 1, (width-140), 598-5);
    
  textFont(fontB); 
  // Draw out the min and max values with the small font.
  // the h value (30,128,266,etc) is a function of height,
  // but I didn't bother to actually do the math. 
  // I guess it's (98*n)+30 where n is 0,1,2,3,4,5, but I don't know
  // exactly how height (600) relates to 98... ((h/6)-2??)
  drawdata("0", width-90,  30, valuesA);
  drawdata("1", width-90, 128, valuesB);
  drawdata("2", width-90, 226, valuesC);
  drawdata("3", width-90, 324, valuesD);
  drawdata("4", width-90, 422, valuesE);
  drawdata("5", width-90, 520, valuesF);
  
  for (int x=150; x<width-1; x++) {
    // next line adjusts the color of the stroke depending on the x value. (fades out the end of the line)
    check(x,255,0,0);

    // next line draws the line needed to get this value in the array to the next value in the array.
    // the offsets (6+ in the next line) were used to get the values where I wanted them without
    // having to actually do real spacial math. There's a hack in getY that offsets a little, too.
    line((width)-x,   6+((height/6)*0)+((height-1-getY(valuesA[x-150]))/6), (width)-1-x, 6+((height/6)*0)+((height-1-getY(valuesA[x-149]))/6));
    check(x,0,255,0);
    line((width)-x,   4+((height/6)*1)+((height-1-getY(valuesB[x-150]))/6), (width)-1-x, 4+((height/6)*1)+((height-1-getY(valuesB[x-149]))/6));
    check(x,0,0,255);
    line((width)-x,   2+((height/6)*2)+((height-1-getY(valuesC[x-150]))/6), (width)-1-x, 2+((height/6)*2)+((height-1-getY(valuesC[x-149]))/6));
    check(x,255,255,0);
    line((width)-x,   0+((height/6)*3)+((height-1-getY(valuesD[x-150]))/6), (width)-1-x, 0+((height/6)*3)+((height-1-getY(valuesD[x-149]))/6));
    check(x,0,255,255);
    line((width)-x,   -2+((height/6)*4)+((height-1-getY(valuesE[x-150]))/6), (width)-1-x, -2+((height/6)*4)+((height-1-getY(valuesE[x-149]))/6));
    check(x,255,0,255);
    line((width)-x,   -4+((height/6)*5)+((height-1-getY(valuesF[x-150]))/6), (width)-1-x, -4+((height/6)*5)+((height-1-getY(valuesF[x-149]))/6));
  }
  
  // draw the boxes in gray. 
    stroke(170,170,170);
    
  // these 5 lines divide the 6 inputs
    line(0,108,width-1,108);
    line(0,206,width-1,206);
    line(0,304,width-1,304);
    line(0,402,width-1,402);
    line(0,500,width-1,500);
 
  // these four lines make up the outer box
    line(      0,        0, width-1,        0);  // along the top
    line(width-1,        0, width-1, height-1);  // down the right
    line(width-1, height-1,       0, height-1);  // along the bottom
    line(      0, height-1,       0,        0);  // up the left
}

void drawdata(String pin, int w, int h, int[] values)
{
  text("pin: " + pin, w, h);
  text("min: " + str(min(values) + 1), w, h + 14); 
  text("max: " + str(max(values) + 1), w, h + 28);
}

void check(int xx, int rr, int gg, int bb)
{
  // floating point operations in Processing are expensive.
  // only do the math for the float (fading out effect) if
  // we have to. You can change 170 to 160 if you want it to
  // fade faster, but be sure to change the other 170 to 160
  // and the 20 to 10. 
  // (20 is the difference between 170 and 150)
  if (xx<=170)
  {
    float kick = (parseFloat(170-xx)/20)*255;
    // invert kick so the brighter parts are on the left side instead of the right.
    stroke(rr,gg,bb,255-kick);
  } 
  else
  {
    stroke(rr,gg,bb);
  }
}

/*
This is the Arduino Code:

#define ANALOGA_IN 0
#define ANALOGB_IN 1
#define ANALOGC_IN 2
#define ANALOGD_IN 3
#define ANALOGE_IN 4
#define ANALOGF_IN 5

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

void loop() {
  int val[5];
  
  val[0] = analogRead(ANALOGA_IN);
  val[1] = analogRead(ANALOGB_IN);
  val[2] = analogRead(ANALOGC_IN);
  val[3] = analogRead(ANALOGD_IN);
  val[4] = analogRead(ANALOGE_IN);
  val[5] = analogRead(ANALOGF_IN);
  
  Serial.print( "A" );   
  Serial.print( val[0] );   
  Serial.print( "B" );
  Serial.print( val[1] );
  Serial.print( "C" );
  Serial.print( val[2] );
  Serial.print( "D" );
  Serial.print( val[3] );          
  Serial.print( "E" );
  Serial.print( val[4] );
  Serial.print( "F" );
  Serial.print( val[5] ); 
}

*/

This sounds good, but it wouldn't work because the "read" will float if you don't tie it high or low with a high-impedance resistor (say, 100k).

No it would not float because it is connected to the resistive pad that is connected to the + and -.

When there is no touch, there is no connection between top-bottom and left or right. So top=5 bottom=0 means left and right are floating.

There's about 330 ohms between top and bottom, or left and right, but infinity between top to left or top to right or bottom to left or bottom to right, until a press actually happens. Then it's just a voltage divider. (I have three 17" screens to test with, so I state these as facts....) :slight_smile:

EDIT: If you put top to 5 and bottom to 0 and left to 0 and read right, you get a double resistive divider on right-- between 0 and 2.5 volts instead of between 0 and 5.

thanks- I didn't know about the settling time... and there is good stuff in there about averaging and discarding and dealing with noise.