[PIC] CTMU current and capacitance calibration

Status
Not open for further replies.

teddydogowners

Newbie level 4
Joined
Jul 4, 2016
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
62
Hi!

I am using the CTMU of a PIC24FJ64GA106, and I can't seem to calibrate it at all. The CTMUIsrc value always returns as 0, and the CTMUCap always returns as NaN. What could be the problem?

Thanks in advance!

Code:
#include "p24Fxxxx.h"
#include "p24FJ64GA106.h"
#include "adc.h"
#include "comparator.h"
#include "crc.h"
#include "ctmu.h"
#include "i2c.h"
#include "incap.h"
#include "outcompare.h"
#include "pmp.h"
#include "ports.h"
#include "PPS.h"
#include "PwrMgnt.h"
#include "Rtcc.h"
#include "spi.h"
#include "sram.h"
#include "timer.h"
#include "uart.h"
#include "wdt.h"
#include "stdio.h"
#include "stdlib.h"
#include "xc.h"
#include "PIC24F_periph_features.h"

// CONFIG3
#pragma config WPFP = WPFP511           // Write Protection Flash Page Segment Boundary (Highest Page (same as page 42))
#pragma config WPDIS = WPDIS            // Segment Write Protection Disable bit (Segmented code protection disabled)
#pragma config WPCFG = WPCFGDIS         // Configuration Word Code Page Protection Selectbit (Last page(at the top of program memory) and Flash configuration words are not protected)
#pragma config WPEND = WPENDMEM         // Segment Write Protection End Page Select bit (Write Protect from WPFP to the last page of memory)

// CONFIG2
#pragma config POSCMOD = EC             // Primary Oscillator Select (EC Oscillator mode Selected)
#pragma config IOL1WAY = OFF             // IOLOCK One-Way Set Enable bit (Write RP Registers Once)
#pragma config OSCIOFNC = OFF           // Primary Oscillator Output Function (OSCO functions as CLKO (FOSC/2))
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor (Both Clock Switching and Fail-safe Clock Monitor are disabled)
#pragma config FNOSC = PRI              // Oscillator Select (Primary oscillator (XT, HS, EC))
#pragma config IESO = OFF               // Internal External Switch Over Mode (IESO mode (Two-speed start-up)disabled)

// CONFIG1
#pragma config WDTPS = PS1              // Watchdog Timer Postscaler (1:1)
#pragma config FWPSA = PR32             // WDT Prescaler (1:32)
#pragma config WINDIS = OFF             // Watchdog Timer Window (Standard Watchdog timer is enabled(Windowed mode is disabled))
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (Watchdog timer is disabled)
#pragma config ICS = PGx1               // Comm Channel Select (EMUC/EMUD share PGC1/PGD1)
#pragma config GWRP = OFF               // General Code Segment Write Protect (Writes to program memory are allowed)
#pragma config GCP = OFF                // General Code Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF             // JTAG Port Enable (JTAG port is disabled)


/**************************************************************************/
//Setup CTMU
/**************************************************************************/


double CTMUISrc=0;
double CTMUCap=0;;

int setupcur(void);
int setupcap(void);
int CurCal(void);
int CapCal(void);
int StartPulse(void);
int TimeMeasure(void);

int main(void)
{
    RCON=0x0000;
    OSCCONL=0x46;
    OSCCONH=0x78;
    //OSCCONH=0x9A;
    //OSCCONH=0x22;
    /*OSCCONbits.CLKLOCK=0;
    OSCCONbits.IOLOCK=1;
    OSCCONbits.LOCK=0;
    OSCCONbits.CF=0;
    OSCCONbits.POSCEN=1;
    OSCCONbits.SOSCEN=1;
    OSCCONbits.OSWEN=0;*/
    CLKDIV=0x0000;
    REFOCON=0x0000;
    CurCal();
    CapCal();
    /*while(1)
    {
        // Step 7: Wait for ADC interrupt
        while(IFS0bits.AD1IF == 0)
        {
            // Steps 8-11
            IFS0bits.AD1IF = 0; // clear the interrupt
            result = ADC1BUF0; // read ADC result
            CTMUCONbits.IDISSEN = 1; // begin manual discharge of cap
            asm("NOP"); // may be required for external caps
            asm("NOP");
            asm("NOP");
            asm("NOP");
            CTMUCONbits.IDISSEN = 0; // stop discharge of cap
            CTMUCON &= ~0x0300; // clear the edge status bits
        }
        
    }*/
    //TimeMeasure();
    int i=0;
    TRISFbits.TRISF0=0;
    LATFbits.LATF0=1;
    while(1)
    {
        LATFbits.LATF0=0;
        for(i=0;i<8100;i++);
        LATFbits.LATF0=1;
        for(i=0;i<8100;i++);
    }
    return(1);
}


