|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
Initial CVD library for PIC 12LF1552 |
Posted: Sun Feb 09, 2014 4:50 am |
|
|
This is a basic library to use the hardware CVD functions on this chip.
Doesn't allow all options, but single or double sampling, with or without guard output(s).
Simple 'main' function to show it, and the include file with the driver:
Code: |
//main
#include <12LF1552.h>
#device ADC=10
#FUSES NOWDT //Watch Dog Timer disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#fuses NOMCLR //MCLR for I/O
#use delay(internal=16000000)
#include <caplib.c> //library
void main()
{
//demonstration of using the caplib library to sense capacitance on A0
int16 reading;
//Now configure the capacitor sense system
setup_guard(GUARD_BOTH); //double pins enabled
setup_sense(PIN_A0, ADC_CLOCK_DIV_16, CAPS4PF, DOUBLE_SAMPLE);
//reading PIN_A0 - double sampled, 4pF extra internal capacitance
port_a_pullups(0b00001000); //anabling pull-up on A3 only
delay_us(10); //ensure MCLR pin has settled.
while (TRUE)
{
delay_ms(20); //50 reading per second approximately.
reading=cap_sense();
//reading drops with extra capacitance
//do what you want with the value here....
}
}
|
Now the actual drive code 'caplib.c'.
Code: |
//code for using the hardware cvd, on PIC12LF1552
//Configuration defines
#define GUARD_OFF 0 //guard disabled
#define GUARD_A5 1 //Single fuard from pin A5
#define GUARD_BOTH 2 //Twin guard, second inverted
//Guard ring control
//These cover the three most likely configurations....
#define PRECHARGE 10 //Times for precharge and acquire - adjust as required
#define ACQUIRE 10 //In instruction cycles 0 to 127
//Times
#define CAPS0PF 0
#define CAPS4PF 1
#define CAPS8PF 2
#define CAPS12PF 3
#define CAPS16PF 4
#define CAPS20PD 5
#define CAPS24PF 6
#define CAPS128PF 7 //Valsue to select extra internal capacitance
//Capacitances
#define AD_OUT 16
#define AD_OUT_OVERRIDE 8
//enable the ADOUT pin, and override
#define POLARITY_HIGH 64
#define POLARITY_LOW 0
//select the charging polarity - only supporting internal pre-charge
#define SINGLE_SAMPLE 0
#define DOUBLE_SAMPLE 1
//select between performing single sample, and automatic double sample
//Default this to inverted polarity
//several options ignored here since not needed for typical application...
//register definitions
#byte aadcon0=getenv("SFR:AADCON0")
#byte aadcon1=getenv("SFR:AADCON1")
#byte aadcon2=getenv("SFR:AADCON2")
#byte aadcon3=getenv("SFR:AADCON3")
#byte aadstat=getenv("SFR:AADSTAT")
#byte aadpre=getenv("SFR:AADPRE")
#byte aadacq=getenv("SFR:AADACQ")
#byte aadgrd=getenv("SFR:AADGRD")
#byte aadcap=getenv("SFR:AADCAP")
#byte aadres0l=getenv("SFR:AADRES0L")
#byte aadres0h=getenv("SFR:AADRES0h")
#byte aadres1l=getenv("SFR:AADRES1L")
#byte aadres1h=getenv("SFR:AADRES1h")
//now bits
#bit ADON=aadcon0.0
#bit GO=aadcon0.1
void setup_guard(int8 rings)
{
//routine to setup the guard rings
switch (rings)
{
case GUARD_OFF:
//disable guard rings
aadgrd=0;
output_float(PIN_A5);
output_float(PIN_A4);
break;
case GUARD_A5:
//single ring driven by A5 only - normally for single sampling
aadgrd=0b10000000;
output_float(PIN_A4);
output_drive(PIN_A5);
break;
case GUARD_BOTH:
//both rings enabled, - normal for double sampling
aadgrd=0b11000000;
output_drive(PIN_A4);
output_drive(PIN_A5);
break;
default:
//disable rings as default
aadgrd=0;
output_float(PIN_A5);
output_float(PIN_A4);
break;
}
}
void setup_sense(int16 pin, int8 clock, int8 caps, int8 mode)
{
int8 temp_int;
//routine to setup to sample the input capacitance. Requires:
//pin number, ADC clock selection (CCS defines), extra capacitance,
//and settings for the mode to use (defined above).
//typical: setup_sense(PIN_A0, ADC_CLOCK_DIV_16, CAPS4PF, DOUBLE_SAMPLE);
//first ensure pin TRIS is 0
output_low(pin);
//then setup the ADC
temp_int=(pin & 7)*4; //generates the selection value needed in AADCON0
aadcon0=temp_int; //enable the adc pin
setup_adc(clock); //and select clock
//now set the timings and capacaitance
aadpre=PRECHARGE;
aadacq=ACQUIRE;
aadcap=caps;
//now configure the actual sampling.
//allowing single or double sampling, ADOUT enabled or disabled, and
//control of it's polarity. However setting some other things 'automatically'
aadcon2=0; //no triggers enabled
temp_int=mode | 2; //invert second sample if double conversion used.
aadcon3=temp_int;
}
int16 cap_sense(void)
{
//routine to read the ADC value returned by the capacitance on selected pin
signed int16 first,second;
signed int16 delta; //offset to ensure result is +ve
GO=TRUE; //enable the ADC
do ;
while (GO==TRUE);
//here a conversion has completed
first=make16(aadres0h,aadres0l); //always OK
second=make16(aadres1h,aadres1l); //only valid if double conversion enabled
if (bit_set(aadcon3.0))
{
//here double conversion is enabled
//The second reading is counting down from 1023, the first up from zero
delta=first;
delta+=1023-second;
//delta now could be 0 to +2046
return delta/2; //return the two values averaged.
}
return first; //return the single reading is single sampling
}
|
Currently using this with a about 25mm sensor ring, surrounded by a guard ring (twin resistor feed off the two guard outputs), and then surrounded by an earth plane, to detect fluid inside a PTFE pipe. With an exponential moving average, and very slow automatic drift compensation, seems to be running well...
Hope somebody who wants to use this hardware CVD, finds it useful.
Best Wishes |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun Feb 09, 2014 9:14 am |
|
|
Great contribution! Looking at using this for a fountain level sensor I have in the works.
Thank You! _________________ Google and Forum Search are some of your best tools!!!! |
|
|
acm45
Joined: 29 Dec 2008 Posts: 18 Location: Italy
|
|
Posted: Mon Oct 03, 2016 5:06 am |
|
|
Hi all,
I'm using the CVD library and it works nicely, as the reading is a little bit noisy I used an exponential moving average that solved the problem.
Now I'm facing another issue related to the cap_sense() reading, it drifts with the time so I can't set a fixed threshold.
I don't understand why the reading is changing even if the sensor is in a steady condition (glued in the back of a ABS panel).
Any advice?
Thank you
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Tue Oct 04, 2016 1:15 am |
|
|
I've used an approach on another system, where the lowest reading recorded over a long time, is automatically used to update the calibration point. So if this goes below the recorded point, it updates straight away, while if over an hour it never drops below a particular value, the calibration is drifted up towards this new level.
You do need something like this, or a user calibration, otherwise 'long term', drifts in dirt on the keypad, humidity, and temperature all cause drift.
Remember also that the system is always measuring the relative capacitance, and the level it is relative 'to', includes the capacitance of the traces to the sensor, the PCB, the pins etc. I've had significant problems with FR4 PCB's having really bad long term drift (actually made hugely worse by modern production techniques involving water cleaning).
Some glues do shift noticeably in capacitance over a long time. |
|
|
mutthunaveen
Joined: 08 Apr 2009 Posts: 100 Location: Chennai, India
|
what is CVD?? |
Posted: Tue Oct 04, 2016 2:05 am |
|
|
Can some one explain what is CVD?? |
|
|
acm45
Joined: 29 Dec 2008 Posts: 18 Location: Italy
|
|
Posted: Tue Oct 04, 2016 4:33 am |
|
|
Thank you Ttelmah,
your answers are always clear, I will study and implement an adapatative threshold as you suggested me.
Best Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
Re: what is CVD?? |
Posted: Wed Oct 05, 2016 4:03 am |
|
|
mutthunaveen wrote: | Can some one explain what is CVD?? |
Stands for 'Capacitive Voltage Divider'.
In this context, it's a way of measuring relative capacitances using an ADC. So allows for things like touch pads.
There are two different PIC hardware modules to do such measurements, the CTMU, and the CVD. CCS supplies code for the CTMU module, but not for the CVD. The code here is for chips with the CVD. The CTMU is more accurate, using 'time' to do the basic measurement.
You can also implement CVD measurements just using software. |
|
|
mutthunaveen
Joined: 08 Apr 2009 Posts: 100 Location: Chennai, India
|
Thank you |
Posted: Wed Oct 05, 2016 9:57 pm |
|
|
Thank you for your kind explanation Ttelmah. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|