PDA

View Full Version : 16F726 Capacitive sensing module



Byte_Butcher
- 13th February 2009, 18:31
Well here I am... stuck again.

I'm trying to learn how to use the capacitive sensing module on the 16F726.

My first problem seems to be getting the sensing oscillator running.

I've been through the CSM section (14.0) of the data sheet and I've read AN1171 (Using the Capacitive Sensing Module on the PIC16F72X)

According to AN1171, once I've set the appropriate registers the oscillator should start up. At this point I would expect to see the oscillator running on my chosen sensor pin... right?

I've got my 'scope on pin 21 (RB0/AN12/CPS0/INT) of the PIC but I don't see anything except a few millivolts of 60 cycle hum. It just looks like a high impedance input with no oscillator running.

Shouldn't this be all it takes to get the CSM oscillator running on CPS0 (pin21) ?


'************************************************* ***************

Include "MODEDEFS.BAS" ' Include Shiftin/out modes

@ __config _CONFIG1, _DEBUG_OFF & _PLL_EN & _BORV_2_5 & _BOR_ON & _CP_OFF & _MCLRE_OFF & _PWRT_EN & _WDT_OFF & _INTOSCIO
@ __config _CONFIG2, _VCAP_RA0

OSCCON = $10 'set oscillator to 4 Mhz

TRISA= %11111111 'Set 'em all to inputs
ANSELA= %11111111 ' Set all pins to analog...

TRISB= %11111111 'all input
ANSELB= %11111111 'all analog

TRISC= %00000000 'Set portC all outputs

CPSCON0 = %10001101 'Cap sense on, high range oscillator
CPSCON1 = %00000001 'Cap sense channel input 0 is selected


Could someone please point me in the right direction?

Thanks!

Steve

Byte_Butcher
- 12th March 2009, 00:10
I'm trying to learn to use the Capacitive Sensing Module (CSM) on the PIC16F727. I've had some minor success getting the CSM set up and running, and with reading the count from TMR1 to an LCD module.

I'm using (trying) Darrel's Instant Interrupts to run an ISR when TMR2 matches PR2, but I clearly don't understand what I'm doing yet...

Here's the part that works so far:
I've got the CSM oscillator running and I can see the triangle wave on pin B0. I've got a wire and "touchpad" connected to it, and when I touch the pad the oscillator slows way down, so that part is working great.


Here's what I'm *trying* to do at this point :

Timer1 is used to count pulses on the cap sensing oscillator. It is set up so that Timer2 controls the gate of Timer1 and starts/stops the Timer1 counter.

Timer2 counts until it matches the value in the PR2 register, then stops Timer1 and triggers an interrupt.

The ISR reads the count in the Timer1 register and stores it in a variable called "timercount", then it resets the registers to 0, resets Timer2 to 0, clears the Timer2 interrupt flag, and restarts the timers.

The main loop is supposed to read the contents of "timercount" and display it on an LCD so I can read the change in timercount when a finger touches the sensing pad.


Here's the problems I'm having (so far):

First, the Interrupt seems to "steal the show" and the program never enters the main loop and displays the data on LCD, UNLESS I put a "goto Main" inside the ISR routine. Then it will display my value on the LCD.

Second, the count in TMR1 seems to be entirely dependent on the length of the "pause" in the main loop. With 100mS pause the timer reads about 15,000 counts, with a 200mS pause it reads about 29,000 counts. What's up with that? The ISR zeros the timers each time through.

I've read sections 11-14 (using the timers and CSM) of the 16F727 datasheet (41341B.pdf) *repeatedly*, as well as AN1103 and AN1171 which explain using the CSM in the 16F727. Hey, I even managed to make Darrels "Blinky light" interrupt example work for me, but alas, I seem unable to pull it all together and make the touch sensor routine work. I figured I'd start by reading the count in TMR1 to an LCD so I can see what's happening..

I've been hammering away at this for quite a while and starting to feel rather lost.

Here's the code I've got so far if someone would *please* be so kind as to take a look and offer advice..



'-------------------------------------------------------------------------------
'Trying to learn to use the Capacitive Sensing Module on a 16F727 --------------
'-------------------------------------------------------------------------------

@ __config _CONFIG1, _DEBUG_OFF & _PLL_EN & _BORV_2_5 & _BOR_ON & _CP_OFF & _MCLRE_OFF & _PWRT_EN & _WDT_OFF & _INTOSCIO
@ __config _CONFIG2, _VCAP_RA0

Include "MODEDEFS.BAS" ' Include Shiftin/out modes
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts

