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.
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
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.
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