Save state of Touch Screen

Dear all,

I have a 4-wire resistive touch screen (yes, one of those Nintendo DS replacement ones) hooked up to my Arduino.

Now I want to control the brightness of a RGB LED with it. My idea was, that I use the y-axis as a brightness value and map it to a PWM pin. Then I could divide the x-axis in three regions R,G and B.

I tink a piture explains it best

Now, when I release my finger or stylus from the touch screen, it obviously jumps back to a zero value which then would cause my LED to switch off.

How can I save the state/value from a touch and further, how can I save three different states?

start of loop
  read finger position x y
  if y > 0
    if finger in red area
      save y coordinate to red variable
    end of if
    else if finger in green area
      save y coordinate to green variable
    end of else
    else if finger in blue area
      save y coordinate to blue variable
    end of else
  end of if
  set LED PWM values based on the 3 colour variables
end of loop

The RGB variables could be a single array with 3 elements if you want.

Bob, that won't work. The red, green, and blue areas are just ranges from 0 to the width of the screen. Since your pseudo code (correctly) reads the finger position on every pass through loop, sometimes it will be zero. Sometimes it will be wherever a finger is touching. Sometimes it will be dropping from a good reading back to 0, after a finger is lifted.

OP: What you need to do is use the X coordinate to select the color and the Y coordinate to define a "save the X coordinate" range. When the Y coordinate is in the "save the X coordinate" range, copy the X coordinate somewhere else. When the Y coordinate is not in the "save the X coordinate" range, don't persist the current X coordinate.

Paul, I see the problem with my idea but will your suggestion work either ?

Since either value may be

dropping from a good reading back to 0, after a finger is lifted.

then all bets are off as to where the finger was when it was touching the screen as no value of Y may be safely regarded as within the "save the X coordinate" range unless I have misunderstood what you meant.

I cannot see a way of leaving the LED at its RGB values returned when the finger last touched the screen without the use of another button which is pressed to record X and Y, and released to hold the last recorded values.

In the meantime I found that it apparently is possible to measure the touch pressure. I am looking into this now.
Then one might be able to trigger an interrupt once the pressure is above a threshold.

I know I could have a button that triggers an interrupt and then set the colour There is a Jeremy Blum tutorial on that, but it would be very neat
to have a touch only solution.

His idea is simple. 1) map the three areas. What are the ranges of red, green and blue. 2) use IF statements to find a "point" within the areas of the three colors.(to make sure where you touch lies within that area of the color). 3) use a timer to look for changes in the Y coordinate, and if the coordinate is not "0,0"(most likely the default value, when not touched) and held for 2 seconds, save the value.

Alt 3) If you don't want to use a timer, then use a regular button. When the button is pressed, it stores that value for that particular color.

The map function should be able to give you zero, when you touch the very bottom of the screen for 2 seconds.

Paul, I see the problem with my idea but will your suggestion work either ?

I think it would, if I were doing it, since I would persist the X coordinate while the finger is still touching the screen, and then ignore the fact that X drops after the finger is lifted.

Although, now I wonder, since y would drop too. One could, though, make the "save the X coordinate" happen at the upper end of the Y scale.

OP: Does the touch screen class have some kind of "is being touched" method that you can use to determine whether the X and Y coordinates even mean anything?

I am not using any touch library as those did not work for me out of the box. I have written my own bit of code. This is not so complicated. The screen has two layers one for x and one for y. You can the energize say X+ and make X- ground and then use either of the Y pins for sensing. Then you energize the Y-plane and sense with a X pin.

If you want to know if a touch is happening you need to do the pressure detection. This is explained here http://arduino.cc/forum/index.php/topic,98328.0.html but I do not have it working yes. Sometimes I get negative values and the values of pressure are strongly correlated to the touch position.

I think HazardsMind is going in the right direction.

If the touch screen always reverts to a given "no-touch" position (call it zero) then it should be possible to record (say) the last three positions continuously. If the first of these is zero then you have just started a touch sequence. If the last one is zero you have just ended a touch sequence so save the second-last position.

