6 votos

¿Cómo utilizar la CTMU (Charge Time Measurement Unit) para un sensor táctil capacitivo en el PIC24F?

Estoy tratando de implementar un sensor táctil básico utilizando el CTMU en mi PIC24F04KA200. Leyendo la hoja de datos y las notas de aplicación proporcionadas por Microchip esperaba que esto fuera un esfuerzo fácil. En esta pregunta me limitaré a 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 en la parte superior de material de placa de circuito impreso del tamaño de una tarjeta postal. El tipo de cosa que usted compra para DIY su propia placa de circuito. He conectado esto al pin AN4(RA2). Tengo un LED y una resistencia limitadora de corriente conectados a RA4. Los únicos otros elementos del circuito que tengo son una tapa de desacoplamiento de .1uF en los pines de alimentación y el PicKit3 alimentando el circuito (también he probado con una fuente de alimentación independiente).

Lo único que he intentado hacer es seguir el ejemplo de código que da Microchip y esencialmente encender la fuente de corriente para que mi almohadilla de cobre se cargue y medir el voltaje con el A/D (como se explica en la App Note) y cuando toque la almohadilla y la capacitancia aumente se deduciría que el voltaje sería menor y detectaría el toque.

Mi problema es que no obtengo nada del pin y no se está cargando; el valor de mi ADC es siempre cero y en mi osciloscopio sólo muestra 0 voltios. Supongo que mi CTMU no se está encendiendo, ya que la tapa del ADC debería al menos cargarse con él. He buscado en internet y en los foros de Microchip y no he encontrado mucha gente con 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 utilizado este Nota de aplicación para ver ejemplos de código.

2voto

Acabo de encontrarme con esta pregunta tan antigua (y sin respuesta) durante una búsqueda en Google.

El problema es que durante la configuración, la CTMU se desactiva, pero nunca se vuelve a activar:

CTMUCONbits.CTMUEN = 0; //asegurarse de que la CTMU está desactivada

Al principio de su función runCTMU, debería tener:

CTMUCONbits.CTMUEN = 1; //asegurarse de que la CTMU está habilitada

Y luego desactivarlo de nuevo justo antes de su retorno en esa función.

1voto

boxofrats Puntos 692
#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);
}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X