Resistive Touch Screen -- (Solved)

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I post it here 'cause I'm using an xMega192D3.

 

Here's my "Read the ADC" code:

 

uint16_t ADCread(uint8_t Channel, uint8_t ADCMode, uint8_t RefSelect ) // Mode = 1 for single ended, 0 for internal
{
	if ((ADCA.CTRLA & ADC_ENABLE_bm) == 0)
	{
		ADCA.CTRLA = ADC_ENABLE_bm ; // Enable the ADC
		ADCA.CTRLB = (0<<5) | (1<<4) | (0<<1); // No current limit, Signed Mode 12 bit, Not free run
		ADCA.REFCTRL = RefSelect; // Which reference
		ADCA.EVCTRL = 0 ; // no events
		if (F_CPU > 16000000)
		{
			ADCA.PRESCALER = ADC_PRESCALER_DIV16_gc ;
		}
		else
		{
			ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc ;
		}
		ADCA.CALL = ReadSignatureByte(0x20) ; //ADC Calibration Byte 0
		ADCA.CALH = ReadSignatureByte(0x21) ; //ADC Calibration Byte 1
		//ADCA.SAMPCTRL = This register does not exist
		_delay_us(400); // Wait at least 25 clocks
	}
	if (ADCA.REFCTRL != RefSelect)
	{
		ADCA.REFCTRL = RefSelect ;
		_delay_us(4); // Wait 7 clocks/
	}
	ADCA.CH0.CTRL = ADC_CH_GAIN_1X_gc | ADCMode ; // Gain = 1, Single Ended
	ADCA.CH0.MUXCTRL = (Channel<<3);
	ADCA.CH0.INTCTRL = 0 ; // No interrupt
	//ADCA.CH0.SCAN Another bogus register
	uint16_t samp = 0 ;
	for(uint8_t Waste = 0; Waste<9; Waste++)
	{
		ADCA.CH0.CTRL |= ADC_CH_START_bm; // Start conversion
		while (ADCA.INTFLAGS==0) ; // Wait for complete
		ADCA.INTFLAGS = ADCA.INTFLAGS ;
		if (Waste>0) samp += ADCA.CH0RES ;
	}
	return samp>>3 ; // We could gain resolution by shifting right 1 or 2.
}

A feature here is the loop that averages 8 "oversamples" to get a stable figure.

 

Here's my touchpanel code:

uint8_t IsTouched(void)
{
	uint8_t ret = 0 ;
	TouchPort.DIRCLR = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.PIN0CTRL = PORT_OPC_PULLUP_gc ; // TouchXTop is digital input with pullup
	TouchPort.PIN1CTRL = PORT_OPC_PULLUP_gc ; 
	TouchPort.OUTSET = (1<<TouchXTop) ;
	TouchPort.PIN2CTRL = (3<<3) ;
	TouchPort.PIN3CTRL = (3<<3) ;
	TouchPort.DIRSET = (1<<TouchYTop) | (1<<TouchYBottom) ;
	TouchPort.OUTCLR = (1<<TouchYTop) | (1<<TouchYBottom) ;
	ret = (TouchPort.IN & (1<<TouchXTop)) ^ (1<<TouchXTop) ;
	return ret ;
}

int TouchPositionX(void)
{
	TouchPort.PIN2CTRL = 7 ;
	TouchPort.DIRSET = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.DIRCLR = (1<<TouchYTop) | (1<<TouchYBottom) ;
	TouchPort.OUTSET = (1<<TouchXTop) ;
	TouchPort.OUTCLR = (1<<TouchXBottom) | (1<<TouchYBottom) ;
	return ADCread(TouchXChannel,1,ADC_REFSEL_VCC_gc) ;//ADC_REFSEL_INT1V_gc
}

int TouchPositionY(void)
{
	TouchPort.PIN3CTRL = 7 ;
	TouchPort.DIRSET = (1<<TouchYTop) | (1<<TouchYBottom) ;
	TouchPort.DIRCLR = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.OUTSET = (1<<TouchYTop) ;
	TouchPort.OUTCLR = (1<<TouchYBottom) ;
	int v = ADCread(TouchYChannel,1,ADC_REFSEL_VCC_gc) ;
	return v ;
}

Now, all this seems to work in a bit of code like this:

	while( A != UILeftPRESS )
	{
		_delay_ms(500);
		if (A == UITouch) tetched = 1 ;
		if (A == UITouchn) tetched = 0 ;
		int ntbx = TouchPositionX() ;
		int ntby = TouchPositionY() ;
		char S10[10] = " " ;
		itoa( ntbx, S10, 10 ) ;
		int x = WinWriteStr( &MainWindow, Tahoma16, 10, 0, PSTR("  "), ColorWhite, ColorBlue ) ;
		x = WinWriteStr( &MainWindow, Tahoma16, 10, 0, S10, ColorWhite, ColorBlue ) ;
		x = WinWriteStr( &MainWindow, Tahoma16, x, 0, PSTR(" : "), ColorWhite, ColorBlue ) ;
		itoa( ntby, S10, 10 ) ;
		x = WinWriteStr( &MainWindow, Tahoma16, x, 0, S10, ColorWhite, ColorBlue ) ;
		x = WinWriteStr( &MainWindow, Tahoma16, x, 0,PSTR("  "), ColorWhite, ColorBlue ) ;
             }
		