DEFINE LCD_DREG PORTA ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTA ' Set LCD Register Select port
DEFINE LCD_RSBIT 2 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTC ' Set LCD Enable port
DEFINE LCD_EBIT 0 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE ADC_BITS 8 ' Set number of bits in ADC result
DEFINE ADC_CLOCK 3 ' Set clock source for ADC (rc = 3)
DEFINE ADC_SAMPLEUS 100 ' Set ADC sampling time in microseconds
DEFINE OSC 4

OSCCON = $10 'set oscillator to 4 Mhz

TRISA= %00000000 'Set 'em all to outputs
ANSELA= %00000000 'Set 'em all to digital
TRISB= %11111111 'all input
ANSELB= %11111111 'all analog
TRISC= %00000000 'Set portC all outputs

CPSCON0 = %10001101 'Cap sense on, high range oscillator
CPSCON1 = %00000000 'Cap sense channel input 0 is selected

'-----Alias Pins
RW var PORTC.3 'Read/Write line for the LCD

'-----Allocate Variables
timercount var word ' A place to store the count from TMR1

'-----Set up Interrrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR2_INT, _CheckCount, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR2_INT ; enable Timer 2 interrupts



low rw 'LCD Read/Write line low (write)
Pause 200 'Let the LCd wake up
lcdout $fe, 1 'Clear LCD

'----- Timer Setup
T2CON.2 = 1 'TMR2 on
T2CON.0 =1 'adjust prescaler
PR2 = $B4 ' w/prescale=1:1, $B4 sets 125us scan rate. '= 10110100
PIR1.1 = 0 'Clear the TMR2 interupt flag
PIE1.1 = 1 'Turn TMR2 interrupt enable on
T1CON = %11010101 'clock=CAPOSC, prescale=1:2, dedicated OSC disabled, no external clock synchronize, timer on
T1GCON = %11100010 'Timer1 gate init/ Toggle Mode
PIR1.7 = 0 'Clear Gate Interrupt Flag
PIR1.1 = 0 'clear the TMR2 interupt flag
PIE1.7 = 1 'Enable Gate Interrupt

Goto main 'Just get it going...

'---[TMR2 - interrupt handler]--------------------------------------------------
disable 'I think I need to kill the interupts here..?
CheckCount:
T2CON.2 = 0 'stop timer2
T1CON.0 = 0 'stop timer1
timercount = TMR1L + TMR1H << 8 'stuff the contents of the timer register into a word
TMR1L = 0 'reset counter to 0...
TMR1H = 0 'upper 1/2 too
TMR2 = 0 'rest timer 2
PIR1.1 = 0 'Clear TMR2 Interrupt Flag
T1CON.0 = 1 'restart timer1
T2CON.2 = 1 'restart timer2
' gosub main 'if I don't add this, I never seem to get out of the interrupt and return to the main routine...
@ INT_RETURN
enable 're-enable interrupts

'----Main loop-----------------------------------------------------------
Main:
LCDOUT $fe,2, " Count= ", dec timercount," ",$fe,$C0," TMR2 = ", dec timertemp," "
pause 100 'changing the duration of the pause also changes the count on timer1. Why?
return

GOTO Main

end



Thanks very much,

Steve

Darrel Taylor
- 12th March 2009, 01:47
I've never used the touch sensor thingy's, but here's a couple items that will be causing problems.


You've enabled TMR1GIE (PIE1.7), but there isn't a handler for it.
Don't think you really need it anyway if TMR2 is handling the gate, and creating an interrupt at the same time.
&nbsp;
There is a return in your Main loop. Very Bad!
&nbsp;

Byte_Butcher
- 12th March 2009, 03:57
Ahhh, thanks Darrel... where would this forum be without you! No problem too large or small. :)

I don't know what happened with the return inside my main loop... Bad late night cut & paste I guess. Thanks for pointing that out!

About TMR1GIE (PIE1.7)...
I've gone back and re-re-re-read section 12.6 (and figure 12-6) about the timer1 gate and "toggle mode" again, and also the "Timer 2 Time Base Setup" section of AN1171, and a few things are starting to make more sense... and it appears that the interrupt I want to watch is NOT the TMR2 to PR2 match, it's the Timer 1 Gate Event Interrupt , "TMR1GIF"(PIR1.7) . That explains some of the other weird results I've had.

I don't see the "Timer 1 Gate Event Interrupt" listed in the Available Interrupt Sources on your website Darrel. Is there a way for me to add that to the selection so i can use TMR1GIF with "Instant Interrupts"?

Thanks very much for your help! Hopefully I'll be able to get the Touch Sensor thing figured out and be one of the first to post a chunk of working code for it.


Steve

Darrel Taylor
- 12th March 2009, 04:34
I don't see the "Timer 1 Gate Event Interrupt" listed in the Available Interrupt Sources on your website Darrel.
Yeah, it's not in there.