int setupcur(void)
{         //CTMUCON - CTMU Control register
        CTMUCON = 0x80FC; //make sure CTMU is disabled
        //CTMU continues to run when emulator is stopped,CTMU continues
        //to run in idle mode,Time Generation mode disabled, 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 = 0x0100; //0.55uA, Nominal - No Adjustment
        //-------------------------------------------------------------------------
        //setupAD converter;
        //-------------------------------------------------------------------------
        TRISB=0x0001; //set channel 0 as an input
        AD1PCFGL=0x0000; //
        AD1PCFGH=0x0000;
        AD1CHS=0x0000; //select the analog channel(0)
        AD1CSSL=0x0001; //
        AD1CON1 = 0x8000; //Turn On A/D Converter, continue in
        // idle mode, Unsigned fractional format, Clear Samp bit to start
        //conversion, Sample when SAMP bit is set, sampling on hold
        AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan,
        //always use MUX A inputs
        AD1CON3 = 0x0100; //A/D uses system clock, conversion
        //clock = 1xTcy
        return(1);
}

int setupcap(void)
{
      //CTMUCON - CTMU Control register
        CTMUCON = 0x80FC; //make sure CTMU is disabled
        //CTMU continues to run when emulator is stopped,CTMU continues
        //to run in idle mode,Time Generation mode disabled, 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 = 0x0100; //0.55uA, Nominal - No Adjustment
        //-------------------------------------------------------------------------
        //setupAD converter;
        //-------------------------------------------------------------------------
        TRISB=0x0002; //set channel 1 as an input
        AD1PCFGL=0x0000; //
        AD1PCFGH=0x0000;
        AD1CHS=0x0101; //select the analog channel(1)
        AD1CSSL=0x0002; //
        AD1CON1 = 0x8000; //Turn On A/D Converter, continue in
        // idle mode, Unsigned fractional format, Clear Samp bit to start
        //conversion, Sample when SAMP bit is set, sampling on hold
        AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan,
        //always use MUX A inputs
        AD1CON3 = 0x0100; //A/D uses system clock, conversion
        //clock = 1xTcy
        return(1);
}

#define COUNT 500 //@ 8MHz = 125uS.
#define DELAY for(i=0;i<COUNT;i++)
#define RCAL .027 //R value is 4200000 (4.2M)
//scaled so that result is in
//1/100th of uA
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 3.3 //Vdd connected to A/D Vr+

int CurCal(void)
{
        int i;
        int j = 0; //index for loop
        double Vread = 0;
        double VTot = 0;
        float Vavg=0, Vcal=0; //float values stored for calculations
        setupcur();
        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; //wait for 125us
                CTMUCONbits.EDG1STAT = 0; //Stop charging circuit
                IFS0bits.AD1IF = 0; //make sure A/D Int not set
                AD1CON1bits.SAMP = 0; //and begin A/D conv.
                while(!IFS0bits.AD1IF); //Wait for A/D convert complete
                AD1CON1bits.DONE = 0;
                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.000); //Average of 10 readings
        Vcal = (float)(Vavg/ADSCALE*ADREF);
        CTMUISrc = Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
        return(1);
}

#define COUNT2 25 //@ 8MHz INTFRC = 62.5 us.
#define ETIME COUNT2*2.5 //time in uS
#define DELAY2 for(i=0;i<COUNT2;i++)
#define ADSCALE 1023 //for unsigned conversion 10 sig bits
#define ADREF 3.3 //Vdd connected to A/D Vr+


int CapCal(void)
{
    int i;
    int j = 0; //index for loop
    unsigned int Vread = 0;
    float Vavg;
    float VTot;
    float Vcal;
    //assume CTMU and A/D have been setup correctly
    //see Example 11-1 for CTMU & A/D setup
    setupcap();
    CTMUCONbits.CTMUEN = 1;//Enable the CTMU
    for(j=0;j<10;j++)
    {
        AD1CON1bits.SAMP = 1; //Manual sampling start
        CTMUCONbits.IDISSEN= 1; //drain any charge on the circuit
        DELAY2; //wait 62.5 us
        CTMUCONbits.IDISSEN = 0; //end drain of circuit
        CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit
        //using the CTMU current source
        DELAY2; //wait for 62.5 us for circuit to 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
        VTot += Vread; //Add the reading to the total
    }
    Vavg = (VTot/10); //Average of 10 readings
    Vcal = (Vavg/ADSCALE*ADREF);
    CTMUCap = (CTMUISrc*ETIME/Vcal)/100;
    //CTMUISrc is in 1/100ths of uA,
    //calculated in Example 1-2
    //time is in us
    //CTMUCap is in pF
    return(1);
}

