Problems in PIC16F722 Capacitive Touch sensing

This conference allows discussion on any subject not already covered in another PICmicro conference. If a topic becomes popular enough, a new conference will be created for it.

Problems in PIC16F722 Capacitive Touch sensing

Postby MVA » Fri Jul 21, 2017 4:05 am

I am using PIC16f722 MCU for implementing capacitive sensing but facing issues in implementing it. I have referred the Microchip AN1103 to help me with software part. I have written my own code by considering that Capacitive sensor works by detecting drop in frequency of Capacitive OSC but my code don't work as expected the switches are getting triggered without pressing ! or outputs just flips randomly. I have also tried implementing different touch pad designs with different gaps between them by thinking error was due to crosstalk but it didn't helped. So I believe there is a problem in my code.

Here is my code:
Code: Select all
sbit AP0 at RA0_bit; //outputs
sbit AP1 at RA1_bit;
sbit AP2 at RA2_bit;
sbit AP3 at RA4_bit;

volatile bit SWP0,SWP1,SWP2,SWP3;//flags to indicate switch was pressed
unsigned short Timer0_value=0;
unsigned short sensor_No=0;//This indicates the current cap sensor number which is being scanned
float Last_Frequency[4]={0,0,0,0};//this indicates last frequency count
unsigned long trip[4]={500,1090,1090,500};
float current_frequency=0;//this indicates current frequency count
bit first_Read;//this indicates that system has first started so Last_Frequency should hold value of no capacitive load. Nominal frequency.
///this also indicates that all sensor last frequency or nominal frequency is saved in array of Last_Frequency
unsigned short avg_count=0;//this indicates the current avg_count while averaging

void interrupt(){
  if(PIR1.TMR1IF==1){
     Timer0_value=TMR0;
     TMR0=0;
     //firstly all sensors nominal frequencies will be stored. This state is indicated by first_Read bit
     if(first_Read==0){//Here Last_Frequency[sensor_No] will hold the nominal frequency(averaged)
     
      AP0=~AP0;
      AP1=~AP1;
      AP2=~AP2;
      AP3=~AP3;
     
      if(avg_count<31){//take 30 samples
      if(Last_Frequency[sensor_No]!=0){
      Last_Frequency[sensor_No]=Last_Frequency[sensor_No]+Timer0_value/0.0131072; //0.0131072 is period of Timer1 will interrupt which is used as a fixed timebase.
      }else Last_Frequency[sensor_No]=Timer0_value/0.0131072;
      avg_count++;
      }else {
       
        Last_frequency[sensor_No]=Last_frequency[sensor_No]/30;
        avg_count=0;
        sensor_No++;
        if(sensor_No>3){
        sensor_No=0;//reset cap sensor count
        first_Read=1;//all nominal frequencies are stored in Last_Frequency array
        AP0=0;
        AP1=0;
        AP2=0;
        AP3=0;
        }
        CPSCON1=sensor_No;
      }
     
     }else{
     
     if(avg_count<31){
     if(current_frequency!=0){
     current_frequency=current_frequency+Timer0_value/0.0131072;//get current frequency take 30 samples
      }else current_frequency=Timer0_value/0.0131072;
      avg_count++;
     
     }else{
       
     avg_count=0;
     current_frequency=current_frequency/30;//take average
     
        //Below current frequency is compared with stored nominal frequency of selected sensor
     if(current_frequency<Last_Frequency[sensor_No]-trip[sensor_No]){//here 1000 is the calibrated value used to tune sensitivity of sensor according to material over sensor
      //button pressed
      switch(sensor_No){
       case 0: SWP0=1;break;
       case 1: SWP1=1;break;
       case 2: SWP2=1;break;
       case 3: SWP3=1;break;
      }
     }else{
      //button not pressed
       switch(sensor_No){
       case 0: SWP0=0;break;
       case 1: SWP1=0;break;
       case 2: SWP2=0;break;
       case 3: SWP3=0;break;
      }
     }
     
     //change sensor no as current sensor was scanned
     sensor_No++;
     current_frequency=0;//reset
     if(sensor_No>3)sensor_No=0;//reset
     CPSCON1=sensor_No;
    }
   
    }
     TMR1L=0;
     TMR1H=0;
     TMR0=0;
     PIR1.TMR1IF=0;
  }else {
  TMR1L=0;
     TMR1H=0;
     TMR0=0;
     PIR1.TMR1IF=0;
  }
}