...R

Now we know that it is possible to measure touch pressure the whole thing becomes easier.

start of loop
  read finger position x y
  read touch pressure
  if touch pressure less than trigger level
    if x in red area
      save y coordinate to red variable
    end of if
    else if x in green area
      save y coordinate to green variable
    end of else
    else if x in blue area
      save y coordinate to blue variable
    end of else
  end of if
  set LED PWM values based on the 3 colour variables
end of loop

Here, this is what you need for the basic X,Y coordinates.

https://kalshagar.wikispaces.com/Arduino+and+a+Nintendo+DS+touch+screen

if touch pressure less than trigger level

Wouldn't it work better to record the values when the pressure is high enough to be recognized as a touch, and stop recording when the pressure drops off?

thanks fr the link. I have the coordinate reading bit sorted already.

At the moment I am struggling with getting reliable pressure readings.

Once I can detect a touch it is indeed a lot easier because I can write data if the pressure is high enough.

The coordinate reading is very fast, but you are right, it is probably better not to read them at all as long as the pressure is too small.

I'll see how I get one

PaulS:

if touch pressure less than trigger level

Wouldn't it work better to record the values when the pressure is high enough to be recognized as a touch, and stop recording when the pressure drops off?

Either way will work I think as long as loop() executes fast enough. I am sure there was a reason why I suggested the way I did but for the life of me I cannot remember what it was and I have slept since then. This morning your way seems better !

Ok, I finally found some time to do a bit more work on it and i have it done now.

I changed my code to use the TouchScreen library (found on github) after all. The reason it did not work in the first place was my own stupidity - I connected some wires wrong.

Then I added 3 LED for testing and divided the TouchScreen in three regions. Each LED can be changed in brightness by swiping from left to right on the screen at either the top, middle or bottom. This is neat for a RGB LED.

The library calculates the ‘pressure’ on the touch screen. That way it allows you to detect a touch and only write data to the LED when there is a touch in the correct region of the display. That way there is no need to save any data or to use interrupts. This makes the code incredibly simple.

//Notes for myself regading the wires
//connected to the 4-wire TouchScreen
// White and Purple = Y
// Gray and Blue = X

//Example from TouchScreen library
//With some custim LED stuff
#include <stdint.h>
#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 A1   // can be a digital pin
#define XP A0   // can be a digital pin

//PWM pins for the LEDs
int red = 9;
int green = 3;
int yell = 10;
int brightness = 0;
// 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, 200);

void setup(void) {
  Serial.begin(9600);
  pinMode(red,OUTPUT);
  pinMode(green,OUTPUT);
  pinMode(yell,OUTPUT);
}

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

  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!
  if (p.z > 25) {
    Serial.print("X = "); 
    Serial.print(p.x);
    Serial.print("\tY = "); 
    Serial.print(p.y);
    Serial.print("\tPressure = "); 
    Serial.println(p.z);
    //Change colours by swipe in X direction
    //100 and 900 are values found from looking at the Serial output
    //of p.x
    brightness=map(p.x,100,900,0,255);
    brightness=constrain(brightness,0,255);
    //Divide the TouchScreen in 3 regions
    //bottom, middle, top, for three LEDs or RGB LED
    //values found by looking at p.y Serial output
    if(p.y < 350){
      analogWrite(red,brightness);
    }
    else if (p.y > 350 & p.y < 660){
      analogWrite(green,brightness);
    }
    else{
      analogWrite(yell,brightness);
    }
  }

  delay(20);
}

Project parts:
-4 wire resistive touch screen (ebay, search for nintendo DS replacement touch screen) 2.50GBP
-Breakout board for the flat cable (the screen has one of those flat cables and the pin pitch is 0.5mm. Impossible to solder if you do not have the right equipment for it. Further, for small quantities, the single connector is almost as expensive as the board. From proto-pic in the UK, I think adafruit in the US) 2.65GBP
http://proto-pic.co.uk/nintendo-ds-touch-screen-connector-breakout/

  • 3 LEDs or RGB LED with the appropriate resistors