I'm trying to implement a basic touch sensor using the CTMU on my PIC24F04KA200. Reading the datasheet and application notes provided by Microchip I was expecting this to be an easy endeavor. In this question I will just explain what I'm doing, post my C code and hopefully someone can point me in the right direction.
I have connected my sensor which is a copper plate on top of PCB board material about the size of a postcard. The kind of thing you buy to DIY your own circuit board. I have this connected this to AN4(RA2) pin. I have an LED and current limiting resistor connected to RA4. The only other circuit items I have are a decoupling cap .1uF on power pins and the PicKit3 powering the circuit (I've also tried with separate power supply).
All I've tried to do is follow the code example given by Microchip and essentially turn on the current source to allow my copper pad to charge and measure the voltage with A/D (as explained in the App Note) and when I touch the pad and the capacitance increases it would follow that the voltage would be lower and it would detect the touch.
My problem is that I get nothing out of the pin and it's not charging; my ADC value is always zero and on my scope it just shows 0 volts. I assume that my CTMU is not turning on, as the ADC cap should at least charge with it. I've searched the internet and Microchip forums and haven't found many people having problems so I think I must be making a simple mistake.
#define CLK 8000000L //8MHZ
#define FCY (CLK/2)
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <libpic30.h>
//#include "p24Fxxxx.h"
#include "uart.h"
#include "p24F04KA200.h"
#pragma config MCLRE = ON, GCP = OFF, FNOSC = FRC, FWDTEN = OFF, ICS = PGx2, PWRTEN = ON, OSCIOFNC = ON
void setup()
{
//setup CTMU
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 = 0; //edges are blocked
CTMUCONbits.EDGSEQEN = 0; //edge sequence not needed
CTMUCONbits.IDISSEN = 0; //Do not ground the current source
CTMUCONbits.CTTRIG = 0; //Trigger Output is disabled
CTMUCONbits.EDG2POL = 0;
CTMUCONbits.EDG2SEL = 0x3; //Edge2 Src = OC1 (don?t care)
CTMUCONbits.EDG1POL = 1;
CTMUCONbits.EDG1SEL = 0x3; //Edge1 Src = Timer1 (don?t care)
//CTMUICON
CTMUICONbits.ITRIM = 0x3F; //Maximum Positive Adjustment
CTMUICONbits.IRNG = 0x3; //55 uA
CTMUCONbits.CTMUEN = 1; //Enable CTMU
//setup A/D converter
AD1PCFG = 0x0000;
AD1CON1 = 0x0000;
AD1CON1bits.FORM = 0x0; //Unsigned fractional format
AD1CON2 = 0x0000;
AD1CON3 = 0x0000; //bits.ADRC=0;
AD1CON3bits.SAMC = 0xB; //12 TAD
AD1CON3bits.ADCS = 0x60; //Used formula for ADCS with 12 TAD
AD1CHS = 0x04; //select the analog channel 4
AD1CSSL= 0x0000;
AD1CON1bits.ADON = 1; //Turn On A/D
}
unsigned short runCTMU()
{
AD1CON1bits.SAMP = 1; //Manual sampling start
CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
__delay_us(125); //wait 125us
CTMUCONbits.IDISSEN = 0; //end drain of circuit
CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit using CTMU current source
__delay_us(125); //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;
return ADC1BUF0;
}
unsigned short getVbaseline()
{
unsigned short vRead = 0;
for(k = 0; k < 50; k++)
{
vRead = vRead + runCTMU();
}
return (vRead/50);
}
void main()
{
unsigned short vRead;
unsigned short vBaseline;
setup();
//Set up sensor pin
TRISA = 0x2;
AD1CHS = 0x4; //select AN04 as input
AD1PCFG = ~(0x4);
//get untouched value on start up
vBaseline = getVbaseline();
while(1)
{
vRead = runCTMU();
//Touch sensed
if (vRead < vBaseline)
{
LATAbits.LATA4 = 1; //output LED
//Send ADC value over UART
UART1PutChar(vRead >> 1);
UART1PutChar(vRead);
}
else //Touch not sensed
{
LATAbits.LATA4 = 0;
}
}
}
I've used this Application Note for code examples.
Best Answer
I just ran across this very old (and unanswered) question during a Google search.
The problem is that during setup, the CTMU is disabled, but it is never re-enabled:
CTMUCONbits.CTMUEN = 0; //make sure CTMU is disabled
At the very beginning of your runCTMU function, you should have:
CTMUCONbits.CTMUEN = 1; //make sure CTMU is enabled
And then disable it again just before your return in that function.