void main() {

TRISA=0x00;
ANSELA=0x00;
SWP0=0;//Switch is not pressed
SWP1=0;//Switch is not pressed
SWP2=0;//Switch is not pressed
SWP3=0;//Switch is not pressed

first_Read=0;//No first read has done.

//reset all outputs
AP0=0;
AP1=0;
AP2=0;
AP3=0;

//Enable Capcitive sensing module
CPSCON0.CPSON=1;
CPSCON0.CPSRNG1=0;
CPSCON0.CPSRNG0=1;
CPSCON0.T0XCS=1;
OPTION_REG.T0CS=1;

CPSCON1=0x00;//Enable CPS0 channel.at RB0

TRISB=0x00;
TRISB.B0=1; //set RB0 as input as it is capacitive input.
TRISB.B1=1;
TRISB.B2=1;
TRISB.B3=1;
ANSELB=0x00;
ANSELB.B0=1;//set ANSELB.B01=1 to enable analog input on RB0 pin.It is required in capacitive sensing.Don't know why!
ANSELB.B1=1;
ANSELB.B2=1;
ANSELB.B3=1;


//Initialize Timer1 for interrupts to scan cap sensors
TMR1IE_bit=1;
PEIE_bit=1;
GIE_bit=1;
TMR1IF_bit=0;
// Timer1 Registers: Prescaler=1:1; TMR1 Preset=0; Freq=76.29395Hz; Period=0.0131072 s
T1CON.T1CKPS1 = 0; // bits 5-4 Prescaler Rate Select bits
T1CON.T1CKPS0 = 0; // bit 4
T1CON.T1OSCEN = 0; // bit 3 Timer1 Oscillator Enable Control: bit 1=on
T1CON.T1SYNC = 1; // bit 2 Timer1 External Clock Input Synchronization Control bit:1=Do not synchronize external clock input
T1CON.TMR1CS0 = 0; // Timer 1 clock source is FOSC and not FOSC/4
T1CON.TMR1CS1 = 0; // Timer 1 clock source is FOSC and not FOSC/4
T1CON.TMR1ON = 1; // bit 0 enables timer
TMR1H = 0; // preset for timer1 MSB register
TMR1L = 0; // preset for timer1 LSB register
TMR0=0;

while(1){

  ///below for each SWPx bit that respective AP(toggle its state)
   if(SWP0){
    AP0=~AP0;
    SWP0=0;//reset this flag
   }
   
   if(SWP1){
    AP1=~AP1;
    SWP1=0;//reset this flag
   }
   
   if(SWP2){
    AP2=~AP2;
    SWP2=0;//reset this flag
   }
   
   if(SWP3){
    AP3=~AP3;
    SWP3=0;//reset this flag
   }

};

}


The above code is not working as expected so I tried to change my code by referring to code from this website: http://www.pcbheaven.com/circuitpages/P ... _Function/. But the code was in assembly so I translated it to C. But it didn't help. This time nothing happened with touching as well as without touching! Maybe this code is not translated well but the code in assembly worked as shown by author in video. And I didn't understood his algortihm too! Here is translated code:
Code: Select all
sbit AP0 at RA0_bit; //outputs
sbit AP1 at RA1_bit;
sbit AP2 at RA2_bit;
sbit AP3 at RA4_bit;

//bit SWP0,SWP1,SWP2,SWP3;//indicates switch was pressed
int PressThreshold_H=0;
int PressThreshold_L=12;
int CountL=0;
int CountH=0;
int CapCh0_H,CapCh0_L,CapCh1_H,CapCh1_L,CapCh2_H,CapCh2_L,CapCh3_H,CapCh3_L;
bit OutputFound;
unsigned short sensorNo=0;

void changeTMR1Gate(){
  TMR0=255;
  if(T1GCON.T1GVAL==1){
    TMR1L=0;
    TMR1H=0;
    TMR0=0;
    T1CON.TMR1ON=1;
    T0IF_bit=0;
    //asm retfie;
  }
}

void firstTime0(){
 CapCh0_L=PressThreshold_L-CountL;
 if(CapCh0_L<0.0){
   CountH--;
   CapCh0_H=CountH-PressThreshold_H;
 }else{
 CapCh0_H=CountH-PressThreshold_H;
 }
}

void firstTime1(){
 CapCh1_L=PressThreshold_L-CountL;
 if(CapCh1_L<0.0){
   CountH--;
   CapCh1_H=CountH-PressThreshold_H;
 }else{
 CapCh1_H=CountH-PressThreshold_H;
 }
}

void firstTime2(){
 CapCh2_L=PressThreshold_L-CountL;
 if(CapCh2_L<0.0){
   CountH--;
   CapCh2_H=CountH-PressThreshold_H;
 }else{
 CapCh2_H=CountH-PressThreshold_H;
 }
}

