Page 1 of 1

Touch screen control using an MSP430

PostPosted: Thu Nov 29, 2007 11:08 am
by pascal
Good morning,

Today, I could find some time to finish testing the new TFT screen
I got a month ago. This is the second part, the touch panel.
I have tried the other day to use an MSP 430 to send data to the
screen. I managed to do it, but it is not possible to do a lot with
an MCU due to the large amount of data that should be sent to the
screen. But this time, we will care about the touch panel only.

1. How a resistive touch panel works.
Imagine a sheet of conductive material (but resistive). The resistance
between two points will depend on the distance between these 2 points.
Now imagine that you have a rectangular sheet of resistive material
and 2 linear electrodes at each end.

Image

If you apply a voltage to that kind of device, the current is likely
to flow uniformly between the electrodes. As the resistance is proportional
to the length, the voltage at point P will be proportional to VCC and to
the ratio d/l. So if you have a method to measure the voltage ot point P,
you can calculate the location of one line, parallel to the electrodes,
where P is located.
For instance, if you have another sheet of conductive material, pressing
on one of the sheets will put both sheets in contact at point P. Then
if you measure the voltage of the second sheet, you can calculate the
location.
A resistive touch panel is no more than 2 sheets of conductive materials
that enter in contact at the point you press on them.

Image

Now what we want is to measure the position in two directions, so here is
the trick: the measurements will alternate like this:
(Left, rightm top, bottom are the electrodes names)
- Disconnect vertical sheet (top and bottom in high impedance)
- Set voltage to horizontal sheet (right = VCC, left = 0)
- Measure vertical sheet voltage; (measure top or bottom)
- Disconnect horizontal sheet (right and left in high impedance)
- Set voltage to vertical sheet; (top = VCC, bottom = 0)
- Measure horizontal sheet voltage. (mesure left or right).

Explanation: when we press on the touch panel, when one sheet is
disconnected, the impedance to ground or VCC is very high compared
to the resistance of the panel itself. So the connected sheet will have a potential
varying linearily with the distance from its electrodes, and the disconnected
panel will have the same voltage as the contact point because of the high impedance.
Therefore, by measuring the voltage of the disconnected sheet, we can calculate
the distance from the electrodes.
Now by alternating the connections (switch the unconnected sheet to connected
and vice versa, we can also measure the voltage in the other direction and
again calculate the distance from the electrodes.

Now another trick: when you disconnect one of the sheet, it can be
influenced by the environment. So we need a pull down to keep it from
getting noise. But this pull down should have a greater resistance than
the panel itself, otherwise it will too much influence the measurement.
The resistance of the panel is somewhere between 200 and 2000 ohms
according to the specs. So I have set a 47K resistance to keep the
voltage low if no touch.

2. Measuring using MSP430
The method explained above is very easy to implement using an MSP430.
- Attach left, right, top, bottom, to an IO port.
- Attach left and bottom to an ADC
I noticed after wiring that I could probably do everything with only
port 6 (could be reconfigured as a digital output or as an analog input
on the fly). But as the wiring was finished, I did the programming for
a 2 port version.

So here it is, in pseudo-code:

#define TOUCH_PORT_IN P2IN
#define TOUCH_PORT_DIR P2DIR
#define TOUCH_PORT_OUT P2OUT

#define MEAS_X 0x20
#define MEAS_Y 0x10

#define LEFT 0x01
#define RIGHT 0x02
#define BOTTOM 0x04
#define TOP 0x08

Then the measurement functions have been taken from TI's sample code in
slac015k.
I took the very first sample code as a reference. Here it the core of the
sample code:

Code: Select all
int main(void) {
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT
  ADC12CTL0 = ADC12ON;                  // ADC12ON
  P6SEL |= 0x01;                        // P6.0 ADC option select
  for (;;) {
    ADC12CTL0 |= ADC12SC + ENC;         // Sampling open
    ADC12CTL0 &= ~ADC12SC;              // Sampling closed, start conversion
    while ((ADC12CTL1 & ADC12BUSY) == 1);   // ADC12BUSY?
  }
  return 0;
}



As some parts of port 6 (ADC) are already taken on the board I used,
I have set left and bottom to P6.4 and P6 5 respectively.

There are probably ways to improve the functions I wrote, but since
I have to change some variables for switching / releasing the panel sheets
to / from the IO port, I thought it would be simpler to relaunch a one-shot
conversion everytime. So here is the get_x function.

Code: Select all
uint16 get_x(void) {
  uint16 retval;
  ADC12CTL0 |= ADC12ON;
  ADC12MCTL0 = INCH_5; // Sheet y to be used for x reading
  TOUCH_PORT_DIR |+ LEFT + RIGHT;
  TOUCH_PORT_OUT &= ~LEFT   // Set left to 0
  TOUCH_PORT_OUT |= RIGHT;   // Set right to VCC (or at least to logical 1)
  P6SEL = MEAS_X;      // Measure the x distance
  ADC12CTL0 |= ADC12SC + ENC;
  ADC12CTL0 &= ~ASC12SC;
  while((ADC12CTL1 & ADC12BUSY) == 1);
  // Disable conversion
  ADC12CTL0 &= ~ENC;
  ADC12CTL0 &= ~ADC12ON;
  retval = ADC12MEM0;
  return retval;
}



That's it. The get_y function is pretty much the same. Replace INCH_5 by
INCH_4, LEFT by BOTTOM, RIGHT by TOP, MEAS_X by MEAS_Y and that should do the
job.

3. Test and conclusion
I have tested the touch panel by using the graphic LCD PW10164LCD and
drawing a ball at a point related to the position in the other screen. See
next photograph.

Image

I could verify that the position is quite accurate: it is possible to move the
spot by 1 pixel and the spot show no jitter at all. I have also tried to scale
the display by 4 and it is also possible to have an accurate control of the
position. So this panel seems to be accurate enough for the LCD it is
mounted onto.

Note that the current implementation needs calibration. I made a
hard-coded calibration, which means that this cannot be used in
production. One way to solve this would be to store the offset and
amplitude of both X and Y into flash. It would therefore be possible to
calibrate the touch panel by software.

Now it is time to put this screen on sale! Leave me some time to write
documentation.
We will provide both source codes: the source code that draws a pattern
on the screen and the source code for the touch panel.

Pascal