t r o n i x s t u f f

fun and learning with electronics

Tutorial: Arduino and the DS touch screen

Use inexpensive touch-screens with Arduino in chapter twenty-three of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe.  The first chapter is here, the complete series is detailed here.

[Updated 19/01/2013]

Today we are going to spend some time with a touch screen very similar to the ones found in a Nintendo DS gaming unit. In doing so, we can take advantage of a more interesting and somewhat futuristic way of gathering user input. Please note that in order to use the screen without going completely insane, you will need the matching breakout board, as shown in the following image:

The flimsy flexible PCB runner is inserted into the plastic socket on the breakout board – be careful not to crease the PCB nor damage it as it can be rather easy to do so. (The screen can be easy to break as well…) However don’t let that put you off. You will most likely want to solder in some header pins for breadboard use, or sockets to insert wires. For this article it is being used with pins for a breadboard.

Before we start to use the screen, let’s have a quick investigation into how they actually work. Instead of me trying to paraphrase something else, there is a very good explanation in the manufacturer’s data sheet. So please read the data sheet then return. Theoretically we can consider the X and Y axes to be two potentiometers (variable resistors) that can be read with the analogRead() function. So all we need to do is use two analog inputs, one to read the X-axis value and one for the Y-axis value.

However, as always, life isn’t that simple. Although there are only four wires to the screen, the wires’ purpose alters depending on whether we are measuring the X- or Y-axis. Which sounds complex but is not. Using the following example, we can see how it all works.

Example 23.1

In this example, we will read the X- and Y-axis values returned from the touch screen and display them on an LCD module. (Or you could easily send the values to the serial monitor window instead). From a hardware perspective, you will need:

Connection of the touch screen to the Arduino board is simple, Arduino analog (yes, analog - more on this later) pins A0 to Y1, A1 to X2, A2 to Y2 and A3 to X1 – as below:

Mounting the rest for demonstration purposes is also a simple job. Hopefully by now you have a test LCD module for easy mounting :)

I have mounted  the touch screen onto the breadboard with some spare header pins, they hold it in nicely for testing purposes. Also notice that the touch screen has been flipped over, the sensitive side is now facing up. Furthermore, don’t forget to remove the protective plastic coating from the screen before use.

From a software (sketch) perspective we have to do three things – read the X-axis value, the Y-axis value, then display them on the LCD. As we (should) know from the data sheet, to read the X-axis value, we need to set X1 as 5V, X2 as 0V (that is, GND) and read the value from Y2. As described above, we use the analog pins to do this. (You can use analog pins as input/output lines in a similar method to digital pins – more information here. Pin numbering continues from 13, so analog 0 is considered to be pin 14, and so on). In our sketch (below) we have created a function to do this and then return the X-axis value.

The Y-axis reading is generated in the same method, and is quite self-explanatory. The delay in each function is necessary to allow time for the analog I/O pins to adjust to their new roles as inputs or outputs or analog to digital converters. Here is our sketch: (download)

/*  Example 23.1 - Arduino and touch screen
http://tronixstuff.com/tutorials > Chapter 23
CC by-sa-nc */
#include <LiquidCrystal.h> // we need this library for the LCD commands
LiquidCrystal lcd(12, 11, 5, 4, 2, 3); // your pins may vary
int x,y = 0;
void setup()
{
lcd.begin(20,4); // need to specify how many columns and rows are in the LCD unit
lcd.clear();
}
int readX() // returns the value of the touch screen's X-axis
{
int xr=0;
pinMode(14, INPUT);   // A0
pinMode(15, OUTPUT);    // A1
pinMode(16, INPUT);   // A2
pinMode(17, OUTPUT);   // A3
digitalWrite(15, LOW); // set A1 to GND
digitalWrite(17, HIGH);  // set A3 as 5V
delay(5); // short delay is required to give the analog pins time to adjust to their new roles
xr=analogRead(0); //  return xr;
}
int readY() // returns the value of the touch screen's Y-axis
{
int yr=0;
pinMode(14, OUTPUT);   // A0
pinMode(15, INPUT);    // A1
pinMode(16, OUTPUT);   // A2
pinMode(17, INPUT);   // A3
digitalWrite(14, LOW); // set A0 to GND
digitalWrite(16, HIGH);  // set A2 as 5V
delay(5); // short delay is required to give the analog pins time to adjust to their new roles
yr=analogRead(1); //
return yr;
}
void loop()
{
lcd.setCursor(0,0);
lcd.print(" x = ");
x=readX();
lcd.print(x, DEC);
y=readY();
lcd.setCursor(0,1);
lcd.print(" y = ");
lcd.print(y, DEC);
delay (200);
}

