¿Cómo usar la CTMU (Unidad de medición del tiempo de carga) para un sensor táctil capacitivo en el PIC24F?

5

Estoy tratando de implementar un sensor táctil básico utilizando el CTMU en mi PIC24F04KA200. Al leer la hoja de datos y las notas de aplicación proporcionadas por Microchip, esperaba que esto fuera una tarea fácil. En esta pregunta, solo explicaré lo que estoy haciendo, publicaré mi código C y espero que alguien pueda indicarme la dirección correcta.

He conectado mi sensor, que es una placa de cobre sobre el material de la placa PCB del tamaño de una tarjeta postal. El tipo de cosas que compra para hacer su propia placa de circuito. He conectado esto a la clavija AN4 (RA2). Tengo un LED y una resistencia limitadora de corriente conectada a RA4. Los únicos otros elementos del circuito que tengo son una tapa de desacoplamiento .1uF en los pines de alimentación y el PicKit3 que alimenta el circuito (también lo he intentado con una fuente de alimentación separada).

Todo lo que he intentado hacer es seguir el ejemplo de código dado por Microchip y esencialmente encender la fuente de corriente para permitir que mi almohadilla de cobre cargue y mida el voltaje con A / D (como se explica en la Nota de la aplicación) y cuando Toco la almohadilla y la capacitancia aumenta, lo que seguiría si el voltaje fuera más bajo y detectaría el toque.

Mi problema es que no saco nada del pin y no se está cargando; mi valor de ADC es siempre cero y en mi alcance solo muestra 0 voltios. Supongo que mi CTMU no se enciende, ya que la tapa del ADC debería al menos cargarse con ella. He buscado en los foros de Internet y Microchip y no he encontrado muchas personas que tengan problemas, así que creo que debo estar cometiendo un simple error.

#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;
        }

    }
}

He usado esta Nota de aplicación para ejemplos de código.

    
pregunta Josh

1 respuesta

-1
#include <stdint.h>
#include <stdio.h>
#include <libpic30.h>
#include "p24FJ64GB004.h"
#include "CTMU.h"
#include "main.h"

void InitCTMU(void){

    /**************setup CTMU*************/
     //CTMUCON
    CTMUCONbits.CTMUEN = 0; //make sure CTMU is disabled
    CTMUCONbits.CTMUSIDL = 1; //Discontinue module operation when device enters 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
    CTMUICON = 0x300; //55uA
    CTMUICONbits.ITRIM = 0; //Nominal - No Adjustment

    /***************setup A/D converter************///////////////
    AD1PCFGL = 0xEFFF; //chanel 12
    TRISCbits.TRISC3=1;
    AD1CON1 = 0x0000;
    AD1CHS = 0x000C; //Channel 0 positive input is AN12
    AD1CSSL=0x0000; //Analog channel is disabled from input scan
    AD1CON1bits.ADSIDL = 1; //Discontinue module operation when device enters Idle mode
    AD1CON1bits.FORM = 0x0; //Integer (0000 00dd dddd dddd)
    AD1CON3bits.ADRC = 0; // Clock derived from system clock
    AD1CON3bits.SAMC = 0b10000; //16TAD
    AD1CON3bits.ADCS = 0x01; //2Tcy
    AD1CON2 = 0x0000; //Interrupts are at the completion of conversion for each sample/convert sequence
    AD1CON1bits.ADON = 1; //Turn On A/D
    CTMUCONbits.CTMUEN = 1; //Enable CTMU
}

unsigned int runCTMU(void){

    uint16_t immediateValue;

    CTMUCONbits.IDISSEN = 1; //drain charge on the circuit
    __delay32(80); //wait 20us
    CTMUCONbits.IDISSEN = 0; //end drain of circuit
    Nop(); Nop();
    IFS0bits.AD1IF = 0; //Make sure A/D interrupt flag = 0
    AD1CON1bits.SAMP = 1; //Manual sampling start
    CTMUCONbits.EDG2STAT = 0;
    CTMUCONbits.EDG1STAT = 1; //Begin charging the circuit using CTMU current source
    __delay32(40); //wait for 10us
    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
    immediateValue = ADC1BUF0;
    AD1CON1bits.SAMP = 0;
    IFS0bits.AD1IF = 0;
    AD1CON1bits.DONE = 0; //Make sure A/D bits are cleared

    return immediateValue;
}

unsigned int getVbaseline(void){

    unsigned int vRead = 0, k;

    for(k = 0; k < 50; k++){
        vRead = vRead + runCTMU();
    }

    return (vRead/50);
}
    
respondido por el user35591

Lea otras preguntas en las etiquetas