But it's not too hard to add it to the DT_INTS-14.bas file....

ASM
#define TMR1GATE_INT PIR1,TMR1GIF ;-- Timer1 Gate Interrupt
#define INT_INT INTCON,INTF ;-- INT External Interrupt
#define RBC_INT INTCON,RBIF ;-- RB Port Change Interrupt
#define TMR0_INT INTCON,T0IF ;-- TMR0 Overflow Interrupt 16F
#define TMR1_INT PIR1,TMR1IF ;-- TMR1 Overflow Interrupt
...

and
GetIntInfo macro IflagReg, IflagBit

Found = NO
; nolist
ifdef TMR1GIF ;----{ TMR1 Gate Interrupt }---------------[PIR1, TMR1GIF]---
INT_Source PIR1, TMR1GIF, PIE1, TMR1GIE
endif
ifdef INTF ;----{ INT External Interrupt }----------------[INTCON, INTF]---
INT_Source INTCON, INTF, INTCON, INTE
endif
ifdef RBIF ;----{ RB Port Change Interrupt }--------------[INTCON, RBIF]---
...
<hr>
Then in your program's interrupt definition ...
'-----Set up Interrrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1GATE_INT, _CheckCount, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1GATE_INT ; enable Timer1 Gate interrupts

Good Luck!

AMay
- 12th March 2009, 16:13
I made a capacitor checker using a 16F84A which works very well within limits. It uses the pot command. The code in PICBasic (not Pro) is:

' Capacitor Measurement
' Four digit common anode mulitplexed display
' Scan about 60/s (4ms pause)
' Driver 74HC4511
' Works for 2.0 uf (1K)- 100pf (20K)
' 8/20/06
' For 16F84A Chip
' Data output port A (Pin A5 NC)
' Pins 1 - 4 - Digit select for multiplex
' Pin5 - pot command
' Pin6 - Display Blanking signal (0 = blank)
' Pin7 - Range 1 = high value (1K resistor); 0 = low (20K)
' Digits 1 - 4; W1 - W4
' Measurement (Msr) W10
' Note that scan must be 60/s, and 1ms on + 3ms off shows no flicker, but
' leds are dim. 2ms on & 2ms off works well.
Settings:
Symbol Blank = pin6
Symbol Range = pin7
Symbol D1 = w1
Symbol D2 = w2
Symbol D3 = w3
Symbol D4 = w4
Symbol Msr = w10
Symbol PortA = 5
Poke $85, 0 ' Set port A to all outputs
Output 1 ' Digit 1 - MSD
Low 1 ' off
Output 2 ' Digit 2
Low 2
Output 3 ' Digit 3
Low 3
Output 4 ' Digit 4
Low 4
Output 6 ' Blanking
Low 6 ' Blank all segments


Start:
pause 750
Blank = 0
If range = 0 then testlow 'Check high or low state

'Testhigh:
pot 5,40,msr
Msr = Msr*10 'Raise results for 4 digit display
goto math

Testlow:
Pot 5,255, msr
Msr = Msr*100

Math: 'Set up digits in memory for display
D1 = Msr/1000
D4 = Msr//1000
D2 = D4/100
D4 = D4//100
D3 = D4/10
D4 = D4//10

Display:
poke porta, D1 'Send data
High 1 'Select Digit
Blank = 1 'Remove blanking
Pause 2 'Pause
Blank = 0 'Blank
Low 1 'Unselect digit
'Pause 2 'Pause again to save battery

poke porta, D2
High 2
Blank = 1
Pause 2
Blank = 0
Low 2
'Pause 2

poke porta, D3
High 3
Blank = 1
Pause 2
Blank = 0
Low 3
'Pause 2

poke porta, D4
High 4
Blank = 1
Pause 2
Blank = 0
Low 4
Pause 2
Goto display
end

Byte_Butcher
- 12th March 2009, 16:14
Bingo!
I changed my interrupt from TMR2/PR2 match to TMR1 gate event and it's working beautifully now. The count on the LCD now accurately reflects what's going on with the CSM oscillator.

Thanks so much for posting the necessary modifications to DT_INTS-14.bas.
I actually opened that file and had a look just before bed last night and had pretty much figured out to do the modifications you posted. Thanks for confirming it for me.

It looks like I need to adjust the TMR2 prescaler a bit to maximize the number of counts in the period, but it's working great now and the next thing to do is set up the averaging and "button pressed" detection routine but I think that should be pretty easy, even for me.

I'll post code when I've got it working well. I'm rather surprised no one here has played with the Touch Sensor module on the 16F726/7 yet....
I spent hours searching the archives and came up with a big zero.