int StartPulse(void)
{
    /*TRISDbits.TRISD10=0;
    RPOR1bits.RP3R=18;
    OC1CON1=0x0000;
    OC1R=0x0002;
    OC1RS=0x0008;
    PR1=0x0004;
    TMR2=0x0002;
    OC1CON1=0x1004;
    OC1CON2=0x001F;
    IEC0bits.T1IE=0;
    IEC0bits.OC1IE=0;
    T1CON=0x0000;
    PR1=0.000000125;
    T1CONbits.TON=1;
    AD1PCFGL=0x0000;
    AD1CON2=0x0000;//comment till here*/
    TRISDbits.TRISD0=0;
    RPOR5bits.RP11R=18;
    asm("NOP");
    OC1CON1 = 0x0000; // Turn off Output Compare 1 Module
    OC1CON1 = 0x0004; // Load new compare mode to OC1CON
    OC1R = 0x3000; // Initialize Compare Register1 with 0x3000
    OC1RS = 0x6000; // Initialize Secondary Compare Register1 with 0x3003
    PR3=0x6000;
    IPC0bits.OC1IP0 = 1; // Setup Output Compare 1 interrupt for
    IPC0bits.OC1IP1 = 0; // desired priority level
    IPC0bits.OC1IP2 = 0; // (this example assigns level 1 priority)
    IFS0bits.OC1IF = 0; // Clear Output Compare 1 interrupt flag
    IEC0bits.OC1IE = 0; // Enable Output Compare 1 interrupts
    T2CONbits.TSIDL=0;
    T2CONbits.TGATE=0;
    T2CONbits.TCS=0;
    T2CONbits.TCKPS=0b00;
    T2CONbits.T32=0;
    T2CONbits.TON = 1; // Start Timer2 with assumed settings
    return(1);
}

int TimeMeasure(void)
{
    float vread=0;
    float time=0;
    int i;
    //setup CTMU
    //CTMUCON
    CTMUCONbits.CTMUEN = 0; //make sure CTMU is disabled
    CTMUCONbits.CTMUSIDL = 0; //CTMU continues to run in idle mode
    CTMUCONbits.TGEN = 0; //disable edge delay generation mode of the CTMU
    CTMUCONbits.EDGEN = 1; 
    CTMUCONbits.EDGSEQEN = 1; 
    CTMUCONbits.IDISSEN = 0; //Do not ground the current source
    CTMUCONbits.CTTRIG = 0; //Trigger Output is disabled
    CTMUCONbits.EDG2POL = 0;
    CTMUCONbits.EDG2SEL = 0b10; //Edge2 Source = CTED2
    CTMUCONbits.EDG1POL = 1;
    CTMUCONbits.EDG1SEL = 0b11; //Edge1 Source = CTED1
    CTMUCONbits.EDG1STAT=0;
    CTMUCONbits.EDG2STAT=0;
    //CTMUICON
    CTMUICON=0x0000;
    CTMUICONbits.IRNG=0b01; //55uA
    CTMUICONbits.ITRIM = 0b000000; //Nominal - No Adjustment
    //setup A/D converter
    TRISBbits.TRISB12 = 1; // Configure RB12 as a input CTED2
    TRISBbits.TRISB13 = 1; // Configure RB13 as a input CTED1
    TRISBbits.TRISB2 = 1; // Configure RB2 as a input
    AD1PCFGL=0x0000; //-----------------IT SAID 0x0004, find out why
    AD1PCFGH=0x0000;
    AD1CHS=0x0004; //select the analog channel(2)
    AD1CSSL=0x0004; //
    AD1CON1 = 0x0000; //Turn Off A/D Converter, continue in idle mode, Unsigned fractional format, Sample when SAMP bit is set, sampling on hold
    AD1CON1bits.SSRC = 4; // CTMU is the conversion trigger source
    AD1CON2 = 0x0000; //VR+ = AVDD, V- = AVSS, Don't scan, always use MUX A inputs
    AD1CON3 = 0x0000; //A/D uses system clock, conversion clock = 1xTcy
    AD1CON3bits.ADCS = 8; // conversion clock = 1xTcy
    AD1CON1bits.ADON = 1;
    AD1CON1bits.ASAM = 1; // Auto-sample
    AD1CHSbits.CH0SA = 2; // Select AN2
    CTMUCONbits.CTMUEN=1;
    CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
    DELAY; //wait 125us
    CTMUCONbits.IDISSEN = 0; //end drain of circuit
    AD1CON1bits.SAMP=1;
    StartPulse();
    DELAY; //wait for 125us
    DELAY;
    IFS0bits.AD1IF = 0; //make sure A/D Int not set
    AD1CON1bits.SAMP = 0; //and begin A/D conv.
    while(!IFS0bits.AD1IF); //Wait for A/D convert complete
    AD1CON1bits.DONE = 0;
    vread = ADC1BUF0;
    time=vread*(CTMUCap/CTMUISrc)*(ADREF/ADSCALE); //Get time difference
    return(1);
}

 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…