Next, let’s have a look at this example in action. The numbers on the LCD may be not what you expected…

The accuracy of the screen is not all that great – however first take into account the price of the hardware before being too critical. Note that there are values returned even when the screen is not being pressed, we could perhaps call these “idle values”. Later on you will learn tell your sketch to ignore these values if waiting for user input, as they will note that nothing has been pressed. Furthermore, the extremities of the screen will return odd values, so remember to take this into account when designing bezels or mounting hardware for your screen.

Each touch screen will have different values for each X and Y position, and that is why most consumer hardware with touch screens has calibration functions to improve accuracy. We can now use the X and Y values in sketches to determine which part of the screen is being touched, and act on that touch.

In order to program our sketches to understand which part of the screen is being touched, it will help to create a “map” of the possible values available. You can determine the values using the sketch from example 23.1, then use the returned values as a reference for designing the layout of your touch interface. For example, the following is a map of my touch screen:

Example 23.2

For the next example, I would like to have four “zones” on my touch screen, to use as virtual buttons for various things. The first thing to do is draw a numerical “map” of my touch screen, in order to know the minimum and maximum values for both axes for each zone on the screen:

At this point in the article I must admit to breaking the screen. Upon receiving the new one I remeasured the X and Y points for this example and followed the  process for defining the numerical boundaries for each zone is completed by finding average mid-points along the axes and allowing some tolerance for zone boundaries.

Now that the values are known, it is a simple matter of using mathematical comparison and Boolean operators (such as >, <, &&, etc)  in a sketch to determine which zone a touch falls into, and to act accordingly. So for this example, we will monitor the screen and display on the LCD screen which area has been pressed. The hardware is identical to example 23.1, and our touch screen map will be the one above. So now we just have to create the sketch.

After reading the values of the touch screen and storing them into variables x and y, a long if…then…else if loop occurs to determine the location of the touch. Upon determining the zone, the sketch calls a function to display the zone type on the LCD. Or if the screen is returning the idle values, the display is cleared. So have a look for yourself with the example sketch: (download)

/*
Example 23.2 - Arduino and touch screen - four zone demonstration
http://tronixstuff.com/tutorials > Chapter 23 CC by-sa-nc
*/
#include <LiquidCrystal.h> // we need this library for the LCD commands
LiquidCrystal lcd(12, 11, 5, 4, 2, 3); // your pins may vary
int x,y = 0;
int d = 500; // used for display delay
void setup()
{
lcd.begin(20,4); // need to specify how many columns and rows are in the LCD unit
lcd.clear();
}
int readX() // returns the value of the touch screen's X-axis
{
int xr=0;
pinMode(14, INPUT);   // A0
pinMode(15, OUTPUT);    // A1
pinMode(16, INPUT);   // A2
pinMode(17, OUTPUT);   // A3
digitalWrite(15, LOW); // set A1 to GND
digitalWrite(17, HIGH);  // set A3 as 5V
delay(5); // short delay is required to give the analog pins time to adjust to their new roles
xr=analogRead(0); //  return xr;
}
int readY() // returns the value of the touch screen's Y-axis
{
int yr=0;
pinMode(14, OUTPUT);   // A0
pinMode(15, INPUT);    // A1
pinMode(16, OUTPUT);   // A2
pinMode(17, INPUT);   // A3
digitalWrite(14, LOW); // set A0 to GND
digitalWrite(16, HIGH);  // set A2 as 5V
delay(5); // short delay is required to give the analog pins time to adjust to their new roles
yr=analogRead(1); //  return yr;
}
// the next four functions just display a zone label on the LCD
void displayA()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("AAAAAAAAAA");
lcd.setCursor(0,1);
lcd.print("AAAAAAAAAA");
delay(d);
}
void displayB()
{
lcd.clear();
lcd.setCursor(10,0);
lcd.print("BBBBBBBBBB");
lcd.setCursor(10,1);
lcd.print("BBBBBBBBBB");
delay(d);
}
void displayC()
{
lcd.clear();
lcd.setCursor(0,2);
lcd.print("CCCCCCCCCC");
lcd.setCursor(0,3);
lcd.print("CCCCCCCCCC");
delay(d);
}
void displayD()
{
lcd.clear();
lcd.setCursor(10,2);
lcd.print("DDDDDDDDDD");
lcd.setCursor(10,3);
lcd.print("DDDDDDDDDD");
delay(d);
}
void loop()
{
// get values from touch screen
x=readX();
y=readY();
// now determine where the touch was located on the screen
if (y>510 && x>520 && x<1000 && y <1000)
{
displayA();
} else
if (y>510 && x<510)
{
displayB();
} else
if (y<500 && x>520)
{
displayC();
} else
if (y<500 && x<510)
{
displayD();
} else
if (x>1000 && y>1000)
{
lcd.clear();
}
}

