Some problems occured when I used MCU for implementing capacitive sensing
I am using PIC16f722(http://www.kynix.com/Parts/3961321/PIC16F722A-E%2FML.html ) 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:
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]={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 if(current_frequency>(Last_Frequency[sensor_No]-trip[sensor_No]+194)){
//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 Capacitive 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;
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? Thanks for your help!