Thanks again Darrel!

Byte_Butcher
- 12th March 2009, 16:19
Thanks AMay,
The capacitance checker may come in handy for me some time.

But what I'm working on isn't a capacitance meter, it's the Capacitive Sensing Module in the PIC 16F726/7's.

It's used to make capacitive "Touch Sensors" that detect a human finger without any buttons, just a simple conductive pad.

I think Darrel has got me up and running now.

Byte_Butcher
- 18th March 2009, 14:51
OK, I was gonna sit on this for a few more days until I had a chance to perfect it a little more, but here it is now in it's crude form. I'm sure it needs lots of fixing to be "good" code, but it's functional as is and hopefully will give a starting place for folks who want to play with the capacitive sensing module on the 16F72X PIC's. Please feel free to critique it and fix it up. I need the education...

This program sets up Capacitive Sensing pin0 (CPS0/RB0) on the 16F726 / 16F727 to be a "Touch Sensor" pin
When the sensor pad is touched, the raw count (from TMR1) will drop below the running average and a LED on PORTA.1 will flash. If the finger is held on the pad long enough, eventually the running average will catch up with the current value and the LED will turn off.

Relevant Data Sheets for the CSM module include:

http://ww1.microchip.com/downloads/en/DeviceDoc/41341B.pdf 16F72X / 16LF72X Data Sheet.
http://ww1.microchip.com/downloads/en/AppNotes/01101a.pdf AN1101 "Introduction to Capacitive Sensing "
http://ww1.microchip.com/downloads/en/AppNotes/01103a.pdf AN1103 'Software Handling for Capacitive Sensing"
http://ww1.microchip.com/downloads/en/AppNotes/01171B.pdf AN1171 "Using the Capacitive Sensing Module on the PIC16F72X"

Crude Code follows.... Enjoy!

Steve

------------



'-------------------------------------------------------------------------------
'Trying to learn to use the Capacitive Sensing Module on a 16F727 --------------
'-------------------------------------------------------------------------------

@ __config _CONFIG1, _DEBUG_OFF & _PLL_EN & _BORV_2_5 & _BOR_ON & _CP_OFF & _MCLRE_OFF & _PWRT_EN & _WDT_OFF & _INTOSCIO
@ __config _CONFIG2, _VCAP_RA0

Include "MODEDEFS.BAS" ' Include Shiftin/out modes
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts

DEFINE LCD_DREG PORTA ' Set LCD Data port
DEFINE LCD_DBIT 4 ' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_RSREG PORTA ' Set LCD Register Select port
DEFINE LCD_RSBIT 2 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTC ' Set LCD Enable port
DEFINE LCD_EBIT 0 ' Set LCD Enable bit
DEFINE LCD_BITS 4 ' Set LCD bus size (4 or 8 bits)
DEFINE ADC_BITS 8 ' Set number of bits in ADC result
DEFINE ADC_CLOCK 3 ' Set clock source for ADC (rc = 3)
DEFINE ADC_SAMPLEUS 100 ' Set ADC sampling time in microseconds
DEFINE OSC 8

OSCCON = $10 'set oscillator to 8 Mhz

TRISA= %00000000 'Set 'em all to outputs
ANSELA= %00000000 'Set 'em all to digital
TRISB= %11111111 'all input
ANSELB= %11111111 'all analog
TRISC= %00000000 'Set portC all outputs

CPSCON0 = %10001101 'Cap sense on, high range oscillator
CPSCON1 = %00000000 'Cap sense channel input 0 is selected

'-----Alias Pins
RW var PORTC.3 : LOW rw 'Read/Write for LCD
LED var PORTA.1 'LED to display when button is pressed

'-----Allocate Variables
timercount var word ' raw count from TMR1
timerave var word ' long term average of timercount
AvgCount var word : AvgCount = 32 'number of samples to average

'-----Set up Interrrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1GATE_INT, _CheckCount, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1GATE_INT ; enable Timer 2 interrupts

High LED
Pause 200 'Let the LCd wake up
lcdout $fe, 1 'Clear LCD
lcdout $fe, 2, " Awake! "
pause 500

'----- Timer Setup
T2CON = %01110110 'bit7=unimplemented, bit6-3=postscaler, bit2=TMRON, bit1-0=prescaler
PR2 = %11111111 'give PR2 a number for TMR2 to match
PIR1.1 = 0 'Clear the TMR2 interupt flag
PIE1.1 = 1 'Turn TMR2 interrupt enable on
T1CON = %11000101 'Timer clock source=CAPOSC, prescale=1:1, dedicated OSC disabled, no external clock synchronize, timer on
T1GCON = %11100010 'Timer1 gate init/ Toggle Mode
PIR1.7 = 0 'Clear Gate Interrupt Flag
PIR1.1 = 0 'clear the TMR2 interupt flag

