Current leakage in PIC18F46K80 CTMU module

Thread Starter

Mellowed

Joined Mar 6, 2016
13
Hi guys,

I am currently trying to build a time measurement unit using the CTMU module of a PIC. I noticed that there seems to be some leakage current from the CTMU module whilst enabled but while the EDGE1STAT and EDGE2STAT are not active. Is this correct or am i doing something wrong? below is the code i am using.

I am activating the CTMU module and then setting a pin ( called LED) high which is connected via coax cable to the start and stop pins of the CTMU. This processes works and i get working results, but if i increase the delay time before activating the led pin connected to the coax cable then my results change. Also simply leaving the module active for a while without enabling the LED pin results in a measurable difference and indication of current leakage (which is kinda small but still a problem for me).

Code:
#include <xc.h>
#define _XTAL_FREQ 16000000
#define TRUE 1
#define FALSE 0
#define LEDs PORTA
#define LED1 PORTAbits.RA2
#define COUNT  2 //500 //@ 8MHz = 125uS.
#define DELAY for(i=0;i<COUNT;i++)

//#define RCAL 19950 //R value is 19.95Kohm 19950
#define RCAL 1496000 //R value is 19.95Kohm 19950
//scaled so that result is in
//1/100th of uA
#define ADSCALE 4096 //for unsigned conversion 10 sig bits
#define ADREF 2
#define Current3 80 // current was calibrated to 80uA
#define Current1 0.28 // current was calibrated to 0.28uA
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <usart.h>
#include <plib.h>
#include <delays.h>
#include <sw_uart.h>


void IO_ports_init(void)
{
TRISA = 0x00;           //set as output
PORTA = 0x00;
TRISB = 0;
//PORTB = 0;

TRISBbits.TRISB2 =1;            // input for CTMU 1 edge
TRISBbits.TRISB3=1;            // input for CTMU 2 edge

//LATB = 0;
//--ADC
TRISBbits.TRISB0 = 1;   //set channel 10 as an input
PORTAbits.RA0 = 0;
LATAbits.LATA0 = 0;
//--UART
TRISCbits.TRISC6 = 0; // RC6  (TX1)
TRISCbits.TRISC7 = 1; //RC7  (RX1)
PORTC=0x00;
PORTD=0x00;

SLRCON = 0x00;
CTMUCONH = 0x00;

RCONbits.IPEN = 1;
INTCONbits.GIEH = 1;
}
void USART_init(void){
    TXSTA1 = 0b10100100;
    SPBRG1 = 103;
}
void OscillatorConfig(void){
OSCCON = 0b01111100;
OSCCON2 = 0b00010010;
}

void delayMsx(int time){
   
for(int x = 0; x < time; x++){
        __delay_ms(1);
}
}

void delayUsx(int time){
   
for(int x = 0; x < time; x++){
        __delay_us(1);
}
}


void ADCConfig(void){ 
ANCON1 = 3;

ADCON2bits.ADFM=1; // Result format 1= Right justified
ADCON2bits.ACQT=1; // Acquisition time 7 = 20TAD 2 = 4TAD 1=2TAD
ADCON2bits.ADCS=2; // Clock conversion bits 6= FOSC/64 2=FOSC/32
ADCON1bits.TRIGSEL=1;

ADCON1bits.VCFG0 =0; // Vref+ = AVdd
ADCON1bits.VCFG =2; // Vref+ = AVdd
ADCON1bits.VNCFG = 0; // Vref- = AVss
ADCON0bits.CHS=10; // Select ADC channel
ADCON0bits.ADON=1; // Turn on ADC      
}

void CTMUInit (void){

CTMUCONH = 0; //make sure CTMU is disabled
CTMUCONHbits.EDGEN=1;        // edge are not blocked
CTMUCONHbits.EDGSEQEN=1;    // edge 1 then 2 for interrupt
CTMUCONHbits.CTTRIG=1;

CTMUCONL = 0b11011100;  // CTMU trigger setup : net edge 1, neg edge 2, edge 1&2 source select CTED 1&2, clear event bits
CTMUICON = 0b01111111; // 1= base current 0.55uA  2= 5.5uA   3=55uA // max positive trim

}


