Post Go back to editing

AD7879 value jamp

Category: Hardware
Product Number: AD7879W

My customer is evaluating the prototype of the product using AD7879W and display with touch panel.
Communication to AD7879W has been established, and various register settings and data readouts have been performed.
The display is 5.7inch by Ampire.

The following problem has occurred.
When testing any position, (for example, touching a position around 500 (dec) several times) it will occasionally jump to a value such as 2050 (dec).
Both X and Y occur, but Y is more common.
The values at the end of the jump tend to be similar, about 2050~2200 (dec).
Sometimes it was 1800 or 1900 (dec).
Problems also occurred when customers changed digital filters or sampling times.
Customers added capacitors (such as 1000 pF, 0.1 μF, 22 μF, or 47 μF) to the power bypass, but the same problem occurred.

If you know the solution, please let me know.
Thank you and best regards,

Parents Reply Children
  • Hi  ,

    When there is a weak or light touch on a resistive screen, X and Y plates bounce a bit due to the mechanical structure of the screen. Bouncing between X and Y layers can cause false activations, in that case the AD7879 outputs might not match touched positions. Some spurious values might also appear when the user lifts off the screen in the middle of a conversion sequence.

    ADI recommends including a software filter to eliminate sudden spikes due to the mechanical bouncing of the screen.  See attached sample code (AD7879_Filter.c) to reduce these effects.  This filter is applied to the AD7879 ADC outputs. The algorithm helps to filter out noise due to the bouncing of the plates but also noise coming from the LCD. The results after applying this software filter can be observed at the GUI screen.

    A significant improvement is achieved as shown in the images below that compare without and with the filter applied

    • Values close to 0 and 4095 are removed
    • Big steps between consecutive values are discarded from the FIFO.
    • The most recent value in the FIFO before lifting off the screen is removed.
    • Values in the FIFO are averaged

    A key factor when choosing a screen is the activation force. Activation force is an inherent parameter that usually is provided in the resistive panel datasheet. The choice of a screen with certain activation force depends on each customer requirements. A typical value for a standard 4-wire screen is less than 80g. The screen used in this test specifies an activation force value lower than 50g. A panel with lower activation force will provide a more accurate response if a user performs a light touch. As a general rule the higher sensitivity is required, the lower activation is recommended. Touch screen controllers such as the AD7879 cannot control the panel sensitivity; this is a mechanical parameter which depends on the panel manufacturer.

    Regards,

    Maurice.

    //AD7879 Filter.c
    //This file is based on algorithm that filters out noise from AD7979 TouchScreen Controller.
    //Does not include I2C or SPI communication.
    //Should only be used as an example of methodology used to filter the code.
    
    //We use a timer to count Time Between Data Available Interrupts. If there is a timeout
    //longer than touchdown timeout. This means we have lifted off and we must reset our FIFO and 
    //filter variables.
    
    //Function Definition
    void Touch_Isr(void);
    void WriteToAD7879(int RegAddress, char NbOfRegs, int  RegValue);
    void ReadFromAD7879(int RegAddress, char NbOfRegs);
    static void EnableTimer(void);
    
    //Generic AD7879 part Functions
    void SetAD7879ToDefaultTouchMode(void);
    void SetAD7879ToDefaultTemperatureMode(void);
    void SetAD7879ToDefaultBatteryMode(void);
    
    //Specific Operations on AD7879 Functions
    void SetConversionIntervalTimer(BYTE TimeoutValue);
    void SetADCChannelAddress(WORD ChannelAddress);
    void SetADCConversionMode(WORD ConversionMode);
    void SetFirstADCConversionDelay(BYTE FirstConversionDelay);
    void SetMedianFilter(WORD MedianFilter);
    void SetADCAveraging(WORD ADCAvgValue);
    void SetPowerMode(WORD PowerMode);
    
    
    //AD7879 Filter Values
    void InitialiseFifo(WORD *FifoName, const BYTE FifoLength, const WORD InitValue);
    void MoveDataInFifo(WORD *FifoName, const BYTE FifoLength, const WORD newData);
    int AverageContentOfFifo(WORD *FifoName, BYTE FifoLength);
    
    //Register Map of CTRL Registers
    #define CTRL_REG1								0x01
    #define CTRL_REG2								0x02
    #define CTRL_REG3								0x03
    #define XVALUE_REG								0x08
    #define YVALUE_REG								0x09
    #define Z1_TOUCH_VAL							0x0A
    #define Z2_TOUCH_VAL							0x0B
    
    //Defined values for 3 Control Registers for reading of X,Y Values
    #define REG1_VAL								0x8DFF
    #define REG2_VAL								0x4167
    #define REG3_VAL								0xD0F0
    
    #define FIFO_LENGTH								5
    
    #define MIN_VAL									20
    #define MAX_VAL									4055
    #define MAX_DIFF_VAL							300
       
    //---------------------------------------------------
    //Global variables for the communication with AD7879
    //--------------------------------------------------
    BYTE 	xdata NumberOfRegisters;			
    WORD  	xdata AD7879ReadWriteBuffer[64];
    WORD  	xdata g_XValue_FIFO[FIFO_LENGTH];
    WORD  	xdata g_YValue_FIFO[FIFO_LENGTH];
    WORD	xdata g_RegisterAddress;
    BYTE	xdata g_DataRegisterCounter;
    WORD	xdata XValue;
    WORD	xdata YValue;  
    BYTE 	FifoXFlag;
    BYTE 	FifoYFlag;
    
    bit		g_TouchScreenActivationStatus;
    bit     g_CommunicationMode;
    bit     g_PulseWidthValue;
    bit		g_SynchroniseWithInterrupt;
    bit		g_IsrFinished;
    BYTE 	xdata g_ActivationTimeoutCounter;
    
    //Define how long before without Interrupt before we turn off our Timer
    #define ACTIVATION_TIMEOUT_VALUE				150		//This value is in Milliseconds (cannot be more than 255)
    
    
    
    //Set up interrupts Timer and DAV Interrupt
    //Timer 0 definitions
    //-------------------
    //This just enables a timer using our Microcontroller
    #define TL0_VAL	  								0x5F
    #define TH0_VAL									0xF0
    
    void  main(void)
    {	
    	//1. Set up Part to TouchScreen Mode		
    	SetAD7879ToDefaultTouchMode
    
    	//2. Variable initialisation
    	g_TouchScreenActivationStatus = 0;
    	g_DataRegisterCounter = 0;
    
    	//3. Enable both AD7879 DAV interrupt and Timer interrupt to monitor
    	// when DAV interrupt stops, so we can reset FIFO's and Filters
    	IT0=0x1;		//The interrupt is negative level triggered
    	EX0=1;			//Enable external interrupt "0"
    	EA=1;			//Enable all 8051 interrupts
    
    	while(1)
    	{	
    
    	}
    
    }
    
    void Touch_Isr(void) interrupt 0 //INT0_VECT
    {
    	EA=0;
    	
    	//Count how long we are touching for	
    	if (g_DataRegisterCounter < 5)
    		g_DataRegisterCounter++;
    
    	//On First Touch Enable Timer
    	if (g_DataRegisterCounter==1)
    	{	
    		g_TouchScreenActivationStatus = 1;
    		//Enable timer
    		EnableTimer();		
    	}
    	else
    	{
    		ReadFromAD7879(XVALUE_REG, 4);//Reg Address, Number of Regs
    		//Wait for 3 interrupts before we initialise the fifo
    		if(g_DataRegisterCounter==3)
    		{
    			if((AD7879ReadWriteBuffer[0]>MIN_VAL) || (AD7879ReadWriteBuffer[0]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[1]>MIN_VAL) || (AD7879ReadWriteBuffer[1]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[2]>MIN_VAL) || (AD7879ReadWriteBuffer[2]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[3]>MIN_VAL) || (AD7879ReadWriteBuffer[3]<MAX_VAL))
    				{
    					//Initialise XValue_FIFO
    					InitialiseFifo(g_XValue_FIFO, FIFO_LENGTH,AD7879ReadWriteBuffer[0]);
    					
    					//Initialise YValue_FIFO
    					InitialiseFifo(g_YValue_FIFO, FIFO_LENGTH,AD7879ReadWriteBuffer[1]);			
    				}
    				else
    					g_DataRegisterCounter=1;
    		}
    		//After 3 interrupts update the Fifo Filter
    		else if(g_DataRegisterCounter > 3)
    		{
    			if((AD7879ReadWriteBuffer[0]>MIN_VAL) || (AD7879ReadWriteBuffer[0]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[1]>MIN_VAL) || (AD7879ReadWriteBuffer[1]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[2]>MIN_VAL) || (AD7879ReadWriteBuffer[2]<MAX_VAL) ||
    			   (AD7879ReadWriteBuffer[3]>MIN_VAL) || (AD7879ReadWriteBuffer[3]<MAX_VAL))
    				{
    					//X Value FIFO
    					MoveDataInFifo(g_XValue_FIFO, FIFO_LENGTH, AD7879ReadWriteBuffer[0]);
    
    					//Y Value FIFO
    					MoveDataInFifo(g_YValue_FIFO, FIFO_LENGTH, AD7879ReadWriteBuffer[1]);
    
    					//After we have moved values into FIFO we check for sudden spikes in code
                        //This is a exceptional difference between 2 points on the Axis.
    					//This value varies depending on Touchscreen
                        if ((abs(g_XValue_FIFO[0] - g_XValue_FIFO[1]) > MAX_DIFF_VAL) &&
                         	(FifoXFlag == 0))
    					 {                       
                            //We have a spike so remove it
                            g_XValue_FIFO[0] = g_XValue_FIFO[1];
                            FifoXFlag = 1;
    					}
                        else
                            FifoXFlag = 0; 
    						
    					//After we have moved values into FIFO we check for sudden spikes in code
                        //This is a exceptional difference between 2 points on the Axis.
    					//This value varies depending on Touchscreen
                        if ((abs(g_YValue_FIFO[0] - g_YValue_FIFO[1]) > MAX_DIFF_VAL) &&
                         	(FifoYFlag == 0))					                        
    					{
                            //We have a spike so remove it
                            g_YValue_FIFO[0] = g_YValue_FIFO[1];
                            FifoYFlag = 1;
                        }
    					else
                            FifoYFlag = 0; 
    						
    					//--------------------------------------------------------
    					//Average the FIFO's out and update X and Y values
    					//This is the Filtered Value
    					XValue = AverageContentOfFifo(g_XValue_FIFO, FIFO_LENGTH-1); //We are not going to use the most recent value to average
    					YValue = AverageContentOfFifo(g_XValue_FIFO, FIFO_LENGTH-1); //This is why we have FIFO_LENGTH-1
    					//--------------------------------------------------------												        
    				}		
    		}
    
    		//Finished ISR 
    		g_IsrFinished = 1;
    		g_ActivationTimeoutCounter = ACTIVATION_TIMEOUT_VALUE;
    	}
    	EA=1;
    	return;
    }
    
    
    //void Timer0_ISR() interrupt 1
    //---------------------------------
    //Interrupt service routine that is executed when the Timer 0 overflows. This 
    //interrupt responds to TF0 bit. Everytimes the isr is services, we read 
    //the proximity status
    //--------------------------------------------------------------------------------
    //This is timer used by us on ACuc841 Microcontroller.
    //Any timer which can provide a timeout at regular intervals can be used.
    static void Timer0_ISR() interrupt 1	//INT1_VECT
    {
    	if (g_ActivationTimeoutCounter > 0)
    		g_ActivationTimeoutCounter--;
    	else if (g_ActivationTimeoutCounter==0)
    	{	
    		//20ms have elapsed, therefore we register a deactivation
    		g_TouchScreenActivationStatus = 0;
    		g_DataRegisterCounter = 0;
    
    	}
    
    	return;
    }
    
    //---------------------------------
    //MoveDataInFifo():
    //---------------------------------
    //Function that shifts the data in the fifo. There are 2 types of Fifos: "WORD" and "long int", 
    //when calling them, we differentiate them using using the "FifoType" parameter
    static void MoveDataInFifo(int *FifoName, const char FifoLength, const int newData)
    {
    	char i;
    	
    	for(i=1; i<FifoLength; i++)
    	    FifoName[FifoLength-i] = FifoName[FifoLength-i-1];
    	FifoName[0]=newData;
    
    }
    
    
    //---------------------------------
    //InitialiseFifo()
    //---------------------------------/
    static void InitialiseFifo(int *FifoName, const char FifoLength, const int InitValue)
    {
    	char i;
    
    	for(i=0;i<FifoLength;i++)
    		FifoName[i]=InitValue;
    }
    
    //------------------------------------------------------
    //AverageContentOfFifo() 
    //------------------------------------------------------
    //Function that returns a value that corresponds to the average of the data in the Fifo
    static int AverageContentOfFifo(int *FifoName, char FifoLength)
    {
    	long int  xdata temp;
    	char xdata i;
    
    	temp=0;
    	//Don't use zero index of Fifo array. To Cancel out most recent touch
    	for(i=1; i<FifoLength; i++)
    		temp=temp+FifoName[i];
    	return(temp/FifoLength);
    }
    
    static void EnableTimer(void)
    {
    	///Enable timer 0 and chain a second interrupt
    	//This is done on First Interrupt only
    	//Timer will be enabled as long as we are touching
    	g_ActivationTimeoutCounter = ACTIVATION_TIMEOUT_VALUE;
    	TH0 = TH0_VAL;		//Configuration for 500uS
    	TL0 = TL0_VAL;
    	ET0 = 1;			//Timer 0 interrupt	
    	TR0 = 1;			//Timer 0 run control bit	
    }