void firstTime3(){
 CapCh3_L=PressThreshold_L-CountL;
 if(CapCh3_L<0.0){
   CountH--;
   CapCh3_H=CountH-PressThreshold_H;
 }else{
 CapCh3_H=CountH-PressThreshold_H;
 }
}


void checkSensor0(){
CPSCON1=1;
if(CapCh0_H==0&&CapCh0_L==0){
firstTime0();
}else{
 if(CountH<CapCh0_H&&CountL<CapCh0_L){
   AP0=~AP0;
   OutputFound=1;
   delay_ms(700);
 }
}
changeTMR1Gate();
}

void checkSensor1(){
CPSCON1=2;
if(CapCh1_H==0&&CapCh1_L==0){
firstTime1();
}else{
 if(CountH<CapCh1_H&&CountL<CapCh1_L){
   AP1=~AP1;
   OutputFound=1;
   delay_ms(700);
 }
}
changeTMR1Gate();
}

void checkSensor2(){
CPSCON1=3;
if(CapCh2_H==0&&CapCh2_L==0){
firstTime2();
}else{
 if(CountH<CapCh2_H&&CountL<CapCh2_L){
   AP2=~AP2;
   OutputFound=1;
   delay_ms(700);
 }
}
changeTMR1Gate();
}


void checkSensor3(){
CPSCON1=0;
if(CapCh3_H==0&&CapCh3_L==0){
firstTime3();
}else{
 if(CountH<CapCh3_H&&CountL<CapCh3_L){
   AP3=~AP3;
   OutputFound=1;
   delay_ms(700);
 }
}
changeTMR1Gate();
}

void interrupt(){
  if(T0IF_bit==1){
  //AP0=~AP0;
     if(T1GCON.T1GVAL==1){
     changeTMR1Gate();
     }else{
       TMR1ON_bit=0;
       CountL=TMR1L;
       CountH=TMR1H;
       sensorNo=CPSCON1;

      switch(sensorNo){
      case 0: checkSensor0();break;
      case 1: checkSensor1();break;
      case 2: checkSensor2();break;
      case 3: checkSensor3();break;
      }
     }
  }
}

void main() {

TRISA=0x00;
ANSELA=0x00;

TRISB=0x00;
TRISB.B0=1; //set RB0 as input as it is capacitive input.
TRISB.B1=1;
TRISB.B2=1;
TRISB.B3=1;
/*ANSELB=0x00;
ANSELB.B0=1;//set ANSELB.B01=1 to enable analog input on RB0 pin.It is required in capacitive sensing.Don't know why!
ANSELB.B1=1;
ANSELB.B2=1;
ANSELB.B3=1;*/

CapCh0_H=0;
CapCh1_H=0;
CapCh2_H=0;
CapCh3_H=0;

CapCh0_L=0;
CapCh1_L=0;
CapCh2_L=0;
CapCh3_L=0;


//reset all outputs
AP0=0;
AP1=0;
AP2=0;
AP3=0;

OPTION_REG.T0CS=0;
OPTION_REG.PSA=0;
OPTION_REG.PS0=1;
OPTION_REG.PS1=0;
OPTION_REG.PS2=1;
INTCON=0;
INTCON.T0IE=1;

//Enable Capcitive sensing module
CPSCON0.CPSON=1;
CPSCON0.CPSRNG1=1;
CPSCON0.CPSRNG0=1;
CPSCON0.T0XCS=0;


CPSCON1=0x00;//Enable CPS0 channel.at RB0

T1CON=0b11000100;
T1GCON=0b11100001;
TMR1L=0;
TMR1H=0;
TMR0=0;
TMR1ON_bit=1;
GIE_bit=1;


while(1){

  /*///below for each SWPx bit that respective AP(toggle its state)
   if(SWP0){
    AP0=~AP0;
    SWP0=0;//reset this flag
   }

   if(SWP1){
    AP1=~AP1;
    SWP1=0;//reset this flag
   }

   if(SWP2){
    AP2=~AP2;
    SWP2=0;//reset this flag
   }

   if(SWP3){
    AP3=~AP3;
    SWP3=0;//reset this flag
   }*/

};

}


Lastly I tried changing my code according to AN1103. But the symptoms were same as above no output was working it seems switch press was not detected. In this application note their code is incomplete hence I didn't understood their algorithm to detect frequency change. Here is the code developed with help of AN1103:
Code: Select all
sbit AP0 at RA0_bit; //outputs
sbit AP1 at RA1_bit;
sbit AP2 at RA2_bit;
sbit AP3 at RA4_bit;