void CTMU (void){
int Vread;
CTMUCONHbits.CTMUEN = 0;
CTMUCONL = 0b11011100;
LEDs = 0;

CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
    __delay_us(30);
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONHbits.CTMUEN = 1;
__delay_us(500);

LEDs = 255;

PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag

char ac_sample_char[12];
char spacer[5];
if(Vread > 10){
sprintf(spacer, "  ");
    if(Vread > 100){
    sprintf(spacer, " ");
        if(Vread > 1000){
        sprintf(spacer, "");
        }
    }
}
sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);

puts1USART(ac_sample_char);
putrs1USART(" \n\r");


}


void CurrentCalibration (void){
   
int i;
int j = 0; //index for loop
int Vread = 0;
double VTot = 0;
double Vavg=0, Vcal=0, CTMUISrc = 0;

CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
__delay_ms(1); //wait 125us
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
for(j=0;j<10;j++)
{
delayMsx(100);  //wait for 125us
PIR1bits.ADIF = 0; //make sure A/D Interupt not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
VTot = VTot + Vread; //Add the reading to the total
}
CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit
CTMUCONHbits.CTMUEN = 0; //Enable the CTMU
Vavg = (double)(VTot/10); //Average of 10 readings
Vcal = 0.0004882812;
Vcal = (double)Vcal*Vavg;
CTMUISrc = (double)Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
CTMUISrc = CTMUISrc*1000000;    // current in uA

char ac_sample_char[12];

sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUISrc ", Vavg,Vcal,CTMUISrc );

puts1USART(ac_sample_char);
putrs1USART(" \n\r");  
}

void CapacitanceCalibration (void){
   
  int i;
int j = 0; //index for loop
int Vread = 0;
float CTMUISrc, CTMUCap, Vavg, VTot, Vcal;
//assume CTMU and A/D have been setup correctly
//see Example 25-1 for CTMU & A/D setup

CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
for(j=0;j<10;j++)
{
CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
delayUsx(125); //wait 125us
CTMUCONHbits.IDISSEN = 0; //end drain of circuit
CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
//using CTMU current source
delayUsx(12); //wait 125us
CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit

PIR1bits.ADIF = 0; //make sure A/D Int not set
ADCON0bits.GO=1; //and begin A/D conv.
while(!PIR1bits.ADIF); //Wait for A/D convert complete
Vread = ADRES; //Get the value from the A/D
PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
VTot += Vread; //Add the reading to the total
}

Vavg = (double)(VTot/10.000); //Average of 10 readings
Vcal = 0.0004882812;
Vcal = (double)Vcal*Vavg;
CTMUISrc = 0.28; //CTMUISrc is in 1/100ths of uA
CTMUCap = (double)(CTMUISrc*12/Vcal); 

char ac_sample_char[12];

sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUCap ", Vavg,Vcal,CTMUCap );

puts1USART(ac_sample_char);
putrs1USART(" \n\r");  
   
}




/*******************************************/
void main(void) {
OscillatorConfig();
IO_ports_init();
USART_init();

ADCConfig();
CTMUInit();

BAUDCON1bits.BRG16 = 1;
Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_CONT_RX & USART_BRGH_HIGH, 68); //103 for 16 mhz 51 for 8mhz

RCONbits.IPEN = 1;
INTCONbits.GIEL = 0;
INTCONbits.GIEH = 1;
CTMUCONHbits.CTMUEN = 1;
putrs1USART("Starting \n\r");
    while(1)
    {

  CTMU();
delayMsx(1000);

    }
}
 

nsaspook

Joined Aug 27, 2009
13,086
Yes there is some usually some leakage that's detectable with no charge current (not just internally from the chip) so you want to keep the current drain circuit active until just before measurements if possible.
 

Thread Starter

Mellowed

Joined Mar 6, 2016
13
Thanks!

I need to detect the time difference between the arrival of two photons which will arrive randomly. At the moment i'm not sure what the maximum frequency of the incoming signal will be but i'm imagining it will be less than a 1ms so the leakage can be managed to some degree (its just good to know that it is actually there!).

Would it be possible to have the drain circuit disable itself when the incoming start signal triggers the CTMU module to start charging the cap?
 

nsaspook

Joined Aug 27, 2009
13,086
I don't think you can auto-toggle the drain circuit.


If you're using the ADC mux to connect to a unused channel I suspect some of your leakage problem is there instead of the edge switch. I believe on that chip you can disconnect the input MUX from the ADC Sample/Hold
 

Picbuster

Joined Dec 2, 2013
1,047
The article ww1.microchip.com/downloads/en/DeviceDoc/61167B.pdf is making a remark on set and reset related to the 'current'.
It might help you and seems to support your idea on leakage.
 
Top