Attached is some of my code (without all the other stuff that nobody cares about) of the Capacitive Sensing Module (CSM) that I'm working on. My project is similar to Byte_Butcher's but I'm only using PBP. There is still some work to be done like having some arrays would be nice, but so far the touch pads work fine.
One of the differences that I can see between my program and Byte_Butchers is OPTION_REG.5. I have it set to one and Byte_Butcher's have it cleared. OPTION_REG.5 set to one means that the TMR0 clock source is the CPSOSC signal and if cleared means the clock source is the internal instruction cycle clock. It works either way because I have tried it. However, AN1171 "CSM using PIC16F72x" and the datasheet suggests to clear this bit, so I guess that would be the right thing to do.Code:'**************************************************************** '* DEFINING VARIABLES AND SETTING INITIAL VALUES * '**************************************************************** DEFINE OSC 4 'Define Oscillator to 4MHz I VAR WORD TRIP VAR BYTE STABILIZE_CSM VAR BYTE 'VARIABLE USED TO LET MCU STABILIZE CSM BUTTON VAR BIT START_PROGRAM VAR BIT 'ONLY USED AT START OF PROGRAM (=0 NO BUTTONS TOUCHED YET) RAW_0 VAR WORD RAW_1 VAR WORD AVERAGE_0 VAR WORD AVERAGE_1 VAR WORD LED_0 VAR PORTB.6 LED_1 VAR PORTB.7 TEST_VAR VAR BYTE STABILIZE_CSM = 2 'LET CSM RUN 2 TIMES BEFORE TAKING READINGS TRIP = 50 'TRIP USED AS (1/50)*(AVERAGE) LED_0 = 0 'LEFT BUTTON LED LED_1 = 0 'RIGHT BUTTON LED RAW_0 = 0 RAW_1 = 0 AVERAGE_0 = 0 AVERAGE_1 = 0 BUTTON = 0 'START WITH BUTTON 0 (LEFT) TEST_VAR = 0 '**************************************************************** '* CAPACITIVE SENSING MODULE INITIALIZATION * '**************************************************************** TRISA = %00000000 'Initialize ports as outputs ANSELA = %00000000 'Initialize as digital ports TRISB = %00010001 'Initialize PortB.0 and PortB.4 as inputs. ANSELB = %00010001 'Initialize CPS4 and CPS0 as analog inputs. TRISD = %00000000 'INITIALIZE ALL PORTS AS OUTPUTS ANSELD = %00000000 'INITIALIZE ALL PORTS AS DIGITAL PORTS TRISC = %10000000 'INITIALIZE RC7 AS INPUT (SERIAL RX) CPSCON0 = %10001111 'CAPACITIVE SENSING MODULE IS ON. OSCILLATOR IS IN HIGH RANGE. CPSCON1 = %00000000 'BITS 3-0, 0000= RB0/CPS0 IS THE CAPACITIVE INPUT CHANNEL. '**************************************************************** '* TMR0 TIME BASE SETUP * '* ENABLE TMR0 TIMER INTERRUPTS * '**************************************************************** OPTION_REG = %11100011 'Bit 2-0, 011= prescaler rate 1:16 (TMRO INTERRUPTS EVERY 4.096 mSec) INTCON = %01100000 'enable TMR0 interrupts. enables all unmasked peripheral interrupts T1CON = %11000101 'Timer1 initialization T1GCON = %11100001 'Timer1 gate init /Toggle Mode/TMR0 time base PIR1.7 = 0 'Clear Gate Interrupt Flag. Timer1 gate is active (TMR1GIF BIT) PIE1.7 = 1 'Disable the Timer1 Gate Acquisition complete interrupt (TMR1GIE BIT) TMR0 = 0 'TMR0 overflows every (256-TMRO)*(Prescaler rate)(4*(1/4)uS)=4096uSec. ON INTERRUPT GOTO ISR INTCON = %10100000 'Enable Interrupts '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '< MAIN PROGRAM > '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> START: '0= PROGRAM HASN'T STARTED YET. 1= PROGRAM STARTED ALREADY (TOUCH BUTTON DETECTED). START_PROGRAM = 0 WHILE START_PROGRAM = 0 PAUSE 1 WEND MAIN: FOR I = 1 TO 200 PAUSE 1 NEXT I GOTO MAIN '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '< INTERRUPT ROUTINE ISR > '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DISABLE 'Disable further interrupts ISR: T1CON.0 = 0 'Stop/Clears Timer1 before reading TMR1 IF BUTTON = 0 THEN RAW_0.BYTE0 = TMR1L : RAW_0.BYTE1 = TMR1H IF BUTTON = 1 THEN RAW_1.BYTE0 = TMR1L : RAW_1.BYTE1 = TMR1H IF STABILIZE_CSM <> 0 THEN STABILIZE_CSM = STABILIZE_CSM - 1 'RUN CSM 2 TIMES BEFORE TAKING A READING IF BUTTON = 0 THEN AVERAGE_0 = 0 IF BUTTON = 1 THEN AVERAGE_1 = 0 ENDIF 'STABILIZING AVERAGE IF RAW OVERSHOOTS DURING STARTUP. IF BUTTON = 0 THEN IF AVERAGE_0 > (RAW_0 + 600) THEN AVERAGE_0 = 0 ENDIF IF BUTTON = 1 THEN IF AVERAGE_1 > (RAW_1 + 600) THEN AVERAGE_1 = 0 ENDIF 'SIMPLE DETECTION. IF RAW < AVERAGE*(1-2.0%) IF BUTTON = 0 THEN IF RAW_0 < (AVERAGE_0 - (AVERAGE_0/TRIP)) THEN LED_0 = 1 PAUSE 500 LED_0 = 0 AVERAGE_0 = 0 'AVOIDS SECOND FALSE READINGS STABILIZE_CSM = 2 'HELPS STABILIZE CSM TO AVOID FALSE READINGS START_PROGRAM = 1 'ONLY USED AT START OF PROGRAM (=0 NO BUTTONS TOUCHED YET) BUTTON = 1 'SWAP BUTTON BIT CPSCON1 = %00000100 'CHANGE BUTTON CAPACITIVE INPUT CHANNEL ELSE AVERAGE_0 = RAW_0 CPSCON1 = %00000000 ENDIF ELSE IF RAW_1 < (AVERAGE_1 - (AVERAGE_1/TRIP)) THEN LED_1 = 1 PAUSE 500 LED_1 = 0 AVERAGE_1 = 0 'AVOIDS SECOND FALSE READINGS STABILIZE_CSM = 2 'HELPS STABILIZE CSM TO AVOID FALSE READINGS START_PROGRAM = 1 'ONLY USED AT START OF PROGRAM (=0 NO BUTTONS TOUCHED YET) BUTTON = 0 'SWAP BUTTON BIT CPSCON1 = %00000000 'CHANGE BUTTON CAPACITIVE INPUT CHANNEL ELSE AVERAGE_1 = RAW_1 CPSCON1 = %00000100 ENDIF ENDIF TMR1L = 0 'Reset Timer1 TMR1H = 0 T1CON.0 = 1 'Restart/Enable Timer1 (TMR1ON BIT) TMR0 = 0 'RESET TMR0 TO 0 INTCON.2 = 0 'Re-enable TMR0 interrupts. Bit 2, 0= clears overflow, 1= overflow ocurred RESUME 'Return to main program ENABLE 'Enable interrupts END ' End of program
Another difference between the two programs is CPSCON0.1. If set to 1 means the oscillator is sourcing current out of the pin and if cleared means the opposite. Again, It works either way but I don't know what would be the right way.
By experimenting with the program and displaying the different variables in the PC monitor through a serial connection I could come up with the above detection algorithm, which I can say it's pretty accurate (so far).
Finally, I want to say that testing this kind of CSM circuits on a breadboard (like I did) and using two adjacent pins on the MCU for CSM detection (like I also did) is not a very good idea. If you do that there will be some crosstalk interference between the two touch pads and touching one button will activate the other one. Apparently a breadboard is not good for this kind of circuits.
Robert




Bookmarks