Goto main 'Just get it going...

'---[TMR2 - interrupt handler]--------------------------------------------------
disable
CheckCount:
T2CON.2 = 0 'stop timer2
T1CON.0 = 0 'stop timer1
timercount = TMR1L + TMR1H << 8 'stuff the contents of the timer register into a word
Gosub Fingercheck

TMR1L = 0 'reset counter to 0...
TMR1H = 0 'upper 1/2 too
TMR2 = 0 'rest timer 2
PIR1.1 = 0 'Clear TMR2 Interrupt Flag
T1CON.0 = 1 'restart timer1
T2CON.2 = 1 'restart timer2
@ INT_RETURN
enable

'----Average the timercount result----------------------------------------------

Fingercheck:
timerave = timerave - (timerave/AvgCount) 'average the count so you have a reference to compare....
timerave = timerave + (timercount/AvgCount) '...with yimercount

If timerave - (timerave /40) > timercount then 'If timercount drops more than 2.5% below the average, signal that a button is pressed.
low LED 'make the LED do a little dance.
pause 50
High LED
pause 25
endif

If timercount > timerave +50 then 'do a "fast recovery" on the average when finger is removed.
timerave = timercount
endif
return

'----Main loop-----------------------------------------------------------
Main:
LCDOUT $fe,2, " Count= ", dec timercount," ",$fe,$C0,"Average = ", dec timerave," "
pause 50
GOTO Main

end

gmglickman
- 4th May 2010, 19:55
Anybody else working with capacitive sensing? Any updates?

rmteo
- 4th May 2010, 20:47
I have used capacitive sensing in a handheld terminal with a graphic LCD. It scans 24 keys (although it will handle up to 32 keys) and does require a special MCU - I'm using a PIC18F44K20. Does auto-repeat, audible feedback, etc.
43744375

Bruce
- 5th May 2010, 00:48
Nice looking project rmteo. Do you have a PBP example for it?

rmteo
- 5th May 2010, 01:32
The project was done in SF BASIC for a client so I cannot go into too much detail. As for the capacitive touch part, the keyboard is implemented as PCB copper pads on the top side (see picture). Each of the 24 pads is routed through a pair of 16-to-1 multiplexers (74HCT4067) to act as the timing capacitor to a TS555 (CMOS version of 555) timer running at about 2MHz in astable mode.

A timer in the PIC is set up as a counter. It counts the number of pulses in a fixed time frame (I use 2 ms). When a pad is touched, its capacitance increases thereby lowering the frequency (lesser pulse count) of the TS555. You will typically see 10-15% change when a key is touched. Because the capacitance can (and will) drift due to temperature (and the fact that each key will have a slightly different capacitance due to trace length, etc.), you will need to employ some algorithms to ensure accurate readings. There is an app note on the MC website that describes this.

The nice thing about this method is that you can use any PIC - it does not need to have a capacitive sense module to work and uses fewer I/O pins. I implemented a similar scheme using the ARM Cortex M0/M3 but the same principle can be applied to work with just about any microcontroller.

4376

Bruce
- 5th May 2010, 16:44
Good looking unit you made there. Nice work. I guess i'm going to have to start playing a bit with cap sensing on the 16F1827 here shortly...:rolleyes:

rsocor01
- 5th May 2010, 17:05
rmteo,

Nice project. I have a project using CSM (capacitive sensing module) on a 16F727. In that project I'm using only two buttons. Yes, you can do it with any PIC but you will need some extra external components.

How did you do the external plastic cover for the buttons? Was it custom made by some company?

Robert

rmteo
- 5th May 2010, 17:40
I used a clear acetate (0.012in.thick) overlay for the buttons. This way, the end user can change legends by printing their own labels on paper using an ink-jet printer. This is one of the nice features of a capacitive switch - you don't have to spend a lot of money for custom labels (and the attendant lead times). And you can change labels easily and cheaply at any time. There is a downside though - there is no feedback (like tactile with a mechanical switch). I implemented an audible click using a buzzer like this one, which is also used for alarms, etc.

http://media.digikey.com/photos/Soberton%20Photos/WST-1203UX_sml.jpg

rsocor01
- 6th May 2010, 18:44
I used a clear acetate (0.012in.thick) overlay for the buttons. This way, the end user can change legends by printing their own labels on paper using an ink-jet printer.


Nice! Now, that is one more item for my "To Buy List".

Robert

rmteo
- 6th May 2010, 18:55
I got the material from a local office supply place - OfficeMax. It is the clear stuff used as covers for book bindings.