I get "ntbx" values between 495 and 545 depending where I poke the screen. If I use the 1v ref, I get a wider range, which is nice. All seems to be working here. I get reasonable values for ntby too.

 

But in a bit of code like:

int TLeft = 0 ;

    while (IsTouched() == 0 ) ;
	TTop = TouchPositionY();
	TLeft = TouchPositionX();
	ShowMe(TLeft) ;

I get a value of 1588 for TLeft.

 

(This code is extracted from a much larger program which is getting cluttered by trying to figure out this accursed touch panel.)

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

Last Edited: Thu. Feb 12, 2015 - 10:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tom,

 

Reading a Resistive Touchscreen is quite fiddly.   It involves applying a voltage across XM,XP as digital pins.   And reading the Y pin via the ADC.   Then using YM,YP and reading X.   Then something else to calculate Z.

 

So you spend a lot of time changing pins from digital output to analog input and back again.    Then averaging the results.

It should be perfectly straightforward with the Xmega.   Just mimic the published code for the Mega.

 

No,  I have not studied your code.   I suggest that you print out a proven Mega implementation on paper.  Then hand-trace your code to compare the operation.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

xMega has an added complication in that it can't measure above vcc-0.6.

 

 

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is not too much of a problem.  Especially if you make XM, XP, YM, YP all analog pins.   You simply change polarity.   After all VP/VM = 0.95 going one way is 0.05 if you go the other way.

 

I have a resistive Touch on a Shield connected to a 32A4U chip.   I will need to check whether the Analog pins are accessible.  I might even give it a go.

 

From memory,   most Touch screens have some series resistance anyway.  So you won't get a 0% - 100% range on the ADC.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was having trouble with the top and left third showing full scale, so I added series resistors. Now it stays in range of the 1v reference. I thought I had it all working when I could touch the screen and see numbers varying as I move my finger around. Pretty slick.

 

Unfortunately, it only works now if I'm NOT testing to see if it's touched at all. 

 

Should have been an hour task and I've been stuck on it for weeks now.

 

X Position: "put X+ high. put X- low. ADC either Y."

Y Position: "put Y+ high. put Y- low. ADC either X."

IsTouched: "put Y+ and Y- low, Set X+ and X- as inputs with pullup. Test either for a low."

 

If I wasn't in such good control of myself I would have flung it by now. Where's a hammer?

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, now that I've pitched a fit, and refrained from smashing my gizmo, I've thought of a solution. I'll try it later this morning.

 

No, it does not involve explosives.

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So here's what I did....

 

Since the xMega can't measure voltages within 0.6 volts of the supply voltage, the touch screen has resistors in the "X+" and "Y+" lines to form a voltage divider so the sensed voltage can't go too high.

 

I changed TouchPositionX and TouchPositionY functions to leave the pullups turned on when they switched the pins to inputs. This pulls the inputs to + when there's no touch so the ADC gets full scale.

 

I know the screen is not being touched when TouchPositionY reads full scale.

int TouchPositionX(void)
{
	TouchPort.PIN2CTRL = (3<<3) ;
	TouchPort.PIN3CTRL = (3<<3) ;
	TouchPort.PIN0CTRL = (3<<3) ;
	TouchPort.PIN1CTRL = (3<<3) ;
	TouchPort.DIRSET = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.DIRCLR = (1<<TouchYTop) | (1<<TouchYBottom) ;
	TouchPort.OUTSET = (1<<TouchXTop) ;
	TouchPort.OUTCLR = (1<<TouchXBottom)  ;
	return ADCread(TouchXChannel,1,ADC_REFSEL_VCC_gc) ;//ADC_REFSEL_INT1V_gc
}

int TouchPositionY(void)
{
	TouchPort.PIN2CTRL = (3<<3) ;
	TouchPort.PIN3CTRL = (3<<3) ;
	TouchPort.PIN0CTRL = (3<<3) ;
	TouchPort.PIN1CTRL = (3<<3) ;
	TouchPort.DIRSET = (1<<TouchYTop) | (1<<TouchYBottom) ;
	TouchPort.DIRCLR = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.OUTSET = (1<<TouchYTop) ;
	TouchPort.OUTCLR = (1<<TouchYBottom) ;
	int v = ADCread(TouchYChannel,1,ADC_REFSEL_VCC_gc) ;
	return v ;
}

uint8_t IsTouched(void)
{
	int x = TouchPositionY() ;
	if (x<2040) return 1 ;
	return 0 ;
}

 

 

 

The largest known prime number: 282589933-1

In my humble opinion, I'm always right.