This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TSC2046E reading problem

Other Parts Discussed in Thread: TSC2046, TSC2046E

Hi,

I am trying to read data from tsc2046 with a m3 core of the concerto mcu. Can you lok at my code and see if there is a mistake. The penirq pin is working fine.

I have checked the connections between the tsc2046e and the touch screen 

X+ ....X_right

Y+.....Y_top

X-......X_left

Y-......Y_bottom

Also I have measured the voltages without any software running.
not touching
X+......3,3V

Y+......3,3V

X-.......0V

Y-.......3,3V

touching
X+......3,3V

Y+......0V

X-.......0V

Y-.......0V


 I have tried with  DCLK 5kHz- 25kHZ-775kHz, but the values are not stable. 

 

void tsc2046_read() // this is the main function that writes x to read_data[0] and y to read_data[1]
{
unsigned int i;

if(GPIOPinRead(GPIO_PORTH_BASE, GPIO_PIN_1)==0)
{
read_data[0]=read_value(0xD9);// get x 
}
else
{
for(i=0;i<3;i++)
{
read_data[i]=0;
}
}

if(GPIOPinRead(GPIO_PORTH_BASE, GPIO_PIN_1)==0)
{
read_data[1]=read_value(0x99);
}
else
{
for(i=0;i<3;i++)
{
read_data[i]=0; // get y
}
}

}

unsigned long read_value(unsigned int data)
{
unsigned int resh, resl,i;
unsigned long read[3],result;
long d[3];


//X1
SPISS_OFF;
SysCtlDelay(delay);
spiComm(data); 
resh = spiComm(0x00) & 0x7F; // clock out 8 zeros - read 1/b11-b5...
resl = spiComm(0x00); // clock out 8 more zeros - read b4-b0 + 3 zeros...

okunan[0] = (resh*256 + resl)>>3;
SysCtlDelay(delay);
SPISS_ON ; // deselect slave

//X2 
SPISS_OFF; /
SysCtlDelay(delay);
spiComm(data); 
resh = spiComm(0x00) & 0x7F; // clock out 8 zeros - read 1/b11-b5...
resl = spiComm(0x00); // clock out 8 more zeros - read b4-b0 + 3 zeros...

okunan[1] = (resh*256 + resl)>>3;
SysCtlDelay(delay);
SPISS_ON ; // deselect slave

//X3 
SPISS_OFF; // slave mode
SysCtlDelay(delay);
spiComm(data-1); 
resh = spiComm(0x00) & 0x7F; // clock out 8 zeros - read 1/b11-b5...
resl = spiComm(0x00); // clock out 8 more zeros - read b4-b0 + 3 zeros...

okunan[2] = (resh*256 + resl)>>3;
SysCtlDelay(delay);
SPISS_ON ; // deselect slave

d[0]=read[0]-read[1]; 
d[1]=read[1]-read[2]; 
d[2]=read[2]-read[0]; 

for (i=0;i<3;i++)
{
if(d[i]<0)
{
d[i]=-d[i]; //absolute value of difference
}
}

//Find the closest values
if(d[0]<d[1])
{
if(d[0]<d[2])
{
result = read[0]+read[1];
}
else
{
result = read[0]+read[2];
}
}
else
{
if(d[1]<d[2])
{
result= read[1]+read[2];
}
else
{
result= read[0]+read[2];
}
}

result>>=1;
return result;
}

