Hi,
I have been experimenting a lot with the PIC24F16KA102 for measuring accurately a period at nanosecond resolution.
I managed to get current calibration up an d running with very good values. I used the 55µA mode with 30K 0.1% resistance to produce 70% of full scale 2.5V as suggested in the application note.
Now I am trying to do capacitance calibration. I am starting from the smallest value of time to give to the A/D internal cap to charge and gradually increase the time and plot a graph. At first there seems to be a cap charging graph but at times, the value is totally distorted and totally goes out of the way. When I simulate it with proteus I get good values all the way. With MPLAB SIM the 5 transients for the A/D cap to charge up to approx. 1.65V, the stop watch showed 184µs. The code is below and the schematic is attached. The CTMUI is infact the voltage across the resistance not the current.
LCD 4-bit PIC24.png
Did anyone try something like and can give me some tips? Or even maybe there is a particular pic that is preferred when it comes to time measurement with the ctmu. (if it is possible to eliminate these factors)
I have been experimenting a lot with the PIC24F16KA102 for measuring accurately a period at nanosecond resolution.
I managed to get current calibration up an d running with very good values. I used the 55µA mode with 30K 0.1% resistance to produce 70% of full scale 2.5V as suggested in the application note.
Now I am trying to do capacitance calibration. I am starting from the smallest value of time to give to the A/D internal cap to charge and gradually increase the time and plot a graph. At first there seems to be a cap charging graph but at times, the value is totally distorted and totally goes out of the way. When I simulate it with proteus I get good values all the way. With MPLAB SIM the 5 transients for the A/D cap to charge up to approx. 1.65V, the stop watch showed 184µs. The code is below and the schematic is attached. The CTMUI is infact the voltage across the resistance not the current.
LCD 4-bit PIC24.png
Did anyone try something like and can give me some tips? Or even maybe there is a particular pic that is preferred when it comes to time measurement with the ctmu. (if it is possible to eliminate these factors)
Code:
#include <p24F16KA102.h>
#include "stdio.h"
#include "lcd.h"
#include "main.h"
#include "string.h"
_FPOR ( MCLRE_ON );
_FOSCSEL(FNOSC_PRI & IESO_OFF);
_FOSC (FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & POSCFREQ_HS & SOSCSEL_SOSCLP);
_FICD( ICS_PGx2 );
#define COUNTC 45 //12 //90 //@ 4MHz
#define ETIME COUNTC //time in uS
#define COUNT 370 //@ 4MHz
#define DELAY for(i=0;i<COUNT;i++)
#define DELAYC for(i=0;i<COUNTC;i++)
#define RCAL 0.03006 //2.983 // //R value is 3MΩ approx
//scaled so that result is in
//1/100th of uA
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 2.4941 //Vdd connected to A/D Vr+
#define home 0x80 //Cursor home
#define line2 0xC0 //Cursor line2
void Print(char* data0);
void PrintF(float num);
void nib_cmd(unsigned char);
void Delay_ms(unsigned int);
void lcd_init();
void initADC(int amask);
int readADC(int ch);
void setup(void);
void convert(int v);
char* CTMUI(float microamps,char *strprt);
char* CTMUCAP(float picof,char *strprt);
int main()
{
int i = 0;
int j = 0; //index for loop
DELAYC;
unsigned int Vread = 0;
double VTot = 0;
float Vavg=0, Vcal=0, CTMUISrc = 0; //float values stored for calcs
TRISB=0;
AD1PCFG=0;
lcd_init(); // LCD initialization
nib_cmd(0x01); //assume CTMU and A/D have been setup correctly
setup();
while(1)
{
Vread=0;
VTot=0;
//see Example 11-1 for CTMU & A/D setup
CTMUCONbits.CTMUEN = 1; //Enable the CTMU
for(j=0;j<10;j++)
{
AD1CON1bits.SAMP = 1; //Manual sampling start
CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
DELAY; //wait 125us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit
//using CTMU current source
DELAY;
IFS0bits.AD1IF = 0; //make sure A/D Int not set
AD1CON1bits.SAMP = 0; //and begin A/D conv.
//DELAY;
while(!IFS0bits.AD1IF); //Wait for A/D convert complete
AD1CON1bits.DONE = 0;
CTMUCONbits.EDG1STAT = 0; //Stop charging circuit
Vread = ADC1BUF0; //Get the value from the A/D
IFS0bits.AD1IF = 0; //Clear A/D Interrupt Flag
VTot += Vread; //Add the reading to the total
}
Vavg = (float)(VTot/10.0000); //Average of 10 readings
Vcal = (float)((Vavg/ADSCALE)*ADREF);
CTMUISrc = Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
char s[20];
nib_cmd(home);
Print("CTMUI: ");
Print(CTMUI(Vcal, s));
i=0;
j=0; //index for loop
Vread = 0;
double CTMUCap=0,time=0,VcTot=0;
setup();
CTMUCONbits.CTMUEN = 1;//Enable the CTMU
for(j=0;j<10;j++)
{
Vavg =0;
Vcal =0;
Vread=0;
CTMUCap=0;
AD1CON1bits.SAMP = 1; //Manual sampling start
CTMUCONbits.IDISSEN= 1; //drain any charge on the circuit
Delay_ms(50); //wait 62.5 us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit
//using the CTMU current source
DELAYC; //wait for charge
CTMUCONbits.EDG1STAT = 0; //Stop charging circuit and begin A/D conv.
AD1CON1bits.SAMP = 0;
while(!IFS0bits.AD1IF); //Wait for A/D conversion to complete
Vread = ADC1BUF0; //Get the value from the A/D converter
IFS0bits.AD1IF = 0; //Clear AD1IF
VcTot += Vread; //Add the reading to the total
}
Vavg = (float)(VcTot/10.000); //Average of 10 readings
Vcal = (float)(Vavg/ADSCALE*ADREF);
CTMUCap = (float)((CTMUISrc*ETIME)/Vcal)/100;
//CTMUISrc is in 1/100ths of uA,
//calculated in Example 1-2
//time is in us
//CTMUCap is in pF
char c[10];
nib_cmd(line2);
Print("Cap: ");
Print(CTMUCAP(Vcal, c));
}
return(0);
}
char* CTMUI(float microamps,char *strprt) // convert long to voltage string
{
int iw=0,ip=0;
iw=(long)((float)microamps);
ip=(long)((float)microamps*1000)-(iw*1000);
sprintf(strprt,"%d.%d",(int)iw,(int)ip);
return strprt;
}
char* CTMUCAP(float picof,char *strprt) // convert long to voltage string
{
int iw=0,ip=0;
iw=(long)((float)picof);
ip=(long)((float)picof*1000)-iw*1000;
sprintf(strprt,"%d.%d",(int)iw,(int)ip);
return strprt;
}
void setup(void)
{
//CTMUCON - CTMU Control register
// CTMUCON = 0x89DC; //make sure CTMU is disabled
// CTMU continues to run when emulator is stopped,CTMU continues
// to run in Idle mode, Time Generation mode enabled, Edges are
// blocked. No edge sequence order, Analog current source not
// grounded, trigger output disabled, Edge2 polarity = positive level,
// Edge2 source = source 0, Edge1 polarity = positive level,
// Edge1 source = source 0, Set Edge status bits to zero
//CTMUICON - CTMU Current Control Register
CTMUICON = 0x0300; //55uA, Nominal - No Adjustment
//adc
TRISB=0x0001; // Set channel 2 as an input// Channel 10 here 0x0001
AD1PCFG=0x0002;
AD1CHS=0X0002; // Select the analog channel(2)
AD1CSSL=0;
AD1CON1 = 0x8000; // Turn On A/D Converter, continue in Idle mode,
//AD1CON1 = 0x00E0;
// Unsigned fractional format, Clear SAMP bit to
// start conversion, Sample when SAMP bit is set,
// sampling on hold
AD1CON2 = 0x2000; // VR+ = AVDD, V- = AVSS, Don't scan,0x2000
AD1CON3 = 0x0000;
}