Current leakage in PIC18F46K80 CTMU module

Discussion in 'Embedded Systems and Microcontrollers' started by Mellowed, Apr 3, 2016.

  1. Mellowed

    Thread Starter New Member

    Mar 6, 2016
    10
    2
    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 (Text):
    1. #include <xc.h>
    2. #define _XTAL_FREQ 16000000
    3. #define TRUE 1
    4. #define FALSE 0
    5. #define LEDs PORTA
    6. #define LED1 PORTAbits.RA2
    7. #define COUNT  2 //500 //@ 8MHz = 125uS.
    8. #define DELAY for(i=0;i<COUNT;i++)
    9.  
    10. //#define RCAL 19950 //R value is 19.95Kohm 19950
    11. #define RCAL 1496000 //R value is 19.95Kohm 19950
    12. //scaled so that result is in
    13. //1/100th of uA
    14. #define ADSCALE 4096 //for unsigned conversion 10 sig bits
    15. #define ADREF 2
    16. #define Current3 80 // current was calibrated to 80uA
    17. #define Current1 0.28 // current was calibrated to 0.28uA
    18. #include <conio.h>
    19. #include <stdio.h>
    20. #include <stdlib.h>
    21. #include <string.h>
    22. #include <math.h>
    23. #include <time.h>
    24. #include <usart.h>
    25. #include <plib.h>
    26. #include <delays.h>
    27. #include <sw_uart.h>
    28.  
    29.  
    30. void IO_ports_init(void)
    31. {
    32. TRISA = 0x00;           //set as output
    33. PORTA = 0x00;
    34. TRISB = 0;
    35. //PORTB = 0;
    36.  
    37. TRISBbits.TRISB2 =1;            // input for CTMU 1 edge
    38. TRISBbits.TRISB3=1;            // input for CTMU 2 edge
    39.  
    40. //LATB = 0;
    41. //--ADC
    42. TRISBbits.TRISB0 = 1;   //set channel 10 as an input
    43. PORTAbits.RA0 = 0;
    44. LATAbits.LATA0 = 0;
    45. //--UART
    46. TRISCbits.TRISC6 = 0; // RC6  (TX1)
    47. TRISCbits.TRISC7 = 1; //RC7  (RX1)
    48. PORTC=0x00;
    49. PORTD=0x00;
    50.  
    51. SLRCON = 0x00;
    52. CTMUCONH = 0x00;
    53.  
    54. RCONbits.IPEN = 1;
    55. INTCONbits.GIEH = 1;
    56. }
    57. void USART_init(void){
    58.     TXSTA1 = 0b10100100;
    59.     SPBRG1 = 103;
    60. }
    61. void OscillatorConfig(void){
    62. OSCCON = 0b01111100;
    63. OSCCON2 = 0b00010010;
    64. }
    65.  
    66. void delayMsx(int time){
    67.    
    68. for(int x = 0; x < time; x++){
    69.         __delay_ms(1);
    70. }
    71. }
    72.  
    73. void delayUsx(int time){
    74.    
    75. for(int x = 0; x < time; x++){
    76.         __delay_us(1);
    77. }
    78. }
    79.  
    80.  
    81. void ADCConfig(void){
    82. ANCON1 = 3;
    83.  
    84. ADCON2bits.ADFM=1; // Result format 1= Right justified
    85. ADCON2bits.ACQT=1; // Acquisition time 7 = 20TAD 2 = 4TAD 1=2TAD
    86. ADCON2bits.ADCS=2; // Clock conversion bits 6= FOSC/64 2=FOSC/32
    87. ADCON1bits.TRIGSEL=1;
    88.  
    89. ADCON1bits.VCFG0 =0; // Vref+ = AVdd
    90. ADCON1bits.VCFG =2; // Vref+ = AVdd
    91. ADCON1bits.VNCFG = 0; // Vref- = AVss
    92. ADCON0bits.CHS=10; // Select ADC channel
    93. ADCON0bits.ADON=1; // Turn on ADC      
    94. }
    95.  
    96. void CTMUInit (void){
    97.  
    98. CTMUCONH = 0; //make sure CTMU is disabled
    99. CTMUCONHbits.EDGEN=1;        // edge are not blocked
    100. CTMUCONHbits.EDGSEQEN=1;    // edge 1 then 2 for interrupt
    101. CTMUCONHbits.CTTRIG=1;
    102.  
    103. CTMUCONL = 0b11011100;  // CTMU trigger setup : net edge 1, neg edge 2, edge 1&2 source select CTED 1&2, clear event bits
    104. CTMUICON = 0b01111111; // 1= base current 0.55uA  2= 5.5uA   3=55uA // max positive trim
    105.  
    106. }
    107.  
    108.  
    109. void CTMU (void){
    110. int Vread;
    111. CTMUCONHbits.CTMUEN = 0;
    112. CTMUCONL = 0b11011100;
    113. LEDs = 0;
    114.  
    115. CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
    116.     __delay_us(30);
    117. CTMUCONHbits.IDISSEN = 0; //end drain of circuit
    118. CTMUCONHbits.CTMUEN = 1;
    119. __delay_us(500);
    120.  
    121. LEDs = 255;
    122.  
    123. PIR1bits.ADIF = 0; //make sure A/D Interupt not set
    124. ADCON0bits.GO=1; //and begin A/D conv.
    125. while(!PIR1bits.ADIF); //Wait for A/D convert complete
    126. Vread = ADRES; //Get the value from the A/D
    127. PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
    128.  
    129. char ac_sample_char[12];
    130. char spacer[5];
    131. if(Vread > 10){
    132. sprintf(spacer, "  ");
    133.     if(Vread > 100){
    134.     sprintf(spacer, " ");
    135.         if(Vread > 1000){
    136.         sprintf(spacer, "");
    137.         }
    138.     }
    139. }
    140. sprintf(ac_sample_char, "%02d %s - CT1:%01d CT2:%01d E1:%01d E2:%01d", Vread, spacer , PORTBbits.RB2, PORTBbits.RB3 ,CTMUCONLbits.EDG1STAT, CTMUCONLbits.EDG2STAT);
    141.  
    142. puts1USART(ac_sample_char);
    143. putrs1USART(" \n\r");
    144.  
    145.  
    146. }
    147.  
    148.  
    149. void CurrentCalibration (void){
    150.    
    151. int i;
    152. int j = 0; //index for loop
    153. int Vread = 0;
    154. double VTot = 0;
    155. double Vavg=0, Vcal=0, CTMUISrc = 0;
    156.  
    157. CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
    158. CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
    159. __delay_ms(1); //wait 125us
    160. CTMUCONHbits.IDISSEN = 0; //end drain of circuit
    161. CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
    162. for(j=0;j<10;j++)
    163. {
    164. delayMsx(100);  //wait for 125us
    165. PIR1bits.ADIF = 0; //make sure A/D Interupt not set
    166. ADCON0bits.GO=1; //and begin A/D conv.
    167. while(!PIR1bits.ADIF); //Wait for A/D convert complete
    168. Vread = ADRES; //Get the value from the A/D
    169. PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
    170. VTot = VTot + Vread; //Add the reading to the total
    171. }
    172. CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit
    173. CTMUCONHbits.CTMUEN = 0; //Enable the CTMU
    174. Vavg = (double)(VTot/10); //Average of 10 readings
    175. Vcal = 0.0004882812;
    176. Vcal = (double)Vcal*Vavg;
    177. CTMUISrc = (double)Vcal/RCAL; //CTMUISrc is in 1/100ths of uA
    178. CTMUISrc = CTMUISrc*1000000;    // current in uA
    179.  
    180. char ac_sample_char[12];
    181.  
    182. sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUISrc ", Vavg,Vcal,CTMUISrc );
    183.  
    184. puts1USART(ac_sample_char);
    185. putrs1USART(" \n\r");  
    186. }
    187.  
    188. void CapacitanceCalibration (void){
    189.    
    190.   int i;
    191. int j = 0; //index for loop
    192. int Vread = 0;
    193. float CTMUISrc, CTMUCap, Vavg, VTot, Vcal;
    194. //assume CTMU and A/D have been setup correctly
    195. //see Example 25-1 for CTMU & A/D setup
    196.  
    197. CTMUCONHbits.CTMUEN = 1; //Enable the CTMU
    198. for(j=0;j<10;j++)
    199. {
    200. CTMUCONHbits.IDISSEN = 1; //drain charge on the circuit
    201. delayUsx(125); //wait 125us
    202. CTMUCONHbits.IDISSEN = 0; //end drain of circuit
    203. CTMUCONLbits.EDG1STAT = 1; //Begin charging the circuit
    204. //using CTMU current source
    205. delayUsx(12); //wait 125us
    206. CTMUCONLbits.EDG1STAT = 0; //Stop charging circuit
    207.  
    208. PIR1bits.ADIF = 0; //make sure A/D Int not set
    209. ADCON0bits.GO=1; //and begin A/D conv.
    210. while(!PIR1bits.ADIF); //Wait for A/D convert complete
    211. Vread = ADRES; //Get the value from the A/D
    212. PIR1bits.ADIF = 0; //Clear A/D Interrupt Flag
    213. VTot += Vread; //Add the reading to the total
    214. }
    215.  
    216. Vavg = (double)(VTot/10.000); //Average of 10 readings
    217. Vcal = 0.0004882812;
    218. Vcal = (double)Vcal*Vavg;
    219. CTMUISrc = 0.28; //CTMUISrc is in 1/100ths of uA
    220. CTMUCap = (double)(CTMUISrc*12/Vcal);
    221.  
    222. char ac_sample_char[12];
    223.  
    224. sprintf(ac_sample_char, "%0.1f Vavg : %0.3f Voltage : %0.2f CTMUCap ", Vavg,Vcal,CTMUCap );
    225.  
    226. puts1USART(ac_sample_char);
    227. putrs1USART(" \n\r");  
    228.    
    229. }
    230.  
    231.  
    232.  
    233.  
    234. /*******************************************/
    235. void main(void) {
    236. OscillatorConfig();
    237. IO_ports_init();
    238. USART_init();
    239.  
    240. ADCConfig();
    241. CTMUInit();
    242.  
    243. BAUDCON1bits.BRG16 = 1;
    244. 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
    245.  
    246. RCONbits.IPEN = 1;
    247. INTCONbits.GIEL = 0;
    248. INTCONbits.GIEH = 1;
    249. CTMUCONHbits.CTMUEN = 1;
    250. putrs1USART("Starting \n\r");
    251.     while(1)
    252.     {
    253.  
    254.   CTMU();
    255. delayMsx(1000);
    256.  
    257.     }
    258. }
     
  2. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,907
    2,163
    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.
     
    Mellowed likes this.
  3. Mellowed

    Thread Starter New Member

    Mar 6, 2016
    10
    2
    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?
     
  4. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,907
    2,163
    I don't think you can auto-toggle the drain circuit.
    [​IMG]

    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
     
  5. dannyf

    Well-Known Member

    Sep 13, 2015
    1,771
    358
    sounds like a task better suited for a timer.
     
  6. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,907
    2,163
    Last edited: Apr 3, 2016
  7. Picbuster

    Member

    Dec 2, 2013
    373
    50
    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.
     
  8. Mellowed

    Thread Starter New Member

    Mar 6, 2016
    10
    2
    Thanks Guys,

    I'v been playing around with my setup and i will just have to do some measurements over and use the internal timer to adjust for the current leakage. I now have another problem which i created a new post for, it has to do with the edge triggered responses which my device is not working :( thanks again for all the advice.

    http://forum.allaboutcircuits.com/t...-to-respond-to-positive-edge-triggers.122985/
     
Loading...