volatile bit SWP0,SWP1,SWP2,SWP3;//indicates switch was pressed
unsigned short Timer0_value=0;
unsigned short sensor_No=0;//This indicates the current cap sensor number which is being scanned
float Last_Frequency[4]={0,0,0,0};//this indicates last frequency count
unsigned long trip[4]={300,350,420,600};
float current_frequency=0;//this indicates current frequency count
bit first_Read;//this indicates that system has first started so Last_Frequency should hold value of no capacitive load. Nominal frequency.
///this also indicates that all sensor last frequency or nominal frequency is saved in array of Last_Frequency
unsigned short avg_count=0;//this indicates the current avg_count while averaging

void interrupt(){
  if(PIR1.TMR1IF==1){
     current_frequency=TMR0;
     TMR0=0;

     if(current_frequency<(Last_frequency[sensor_No]-trip[sensor_No])){
     switch(sensor_No){
      case 0: SWP0=1;break;
      case 1: SWP1=1;break;
      case 2: SWP2=1;break;
      case 3: SWP3=1;break;
     }
     }else if(current_frequency>(Last_frequency[sensor_No]-trip[sensor_No]+70)){
      switch(sensor_No){
      case 0: SWP0=0;break;
      case 1: SWP1=0;break;
      case 2: SWP2=0;break;
      case 3: SWP3=0;break;
     }
     
     if(avg_count<2){
     avg_count++;
     }else avg_count=0;
     
     if(avg_count==2)Last_frequency[sensor_No]=Last_frequency[sensor_No]+((long)current_frequency-(long)Last_frequency[sensor_No])/4;
     
     }
     TMR1L=0;
     TMR1H=0;
     TMR0=0;
     PIR1.TMR1IF=0;
  }else {
  TMR1L=0;
     TMR1H=0;
     TMR0=0;
     PIR1.TMR1IF=0;
  }
}

void main() {

TRISA=0x00;
ANSELA=0x00;
SWP0=0;//Switch is not pressed
SWP1=0;//Switch is not pressed
SWP2=0;//Switch is not pressed
SWP3=0;//Switch is not pressed

first_Read=0;//No first read has done.

//reset all outputs
AP0=0;
AP1=0;
AP2=0;
AP3=0;

//Enable Capcitive sensing module
CPSCON0.CPSON=1;
CPSCON0.CPSRNG1=0;
CPSCON0.CPSRNG0=1;
CPSCON0.T0XCS=1;
OPTION_REG.T0CS=1;

CPSCON1=0x00;//Enable CPS0 channel.at RB0

TRISB=0x00;
TRISB.B0=1; //set RB0 as input as it is capacitive input.
TRISB.B1=1;
TRISB.B2=1;
TRISB.B3=1;
ANSELB=0x00;
ANSELB.B0=1;//set ANSELB.B01=1 to enable analog input on RB0 pin.It is required in capacitive sensing.Don't know why!
ANSELB.B1=1;
ANSELB.B2=1;
ANSELB.B3=1;


//Initialize Timer1 for interrupts to scan cap sensors
TMR1IE_bit=1;
PEIE_bit=1;
GIE_bit=1;
TMR1IF_bit=0;
// Timer1 Registers: Prescaler=1:1; TMR1 Preset=0; Freq=76.29395Hz; Period=0.0131072 s
T1CON.T1CKPS1 = 0; // bits 5-4 Prescaler Rate Select bits
T1CON.T1CKPS0 = 0; // bit 4
T1CON.T1OSCEN = 0; // bit 3 Timer1 Oscillator Enable Control: bit 1=on
T1CON.T1SYNC = 1; // bit 2 Timer1 External Clock Input Synchronization Control bit:1=Do not synchronize external clock input
T1CON.TMR1CS0 = 0; // Timer 1 clock source is FOSC and not FOSC/4
T1CON.TMR1CS1 = 0; // Timer 1 clock source is FOSC and not FOSC/4
T1CON.TMR1ON = 1; // bit 0 enables timer
TMR1H = 0; // preset for timer1 MSB register
TMR1L = 0; // preset for timer1 LSB register
TMR0=0;

while(1){

  ///below for each SWPx bit that respective AP(toggle its state)
   if(SWP0){
    AP0=~AP0;
    SWP0=0;//reset this flag
   }
   
   if(SWP1){
    AP1=~AP1;
    SWP1=0;//reset this flag
   }
   
   if(SWP2){
    AP2=~AP2;
    SWP2=0;//reset this flag
   }
   
   if(SWP3){
    AP3=~AP3;
    SWP3=0;//reset this flag
   }

};

}


So where am I making mistake? Any help would be helpful.
MVA
 
Posts: 1
Joined: Fri Jul 21, 2017 4:00 am
PIC experience: Experienced Hobbyist

Return to Other PICmicro topics

Who is online

Users browsing this forum: No registered users and 12 guests

cron