/*===================================================================
spiComm(): SPI 
===================================================================*/
unsigned int spiComm(unsigned int spidata)
{
unsigned int i;
unsigned int spirecv;

spirecv = 0;

for (i=0; i<8; i++)
{
SPISCLK_OFF; // drop SCLK
SysCtlDelay(delay);
//SPIMOSI = spidata & 0x80;
if(spidata & 0x80) // write bit
SPISMOSI_ON;
else
SPISMOSI_OFF;

spidata <<= 1; // shift to next bit
SysCtlDelay(delay);
SPISCLK_ON; // raise SCLK
spirecv <<= 1; // get ready to receive
SysCtlDelay(delay);
spirecv |= SPIMISO; // read bit
SysCtlDelay(delay);
}
SPISCLK_OFF;
return spirecv;
}

  • Hello Unal,

    Before connecting the touch panel to the TSC, please measure your touch panel first --

    • without touch:
    • the resistance between the left to the right (X+ to X-), which should be in the range 200-ohms to 1000-ohms typically
    • the resistance between the top and the bottom (Y+ to Y-), which should be in the range 200-ohms to 1000kohms typically
    • the resistance between X+ (or X-) to Y+ (or Y-), which should be almost infinite typically
    • with a touch:

    • the resistance between the left to the right (X+ to X-), which should be exactly the same as that without touch
    • the resistance between the top and the bottom (Y+ to Y-), which should be exactly the same as that without touch
    • the resistance between X+ (or X-) to Y+ (or Y-), which should be from some 100s-ohms to some Ks-ohms, depending on touch pressure and strong touch results in lower resistance and weak touch results in higher resistance.

    If your touch panel meets the above resistance range, you can connect the TSC2046 with the touch panel, typically in such a way

    Left to TSC2046 X+

    right to TSC2046 X-

    Top to TSC2046 Y+

    bottom to TSC2046 Y-.

    Please note that, in fact, the X+ and X- can be exchangeable; and so are Y+ and Y-. For example, if you connect left to X+ and right to X- (as I mentioned above), the X data is the minimal if the touch location is at the most right and the X data is the maximal if the touch moves to the most left; and  if you connect right to X+ and left to X- (as you have currently), the X data is the maximal if the touch location is at the most right and the X data is the minimal if the touch moves to the most left. Such connection differences can be corrected by a line of software code -- X = 4095 - XRAW (if 12-bit resolution).

    That is: the X+ and X-  can be connected to the touch panel's left and right pins, respectively; or right and left pins, respectively, and the difference can be changed back by software X = 4095 - XRAW. Similarly, the Y+ and Y-  can be to the touch panel's top and bottom, respectively; or bottom and top, respectively. The difference can be changed back by software Y = 4095 - YRAW.

    After the connection, please keep /CS high and do not run any SPI software,  and  then measure the voltage at the X+, X-, Y+, or Y-, and you should get:

    • Without touch:
    • X+ = 3.3V
    • X- = 3.3V
    • Y+ = 0V
    • Y- = 0V
    • With a touch
    • X+ = 0V
    • X- = 0V
    • Y+ = 0V
    • Y- = 0V

    Also tell me what is the status of the TSC2046 /PENIRQ pin, which should be kept at high without touch; or low with a touch.

    After we get the touch panel and its connection right, we can further go into the software in our further discussion the next.

    Regards,
    Wendy F.

  • Thank you Wendy for your quick reply. I did the things exactly as you said  and here are the results.



    Touch screen resistance measurement without any connection to tsc2046 

    Without touch

    XR-XL 597 ohm
    YT-YB 353 ohm
    YB-XR infinite
    YB-XL infinite
    YT-XR infinite





    With touch

    XR-XL 594 ohm
    YT-YB 350 ohm
    YB-XR 890 ohm
    YT-XR 760 ohm






    TSC2046E Voltage measurement with touch screen connected without spi software running

    CS= 3.3 volt 

    Without touch

    X+ 3.3 V
    Y+ 0 V
    X- 3.3 V
    Y- 0 V
    penirq 3.3 V

    With touch

    X+ 0 V
    Y+ 0 V
    X- 0 V
    Y- 0 V
    penirq 0 V
  • Hello Unal,

    Good, it seems correct with your hardware connection now. Please also note that: the connection between the touch panel and the TSC is the key for the touch system performance and it should be kept as simple, as short, and as secure as possible.

    Looked into your software code, I find the following suspected spots:

    (1)  your command is either 0xd9 (for read x) or 0x99 (for read y), and shows that you are using 8-bit resolution mode. But your software code has 12-bit data format.

    For 8-bit resolution, the data should be

    okunan[ ] = (resh*256 + resl)>>7;

    For 12-bit resolution, the data should be

    okunan[ ] = (resh*256 + resl)>>3.

    (2) Based on your code, you have put the SPI read 3 data into array variable okunan[0], okuan[1] and okuan[2]; but the returned variable result is calculated from another array variable read[0], read[1] and read[2]. Have I missed something?

    Please double check! 

    Regards,
    Wendy F.

  • Wendy,

    I want to use 12 bit format.,so I should send 0xD1 for x Ithink and 0x91 for y. I know the mismatch of the variable names.It's my fault I changed the variable names.They were not in english. I changed the names while writing here to make it easy for everyone  to understand . I missed some of them :) Also I will use 

    okunan[ ] = (resh*256 + resl)>>3.

    for 12 bit reading. 

    I have tried with 0xD1 and 0x91 still values are not good enough. The values are changing. 

    I use this codes to read x:


    0xD1

    0xD1

    0xD0

    and for y

    0x91

    0x91

    0x90

    Are these ok?

     

  • Hello Unal,

    Yes, the sequence you provided for reading touch data is good.

    Is the data noisy, or totally nonsense? Can you provide me your raw data from your system? 

    Regards,
    Wendy F.

  • My code sequence that I am sending is exactly the same as you said.It is noisy. For example in 8 bit mode it has got various values changing between 150-250 while pressing the same area touching without taking my finger off. It's like 150 - 248 - 248 -248 -180 -240 something like that. I am using an timer interrupt. And check the pernirq in 10ms periods. If there is a touch then I read the data. Can you please check my code that I have send before. I want to be sure about it. If it is ok , then I will look for hardware solutions.

  • Hello Unal,

    I will check your code. However, I am on business trip this week and "free" time for me is very limited and thus please expect some delay!

    In the mean time, may you send me the related schematic of your system? Thanks!

    Regards,
    Wendy F.

  • Hello Unal,

    For noise problem, there are several spots to checkup, refer to the application report sbaa155a. Also double check the schematic could be helpful too.

    Just checked your code provided in your first post, and could not find obvious problem. Just to make sure:

    (1) Make sure using 8-bit (0xD9 and 0x99) with read_data[] = (resh*256 + esl)>>7; or 12 bit (0xD1 and 0x91) with read_data[] = (resh*256 + resl)>>3;

    (2) your spiComm() sub-routine seems the same as my EVM's routine. For your double check, the below is what in TSC2046EVM --

    /*===================================================================
    spiComm(): Write & Read from SPI
    ===================================================================*/
    byte spiComm(byte spidata)
    {
     byte i;
     byte spirecv;

    spirecv = 0;

     for (i=0; i<8; i++)
     {
      SPISCLK = 0;     // drop SCLK
      SPIMOSI = spidata & 0x80;  // write bit
      spidata <<= 1;     // shift to next bit
      SPISCLK = 1;     // raise SCLK
      spirecv <<= 1;     // get ready to receive
      spirecv |= SPIMISO;    // read bit
     }
     SPISCLK = 0;
     return spirecv;
    }

    Best regards,

    Wendy F.

  • Hello Wendy,

    I have checked the pcb but couldn't find any solution. I measured the x+, x-,y+,y- using an oscilloscope and all of them change smoothly as I move my finger on the screen.  But I couldn't get a smooth data. The differences between following reads are huge. I think it's a software problem. But I couldn't figure out where in the code ? Also I get 3 datas for one read and apply them closest average filter as you described in the application note. If analog values are changing accordingly why the datas are not stable. I hope we solve the problem. I have send the files for 100 readings continuously to your e-mail.

    Best Regards
    Ünal 
     

  • Hello Unal,

    In order to make sure you have fixed all issues we discussed, I am putting the non-error (but I can not test it in your system ;-) ) source code below, for your reference.

    Regards,
    Wendy F.

    *******************

    void tsc2046_read() // this is the main function that writes x to read_data[0] and y to read_data[1]
    {
    unsigned int16 X[3], Y[3];

     if(GPIOPinRead(GPIO_PORTH_BASE, GPIO_PIN_1)==0)
     {
      X[0] = read_value(0xD9);// get x1
      X[1] = read_value(0xD9);// get x2
      X[2] = read_value(0xD8);// get x3
     }
     else
     {
      goto Rend;
     }
     if(GPIOPinRead(GPIO_PORTH_BASE, GPIO_PIN_1)==0)
     {
      Y[0] = read_value(0x99);// get y1
      Y[1] = read_value(0x99);// get y2
      Y[2] = read_value(0x98);// get y3
     }
     else
     {
      goto Rend;
     }
     read_data[0] = filt_value(X[0], X[1], X[2]);
     read_data[1] = filt_value(Y[0], Y[1], Y[2]);
     
    Rend:
     return;
    }

    unsigned int16 read_value(byte data)
    {
    byte resh, resl;
    unsigned int16 result;

     SPISS_OFF;
     SysCtlDelay(delay);
     spiComm(data);
     resh = spiComm(0x00) & 0x7F; // clock out 8 zeros - read 1/b11-b5...
     resl = spiComm(0x00); // clock out 8 more zeros - read b4-b0 + 3 zeros...
     result = (resh*256 + resl)>>7;
     SysCtlDelay(delay);
     SPISS_ON ; // deselect slave
     return(result);
    }

    unsigned int16 filt_value(unsigned int16 val0, unsigned int16 val1, unsigned int16 val2)
    {
    unsigned int16 result;
    int16 diff0, diff1, diff2;

     diff0 = val0 - val1;
     diff1 = val1 - val2;
     diff2 = val2 - val0;
     diff0 = diff0 > 0  ? diff0 : -diff0;
     diff1 = diff1 > 0  ? diff1 : -diff1;
     diff2 = diff2 > 0  ? diff2 : -diff2;
     // Eliminate the one away from other two and add the two
     if (diff0 < diff1)
      result =(unsigned int16)(val0 + ((diff2 < diff0) ? val2 : val1));
     else 
      result =(unsigned int16)(val2 + ((diff2 < diff1) ? val0 : val1));
     // Get the average of the two good samples
     result >>= 1;
     return(result);
    }