Normnet
- 7th May 2010, 04:09
I have been using capacitive touch switches for several years with little problem except the
Q prox chips became obsoleted after a couple of years.

Any Microchip can be used as the requirements are unbelievably simple:
An I/O pin to charge with supply voltage and an AD pin to read the cap sense value.

I sometimes take 20 to 100 readings, bubble sort them highest to lowest, then average
only array elements 20% to 80% to to remove any errant readings.
The outcome is stable, varies only one or two at 8 bit.
The AD needs to be coded for power conservation however.

The following code is derived almost directly from AN1286: (http://ww1.microchip.com/downloads/en/AppNotes/01286A.pdf)

'PIC18F2520
subLOAD_AD_ARRAY:
ADCON0 = %00000001 'ENABLES AD
For i = 0 To 99
LOW PORTA.0
LOW PORTA.2
ASM
NOP
ENDASM
TRISA.0 = 1 'INPUT
HIGH PORTA.2
ASM
NOP
ENDASM

'AD BY REGISTER'S
ADCON0.1 = 1 ' START AD GO/DONE BIT
While ADCON0.1 = 1 : Wend ' AD ENDED GO/DONE Bit
wAD.LowByte = ADRESL ' 2520 10 BIT AD ONLY
wAD.HighByte = ADRESH
yAD_ARRAY100[i] = wAD >> 2
Next
ADCON0 = %00000000 'DISABLE AD
Return

The touch button is simply a 3/16" stainless steel machine screw through the faceplate with
a double nut tightened around a soldered wire loop connected to the AD.
I add a little grommet for looks.
The charge lead is simply wound several times around the screw behind the faceplate.

Another version is individual metal tabs of sheet metal adhered to the underside of the
enclosure for buttons.
The AD wire is soldered to each tab and the charge wire only needs to wrap around the
AD wire or all AD wires.

The cap sensor readings can vary over time and the base line to compare the readings against
should be re zeroed and a new max value redetermined at regular intervals.

I laminate an inkjet photo quality paper (not photo paper) printout for the faceplate.

The last consideration is ESD.
A simple 100k resistor in line on both leads is a good solution.

Norm

Ioannis
- 7th May 2010, 08:41
Hi Norm.

I think you can shorten your code by Left justify the AD results and take only the ADRESH. Same as with the lines:



wAD.LowByte = ADRESL ' 2520 10 BIT AD ONLY
wAD.HighByte = ADRESH
yAD_ARRAY100[i] = wAD >> 2


Ioannis

rsocor01
- 7th May 2010, 12:48
Norm,

There are many ways to do it. You can also use the interrupt TMR1 to detect changes in the output frequency due to a pad being touched by a finger. This is explained in AN1101 "Introduction to Capacitive Sensing".

http://ww1.microchip.com/downloads/en/AppNotes/01101a.pdf



The following code is derived almost directly from AN1286: (http://ww1.microchip.com/downloads/en/AppNotes/01286A.pdf)

I see that you are using AN1286 "Water-Resistant Capacitive Sensing". If you are using your touch sensors in a wet environment, then you might want to consider using inductive sensors. Take a look at the table I attached to this post.

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2694&param=en538303

4378

Robert

George
- 31st August 2010, 03:21
I'm trying to use capacitive touch too - was kinda hoping that the inbuilt capacitive sensing was a bit more straight forward than the convoluted mess and complexity it looks like. Would it be too hard for microchip to make it a bit user friendly so you just enable named pins as capacitive, then read the register to see which were pressed and had inbuilt filtering etc??

I've used Mister E's capacitive touch idea before and it seems so much simpler than the "integrated' solution.

Anyrate - enough of my ramblings, I'd like to learn to use it - hopefully it's not as complex as it appears from outset. I've copied byte butchers code as above and pasted it directly into MCS and I have errors all over the place. I have a fresh install of PBP2.6 and have also just downloaded DTs' ints-14.

How come it works for him and not for me? I had the chip type 16F726 like his also

While I'm on a roll, why wont MCS allow you to copy and paste the error list???

I think many of the issues come from the Interrupt routine but asm and interrupts are well over my head. Is there any reason Byte Butcher used interrupts rather than just checking pins periodically?

Thanks

Error[118]c:\pbp...asm 213 : Overwriting previous address contents (2007)
Error[101]c:\pbp...asm 342 : ERROR: (wsave variable not found)
Error[101]c:\pbp...asm 308 : ERROR: (" Add:" wsave VAR BYTE $20 SYSTEM)
Error[101]c:\pbp...asm363 : ERROR: (Chip has RAM in BANK1, but WSAVE was not found)
Error[101]c:\pbp...asm315 : :ERROR: (" Add:" wsave VAR BYTE $A0 SYSTEM)
Error[128]c:\pbp...asm 989 : Missing argument(s)
Error[101]c:\pbp...asm672 : ERROR: ("INT_Handler" - Interrupt Flag (FlagReg,FlagBit) not found)
Error[128]c:\pbp...asm 1000 : Missing argument(s)
Error[101]c:\pbp...asm 672 : ERROR: (INT_ENABLE" - Interrupt Flag ( FlagReg,FlagBit) not found)

rsocor01
- 31st August 2010, 04:42
I think many of the issues come from the Interrupt routine but asm and interrupts are well over my head. Is there any reason Byte Butcher used interrupts rather than just checking pins periodically?

He used interrupts because that is the way to do it. You need to count the number of pulses in the signal for a fixed amount of time and determine if the switch has been touched or not. This app note might help you to understand the basics of CSM

http://ww1.microchip.com/downloads/en/AppNotes/01101a.pdf

Robert

Ioannis
- 31st August 2010, 07:54
Don't you have to do better things?

Seriously now, I mean it, while the timers do their jobs, that is to count, you can do many other tasks in your program.

That is why the so hated interrupts are needed.

As for your errors, do post your code. Do you need help or guesses?

Ioannis

HankMcSpank
- 31st August 2010, 10:00
I experimented with capacitive touch on a 16f690, my related thread about it here (you might glean some stuff from it)...

http://www.picbasic.co.uk/forum/showthread.php?t=12196

My (short!) youtube video of the end result here (using a guitar's scratchplate screw's 'head', as a 'toggle switch')...

http://www.youtube.com/watch?v=SNeSzgY2234

Re the process itself...it might initially seem a lot to swallow (especially if it's your first sortie using interrupts - which are pretty much essential for capacitive touch), but like everything else, if you break it down into smaller 'building blocks' and approach each block one at a time, then it becomes much more digestible.

You obviously need to get the relaxation oscillator working first - an oscilloscope is *extremely* useful to make sure this is working (& getting it working proved to be the most troublesome part for me....there's a whole heap of registers that need to be set 'oh so right', once I got it running, I was off to the races).

re those wsave errors you're seeing when compiling - you need to comment out some lines in the DTS_INTS-14.BAS (search on the error wsave VAR BYTE $20 SYSTEM on this forum to find out what needs doing!)

Ioannis
- 4th December 2011, 22:19
Finally I got my first touch demo working with 16F1827 chip. The CSM module is easy to use and makes program small enough.

But, I have one problem with the stability of the output that shows whether one is touching, close to touch or not touching at all.

Although I have included Darrel's Average routine there is a grey region that makes deciding if one is touching not very clear.

The following test code has a LED indicator to show when touch pad is really touched or not. If finger is very close, value is playing up or down the threshold and makes the LED indicator blink.



OPTION_REG = %10000110 'Tmr0 from 256 presc and Int Clock

T1CON = %11000001 '%00110000 ' TMR1 1:8 prescale, timer1 off

led var portb.4
value var word
AvgCount CON 32 ' = Number of samples to average
FAspread CON 10000 ' = Fast Average threshold +/-
ADavg VAR WORD
flag var bit
'Interrupt Engine Setup
'::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR0_INT, _Timer_0, PBP, yes

endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE TMR0_INT
ENDASM
'::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::

goto main

Timer_0:
t1con.0=0
vALUE.lowbyte=tmr1l:VALUE.highbyte=tmr1h
flag=1
tmr1l=0:tmr1h=0
t1con.0=1
@ INT_RETURN

main:
clear
pause 1000

start:
if flag=1 then
flag=0
gosub Average
endif

hserout [27,"[H",27,"[10;0H","Value is: ",#vALUE," "]

if VALUE<319 then
high led
else
low led
endif
goto start

Average:
IF Value = ADavg Then NoChange
IF ABS (Value - ADavg) > FAspread OR Value < AvgCount Then FastAvg
IF ABS (Value - ADavg) < AvgCount Then RealClose
ADavg = ADavg - (ADavg/AvgCount)
ADavg = ADavg + (Value/AvgCount)
GoTo AVGok
FastAvg:
ADavg = Value
GoTo AVGok
RealClose:
ADavg = ADavg - (ADavg/(AvgCount/4))
ADavg = ADavg + (Value/(AvgCount/4))
AVGok:
Value = ADavg ' Put Average back into Value
NoChange:
Return


Any ideas welcome.
Ioannis

mackrackit
- 5th December 2011, 01:45
Just a wild guess...

What if bit 6 of the T1GCON register is set to 0?

Darrel Taylor
- 5th December 2011, 04:45
Ioannis,

Try this modification to the averaging routine for the CSM.
http://www.picbasic.co.uk/forum/showthread.php?t=15468&p=107598#post107598

Ioannis
- 5th December 2011, 08:07
I wanted to correct minor mistakes in the comments of the code I posted but it is not possible. Can any of the moderators or Admins see the whole code? I cannot for sure (in the Edit Post mode).

Dave, I have not changed the T1GCON register which by default on Power up is reset to zero. I do not use the gate anyway.

Darrel, I missed that. Will try it an get back.

Thanks both,
Ioannis

HankMcSpank
- 5th December 2011, 21:34
I use the CSMs with great success without having to average.

I basically store away the last cap sense output reading (ie TMR1 count), take the present reading (the TMR1 count again) and just have the program calculate an ongoing 'trigger' threshold count (the threshold being the last TMR1 reading reading minus a certain percentage)

And then just code it along the lines of if the present reading just takenis less than the threshold (ie the last reading minus a preset percentage), then the sensor has been touched....set a flag variable.

There should be a huge amount of difference between the non touched count & the touched count ...I set my threshold at something like 30% and it trigger everytime.

One thing i've found helps greatly with CSM ...is to adjust the CSM oscillator settings & also the sample period so that you get a 'normal' reading in the 10,000->15,000 count ballpark.

Ioannis
- 5th December 2011, 23:06
Thanks Hank. Well, 30% seems too much to me. I have managed up to 16%...

Thanks Darrel too. Yes your suggestions did made alot of difference.

Ioannis

Ioannis
- 6th December 2011, 07:37
After some testing, it seems that with the modification Darrel suggested, it needs to touch very quickly to get a 'pressed=1' flag.

If you approach relatively slow the touch pad it won't get triggered. I may have to play with the constants in the CSM and average too.

But it made a very reliable system now.

Thanks for the tips.

PIC16f1827 with the internal CSM module makes it very easy to make a touch keyboard. Only a couple of registers to setup and you are ready.

Ioannis

HankMcSpank
- 6th December 2011, 16:16
Yes the deviation from the 'normal' (no finger nearby) CSM output count, is related to how long the sample period is vs how long you actually touch the sensor for.....also the physical composition of the sensor itself, and how moist your finger is!

So a quick touch might only see a 5% deviation from the normal count, whereas a long sensor press, will see the CSM output count plummet.

Darrel Taylor
- 6th December 2011, 16:30
If you approach relatively slow the touch pad it won't get triggered.
I think increasing the number of samples in the average will adjust that behavior.

Ioannis
- 6th December 2011, 19:30
OK, seems to work good now with these settings:

PIC chip : 16F1827
System clock : 32MHz
Timer0 Int's : From system clock every 8ms
Timer1 input : From CSM module
CSM setup : CPSCON0 = %10001100
CPSCON1 = %00000010
T1CON setup : %11000001
OPTION_REG : %10000111 Timer0 with /256 prescaller
AvgCount CON 16 ' = Number of samples to average (max 32)
FAspread CON 25

Now you may wonder why the average constants are low valued. Because the system clock is high enough, clocking everything too fast. But with these settings looks OK for the touch pad I am testing.

Ioannis

LakisFM1
- 14th March 2013, 15:30
Ioannis , geia !

Is it possible to post the modified optimized code for the 16F1827?

Thank you.
Lakis.

Ioannis
- 14th March 2013, 16:54
Geia Laki.

OK, it is over a year now. Hmm, where do I have this file?

Let me search a bit, OK?

Ioannis

Ioannis
- 14th March 2013, 22:37
OK, Here it is.

It makes use of Darrels Averaging and Interrupt routines.

Unfortunately I had not add comments and may be hard to follow this test code. Sorry about that.

Ioannis

LakisFM1
- 14th March 2013, 22:54
OK !
It is not so difficult to read.

Thanks again!
Lakis from Thessaloniki.

visnja30
- 15th May 2014, 19:40
Hi,
Is it possible to use A ByteBucher code on PIC16F724.

How to modified a Darrels Taylor file "DT_INTS-14.bas" with his red text on this thread.
When I open his file "DT_INTS-14.bas" ver 1.10 I dont see anywhere where I can put this code:

GetIntInfo macro IflagReg, IflagBit

Found = NO
; nolist
ifdef TMR1GIF ;----{ TMR1 Gate Interrupt }---------------[PIR1, TMR1GIF]---
INT_Source PIR1, TMR1GIF, PIE1, TMR1GIE

and


ASM
#define TMR1GATE_INT PIR1,TMR1GIF ;-- Timer1 Gate Interrupt

Can someone help me to use capacitive sensing on this pic

Best regards