4 wire touch screen: I'm touched.

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

Or, would that be "tetched?" (see http://en.wiktionary.org/wiki/te... )

I have the X+ pin pulled "high". The X- pin "low." I can see the Y- pin varying as I move my finger around. Pretty cool. My METER can see the voltage vary on Pin 9 of my xMega192D3, but the ADC always says 666. Well, it bounces a bit between 649 and 673.

Ok, trace this out a bit:

My readx function:

int TouchPositionX(void)
{
   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,0,ADC_REFSEL_VCC_gc) ;
}

RefSel indicates VCC/1.6 or 1.875V. Hmm, might be a problem, I see pin 9 going between 0.23 to 2.63.

Since it's pin 9, the datasheet says that's PB 3 or ADC 11. TouchXChannel says:

#define TouchXChannel 11

And here's the ADCread function:

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
	ADCA.PRESCALER = ADC_PRESCALER_DIV128_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 ;
   }
    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
    for(uint8_t Waste = 0; Waste<2; Waste++)
    {
       ADCA.CH0.CTRL |= ADC_CH_START_bm; // Start conversion
       while (ADCA.INTFLAGS==0) ; // Wait for complete
       ADCA.INTFLAGS = ADCA.INTFLAGS ;
    }
    return ADCA.CH0RES ;
}

And, here's where it's displayed:

   int sc = 0 ;
    while(1)
    {
      itoa(sc, S10, 10) ;
      WinWriteStr(&CountWindow, Tahoma32,0,0, S10, ColorWhite, ColorBlue) ;
      char bs[10] ;
      FormatNumber(BatteryVoltage(), bs, 2, "v") ;
      int x = WinWriteStr(&FullScreen, Tahoma16, 10, 180, PSTR("Bat: "), ColorWhite, ColorBlue) ;
      WinWriteStr(&FullScreen, Tahoma16, x, 180, bs, ColorYellow, ColorBlue) ;
      x = WinWriteStr(&FullScreen, Tahoma16, 10, 164, PSTR("Touch X: "), ColorWhite, ColorBlue) ;	  
      itoa(TouchPositionX(), S10, 10) ;
      WinWriteStr(&FullScreen, Tahoma16, x, 164, S10, ColorYellow, ColorBlue) ;
      _delay_ms(1000) ;
      sc += 1 ;
    }

Hmm. I thought all this analysis would show that I was reading the wrong ADC channel or writing the wrong char string to the display. Do I need to allow a settling time if I change the mux selection?

I was going to make a tiny program that just read the position and stuffed it in a variable so I could see it with the debugger, but my atmelice bit the dust.

You can see I've been testing the display functions. The one that didn't work yesterday is doing fine now. See the "Nuts!" written in the middle over the big C.

Attachment(s): 

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

Maybe it's the pin control! I thought of this while taking a walk.

Hmm. Don't think so.

	PORTB.DIR = 0;
	PORTB.PIN0CTRL = 0x07; // Disable input circuit on touch screen inputs.
	PORTB.PIN1CTRL = 0x07;
	PORTB.PIN2CTRL = 0x07;
	PORTB.PIN3CTRL = 0x07;
	PORTB.PIN4CTRL = 0x07;
	PORTB.PIN5CTRL = (3<<3);
	PORTB.PIN6CTRL = (3<<3);
	PORTB.PIN7CTRL = (3<<3);

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

I can give you some code for the AVR or LPC1114 (ported from AVR), I haven't bothered porting to Xmega because I would have to use AS6 and I get diarrhea.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
I can give you some code for the AVR or LPC1114 (ported from AVR), I haven't bothered porting to Xmega because I would have to use AS6 and I get diarrhea.

Eek! Don't do that!

I have a minimal program now that lets me see, using my re-fried Atmel-ICE, the values changing according to where I touch the screen.

/*
 * RemoteADCtest140731.c
 *
 * Created: 7/31/2014 4:47:47 PM
 *  Author: Tom
 
 * Minimal program to test ADC and touchscreen
 */ 

#define F_CPU 2000000
#include 
#include 

// TouchScreen
#define TouchPort PORTB
#define TouchYTop 2
#define TouchYBottom 3
#define TouchXTop 0
#define TouchXBottom 1

// Analog inputs
#define ADCBatteryChannel 12
#define TouchXChannel 11
#define TouchYChannel 8


void BoardInit(void)
{
	PORTA.DIR = 255 ;
	PORTA.PIN0CTRL = (3<<3);
	PORTA.PIN1CTRL = (3<<3);
	PORTA.PIN2CTRL = (3<<3);
	PORTA.PIN3CTRL = (3<<3);
	PORTA.PIN4CTRL = (3<<3);
	PORTA.PIN5CTRL = (3<<3);
	PORTA.PIN6CTRL = (3<<3);
	PORTA.PIN7CTRL = (3<<3);
	PORTA.OUT = 255 ;

	PORTB.DIR = 0;
	PORTB.PIN0CTRL = 0x07; // Disable input circuit on touch screen inputs.
	PORTB.PIN1CTRL = 0x07;
	PORTB.PIN2CTRL = 0x07;
	PORTB.PIN3CTRL = 0x07;
	PORTB.PIN4CTRL = 0x07;
	PORTB.PIN5CTRL = (3<<3);
	PORTB.PIN6CTRL = (3<<3);
	PORTB.PIN7CTRL = (3<<3);
	PORTB.OUT = 0 ;


	// PORT C is LCD Data Low
	PORTC.DIR = 255 ;
	PORTC.PIN0CTRL = (3<<3);
	PORTC.PIN1CTRL = (3<<3);
	PORTC.PIN2CTRL = (3<<3);
	PORTC.PIN3CTRL = (3<<3);
	PORTC.PIN4CTRL = (3<<3);
	PORTC.PIN5CTRL = (3<<3);
	PORTC.PIN6CTRL = (3<<3);
	PORTC.PIN7CTRL = (3<<3);
	PORTC.OUT = 0 ;

	// Port D is LCD Data High
	PORTD.DIR = 255 ;
	PORTD.PIN0CTRL = (3<<3);
	PORTD.PIN1CTRL = (3<<3);
	PORTD.PIN2CTRL = (3<<3);
	PORTD.PIN3CTRL = (3<<3);
	PORTD.PIN4CTRL = (3<<3);
	PORTD.PIN5CTRL = (3<<3);
	PORTD.PIN6CTRL = (3<<3);
	PORTD.PIN7CTRL = (3<<3);
    PORTD.OUT = 0 ;

	// PortE is LCD Control
	PORTE.DIR = 255 ;
	PORTE.PIN0CTRL = (3<<3);
	PORTE.PIN1CTRL = (3<<3);
	PORTE.PIN2CTRL = (3<<3);
	PORTE.PIN3CTRL = (3<<3);
	PORTE.PIN4CTRL = (3<<3);
	PORTE.PIN5CTRL = (3<<3);
	PORTE.PIN6CTRL = (3<<3);
	PORTE.PIN7CTRL = (3<<3);
	PORTE.OUT = 255 ;

	// PortF is LCD Control
	PORTF.DIR = 255 ;
	PORTF.PIN0CTRL = (3<<3);
	PORTF.PIN1CTRL = (3<<3);
	PORTF.PIN2CTRL = (3<<3);
	PORTF.PIN3CTRL = (3<<3);
	PORTF.PIN4CTRL = (3<<3);
	PORTF.PIN5CTRL = (3<<3);
	PORTF.PIN6CTRL = (3<<3);
	PORTF.PIN7CTRL = (3<<3);
	PORTF.OUT = 255 ;
}

static void adc_init(void)
{
	ADCA.CTRLA = ADC_ENABLE_bm;                     // Enable ADC
	ADCA.CTRLB = ADC_CURRLIMIT_NO_gc | ADC_CONMODE_bm ; // | ADC_RESOLUTION_MT12BIT_gc;  // No power saving, signed singleended mode, oversampling resolution
	ADCA.REFCTRL = ADC_REFSEL_VCC_gc;             // Use internal VCC/1.6  reference (same as DAC)
	ADCA.EVCTRL = ADC_EVACT_NONE_gc;                // Do not use events
	ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc;         // ADC clock = 1 MHz
	ADCA.CH0.CTRL = ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_SINGLEENDED_gc;       // No gain, use internal input (from DAC)
	ADCA.CH0.MUXCTRL = (11<<3);        // Use channel 11 input to ADC
	ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;   // No interrupts
	//ADCA.CH0.SCAN = 0;                              // No channel scanning

	/* This is the interesting stuff, select the average/oversampling you want to test */
	//ADCA.CH0.AVGCTRL = ADC_SAMPNUM_1X_gc;                                       // No averaging, no oversampling (change the resolution to 12 bit in CTRLB above)
	//ADCA.CH0.AVGCTRL = ADC_SAMPNUM_4X_gc | (1 << ADC_CH_RIGHTSHIFT_gp);         // Oversampling to 13-bit resolution
	//ADCA.CH0.AVGCTRL = ADC_SAMPNUM_16X_gc | (2 << ADC_CH_RIGHTSHIFT_gp);        // Oversampling to 14-bit resolution
	//ADCA.CH0.AVGCTRL = 0 ; //ADC_SAMPNUM_64X_gc | (1 << ADC_CH_RIGHTSHIFT_gp);        // Oversampling to 15-bit resolution
	//ADCA.CH0.AVGCTRL = ADC_SAMPNUM_256X_gc | (0 << ADC_CH_RIGHTSHIFT_gp);       // Oversampling to 16-bit resolution
	//ADCA.CH0.AVGCTRL = ADC_SAMPNUM_32X_gc;                                     // Averaging only
}


static uint16_t adc_read(void)
{
	ADCA.CH0.INTFLAGS = ADCA.CH0.INTFLAGS;               // Clear ADC interrupt flag
	ADCA.CH0.CTRL |= ADC_CH_START_bm;               // Start ADC single conversion
	while (!(ADCA.CH0.INTFLAGS & 1));    // Wait for ADC to complete
	return ADCA.CH0.RES;                            // Return result
}

uint16_t v = 0 ;

int main(void)
{
	BoardInit() ;
	adc_init() ;
	TouchPort.DIRSET = (1<<TouchXTop) | (1<<TouchXBottom) ;
	TouchPort.OUT = (1<<TouchXTop) ;
	_delay_us(500) ;
	
    while(1)
    {
       v = adc_read() ;
	   v = adc_read() ;
	   PORTC.OUT = v & 255 ;
	   PORTD.OUT = v>>8 ; 
    }
}

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

This is what I have for the AVR (no diarrhea)

#define T_YU PE7	// Pin 37 can be a digital pin
#define T_XL PE6	// Pin 38 can be a digital pin
#define T_YD PF3	// Pin 39 must be an analog pin, use "An" notation!
#define T_XR PF2	// Pin 40 must be an analog pin, use "An" notation!
.
.
uint16_t p_x, p_y, p_z=1;
.
.
// enable ADC, select ADC clock = F_CPU / 64 (i.e. 125 kHz)
   
	ADCSRA = (1<<ADEN | 1<<ADPS2 | 1<<ADPS1 );
.
.
void readTouch(void) 
	{
	//Do X
	ADMUX=(1<<REFS0 | ADC_2);	//Conversion on channel 2, AVCC reference,
	PORTE |= (1<<T_YU);		// YU High (V+ YU)
	DDRE |= (1<<T_YU);		// YU output
	PORTF &= ~ (1<<T_YD);	// YD Low (gnd YD)
	DDRF |= (1<<T_YD);		// YD output
	PORTE &= ~ (1<<T_XL);	// XL low (no pull up)
	DDRE &= ~ (1<<T_XL);	// XL input (disconnected)
	PORTF &= ~ (1<<T_XR);	// XR low (no pull up)
	DDRF &= ~ (1<<T_XR);	// XR input (ADC 2 read)
	_delay_ms(1);
	ADCSRA |= (1<<ADSC);					//Start conversion
	loop_until_bit_is_clear (ADCSRA, ADSC);	//Wait for conversion complete
	p_x =  ADCW;

//Do Y
	ADMUX=(1<<REFS0 | ADC_3);	//Conversion on channel 3, AVCC reference,
	PORTE |= (1<<T_XL);		// XL High (V+ XL)
	DDRE |= (1<<T_XL);		// YU output
	PORTF &= ~ (1<<T_XR);	// XR Low (gnd XR)
	DDRF |= (1<<T_XR);		// XR output
	PORTE &= ~ (1<<T_YU);	// YU low (no pull up)
	DDRE &= ~ (1<<T_YU);	// YU input (disconnected)
	PORTF &= ~ (1<<T_YD);	// YD low (no pull up)
	DDRF &= ~ (1<<T_YD);	// YD input (ADC 3 read)
	_delay_ms(1);
	ADCSRA |= (1<<ADSC);					//Start conversion
	loop_until_bit_is_clear (ADCSRA, ADSC);	//Wait for conversion complete
	p_y =  ADCW;
}
.
.

don't know if I have left anything out.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

And the main reason the original program wasn't working: I was passing 0 to ReadADC which selected set up the mux to read something internal, NOT the pin. I needed to pass 1 as the comment indicates. Once I got that going, it was a simple matter to set X High to 1, X Low to 0 and read voltage on Y Low, then set Y High to 1 and Y Low to 0 and read the voltage on Y High.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

To tell if the user is touching the screen or not, set the XHigh to an input with a pullup, set YHigh and YLow as output to 0. If the user is touching the screen, XHigh will read a low.

You can, of course, do it the other way around.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

And, now I broke it.

Since xMega ADC can't measure higher than VCC / 1.6 (That's VCC * 0.625.) The traditional technique will only see the "bottom" or is that "right" .625 part.

To solve this, I added 1K resistors to the x+ and y+ pins to make a resistor divider and shift the readings down so they don't bump into "full scale." Must have goofed something up 'cause now the display doesn't turn on. Monday's job.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

The OEDB System works with 4-wire touch and capacitive Touchscreens as well. For the 4-wire touch it has a calibration Software that accurately adjusts the Output to the Pixel Position.

Through a unique relative Position acquisition algorithm it works absolutely stable and fast at the same time :

http://www.youtube.com/watch?v=77j2ImAbYDQ

https://www.facebook.com/pages/Ostwald-Elektronik-GmbH/357867021056382

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

It's working now. Forgot to post a follow up when I got it going. The added resistors bring the touch screen within the range of the ADC and it doesn't go full scale before you reach the edge.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

So what's the story of your Atmel ice?  Did it melt?

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

The Atmel-ICE: (Atme-lice?)

 

I took it out of the case and noticed that there are no parts on the bottom side. "I can solder this with my frypan!" So I cleaned solder from the connector and board, put some fresh paste on and fried it. Working quite nicely now.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

Nice, refried Atmel-ICE.   Does the manual say how often you should fry it?

 

By the way, I've always wondered how boards with parts on both sides are made commercially.

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

how boards with parts on both sides are made commercially.

Not with a fry pan....  but with an oven. I had one board with parts on both sides, 64 RGB leds on the solder side, drivers on the component side.

 

The leds were glued in place and the boards would go into the oven on carrier frames so that both sides would solder simultaneously. At least that's what my board stuffer told me. laugh

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:

The leds were glued in place

Thanks.  I had heard of glue logic but I never knew what it meant.  smiley

 

I guess when you light up all colors, it emits white light.