And see it in operation:

So there you have it, I hope you enjoyed reading this as much as I did writing it. Now you should have the ability to use a touch screen in many situations – you just need to decide how to work with the resulting values from the screen and go from there.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

December 29, 2010 - Posted by | arduino, BOB-09170, education, hardware hacking, LCD-08977, microcontrollers, tutorial | , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

11 Comments »

  1. Hi John

    Nice project. You seem to have got the odd false postive, specifically @ 00:09 ‘CCC’ when finger is at ‘D’ location and @ 00:18 ‘BBB’ when finger is at D. Can these be eliminated? Is it just since the touch screen isn’t firmly mounted? Is it software.

    I’ve had a similar problem in a software only setting doing the same thing, dividing screen in 4 or 5 regions and conditionally testing from the x,y cords from a Wacom tablet. Occasionally the hits lock up in _two_ bordering regions and the software will flutter the ‘ON’ light between two regions. It seems to actually lock up and can keep going for a few seconds even when the stylus is removed. Needless to say this drives me nuts!! (Doesn’t seem to do it with the mouse as input device).

    For an _in situ_ A/V control device (which is where I’d like to go with something like what you have made with an LCD behind it) getting false hits on buttons would be a big No-No.

    Off the shelf systems to do that kinda thing have been around for decades but last time I checked were still super exy and not nearly customisable as an Arduino device. So this is worth getting to work reliably IMO.

    Comment by Alastair | December 30, 2010 | Reply

    • Hello Alastair
      Problems are due to mounting – I cannot find a bracket or bezel or anything premade anyway. In testing I tried putting some paper underneath the touch screen which improved things slightly. I am tempted to just superglue it over a graphical LCD for a project in mind similar to your AV setup. Stay tuned, I’ll probably publish it next month.
      cheers
      john

      Comment by John Boxall | December 30, 2010 | Reply

  2. Great. I look forward to seeing developments!

    Another thing I want to make is a temperature logger for an array of sensors. I’ve done a little research on arduino forums and it seems like one-wire protocols over cat5 cable are the most robust and reliable way to go. I was interested in your IC2 write up an will definitely try it as a starting tutorial.

    There are a few open source one-wire libraries available and the devices seem to come mainly from one US company but they are cheap. They use analogue pins instead or digital. Could you look at doing a tutorial on one-wire devices and code one day? No rush I still haven’t got my soldering hot yet!

    Comment by Alastair | December 31, 2010 | Reply

    • One-wire, ok I’ll put it on my list. Only problem with those is the signal loss of analog over distance, whereas I2C can be sent along great distances using booster ICs.
      Food for thought
      Happy New Year
      john

      Comment by John Boxall | December 31, 2010 | Reply

  3. Very helpful and fun :) C
    Cheers!

    Comment by primadeluxe | January 7, 2011 | Reply

  4. Thank you kindly :)
    So much nice options with this touchscreen!

    Comment by Primadeluxe | February 16, 2011 | Reply

  5. I am trying to put this together in my computer engineering class and i have multiple questions. first of all i do not have the lcd screen from the shield project. I have just a simple 16 by 2 lcd screen. will that work?

    Comment by mark | January 20, 2012 | Reply

    • Yes that will be fine, just change the dimensions in the LCD setup lines.

      Comment by John Boxall | January 20, 2012 | Reply

  6. Hello John.
    It seems this screen is discontinued: http://www.sparkfun.com/products/8448
    Thanks for your blog, it’s awesome!

    Comment by q2dg | June 19, 2012 | Reply

    • No worries, we use the Nintendo DS one.
      Thanks for your feedback
      cheers
      John

      Comment by John Boxall | June 19, 2012 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 3,838 other followers

%d bloggers like this: