mTouch™ un teclado capacitivo con sólo un PIC


Entre los últimos PIC’s que Microchip ha sacado al mercado destaca la incorporación del módulo de sensado capacitivo mTouch™ que incluye todo el hardware necesario para realizar un teclado capacitivo con sólo pintar las pistas correspondientes a los botones.

EL primer paso para comenzar es, evidentemente, ir a la página de Microchip y revisar la última información publicada al respecto. aquí

En mi caso surgió la posibilidad de cambiar un teclado tradicional PS2 por este nuevo sistema, por lo que monte mi prototipo con un 16LF272 y comencé a probar con el código que Michochip facilita (sí, claro, antes hay que leer los datasheets, AN,..) el caso es que contenía más de un fallo que lo hace inoperativo… por eso esta primera entrada en el blog, para dejar un código que si funciona a quien le pueda venir bien, seguro que a los que empezáis con el tema os ahorra alguna que otra horas de trabajo…

Este primer diseño ha sido ejecutado siguiendo las recomendaciones del las AN de Microchip con un excelente resultado, asi quedó la tarjeta prototipo:

Este es el aspecto del PCB del prototipo, con los componentes en una cara y los pads en la otra, por último un conector soldado directamente al micro para depurar con REAL ICE.

El código está para compilarlo con CCS, que viene gratis en el MPLAB.

//****************************************************************************//
// Nombre:  tecladocap.c
// Autor: Félix Sasián
// Fecha: enero 2009
// Proposito: mostrar el uso del modulo de sensado capacitivo
// este programa escanea el estado de las 16 entradas del pic 16LF727
// con un intervalo fijo. Se hace una media de la frecuencia del teclado en reposo
// y cuando se toca un PAD la frecuencia cambia por la capacitancia del dedo.
// Cuando se pulsa una tecla se enciende un led y se envía la tecla pulsada por
// el puerto serie. El sistema se queda a la espera de que se suelte la tecla.
//
// Es muy sencillo modificar este programa para poder detectar varias teclas
// pulsadas de forma simultanea.
//
//****************************************************************************//
#include <16LF727.h>

#include

#FUSES HS                        //Cristal de 8 Mhz
#FUSES NOWDT                     //Sin Watch Dog Timer
#FUSES NOPROTECT                 //Código abierto
#FUSES PLLEN                     //Habilita PLL
#FUSES NODEBUG                   //No Debug
#FUSES NOMCLR                    //NO Master Clear pin
#FUSES NOBROWNOUT                //No brownout reset
#FUSES NOPUT                     //No Power Up Timer

//configurar los ‘delays’
#use delay(clock=8000000)
//configuración del puerto serie
#use rs232(baud=19200, xmit=PIN_C6,rcv=PIN_C7)

//****************************************************************************//
//*   DEFINICIONES
//****************************************************************************//
int16   timer1_val[NUMSENSORES];
int16   timer1_raw[NUMSENSORES];
int16   media_boton[NUMSENSORES];
int16   trip_val[NUMSENSORES];
char pasadas_estabilizacion;
char pasadas_media;
char num_sensor;
char tecla;
//****************************************************************************//
//*   PROTOTIPOS
//****************************************************************************//
void init(void);
void timers_isr(void);
void reset_timer1(void);
void selecciona_siguiente_sensor(void);

//****************************************************************************//
//*   FUNCION DE INICIALIZACION
//****************************************************************************//
void init()
{
char x;
setup_adc_ports( ALL_ANALOG );
OSCCON = 0×30;   //16 MHz with PLLEN

// INICIALIZAR LOS TIMERS
OPTION = 0xC3;
T0IF = 0;
T0IE = 1;
T1CON = 0xC5;
T1GCON = 0xE1;

//INICIALIZAR EL MODULO CAPACITIVO
CPSCON0 = 0b10001100;
CPSCON1 = 0;

//INICIALIZAR LAS VARIABLES
pasadas_estabilizacion = PASES_ESTABILIZACION;
pasadas_media = PASES_MEDIA;

for(x = 0; x < NUMSENSORES; x++)
{
trip_val[x] = UMBRAL;
media_boton[x] = 0;
}

// Gate Setup
TMR1GIF   = 0;                   // borra el gate interrup flag
TMR1GIE   = 1;                   // habilita la gate interrup
PEIE      = 1;                   // habilita las peripheral intpts
GIE       = 1;                   // habilita las global intpts

// APAGA EL LED
output_low(LED);
}
//****************************************************************************//
// ISR() RUTINA DE INTERRUPCION
//****************************************************************************//

#INT_DEFAULT                     // Interrupciones
void timers_isr()
{
if (T0IF==1)                  // Timer0
{
T0IF = 0;               // limpia el  interrup flag
}

if(TMR1GIF==1)                // Timer1 gate
{
TMR1GIF = 0;               // limpia el interrup flag
TMR1ON = 0;                // TIMER1 off

timer1_val[num_sensor] = make16(TMR1H,TMR1L);
timer1_raw[num_sensor] = timer1_val[num_sensor] * 16;
//estabilizar el valor de media_boton
if(pasadas_estabilizacion > 0×00)
{
pasadas_estabilizacion–;
media_boton[num_sensor] = timer1_raw[num_sensor];

if((pasadas_estabilizacion == 0) && (num_sensor < (NUMSENSORES - 1)))
{
pasadas_estabilizacion = PASES_ESTABILIZACION;
selecciona_siguiente_sensor();
}

}
else
{
//buscar botones pulsados
if(timer1_raw[num_sensor] < (media_boton[num_sensor] - trip_val[num_sensor]))
{
tecla=num_sensor+1;
}
else if(timer1_raw[num_sensor] > (media_boton[num_sensor] - trip_val[num_sensor])+ VALOR_HISTERESIS)
{
tecla=0;
if(timer1_raw[num_sensor] > (media_boton[num_sensor]))
{
media_boton[num_sensor] = media_boton[num_sensor] + (timer1_val[num_sensor] - (media_boton[num_sensor] / 16));
}
//calcular la media
pasadas_media–;
if(pasadas_media == 0)
{
media_boton[num_sensor] = media_boton[num_sensor] + (timer1_val[num_sensor] - (media_boton[num_sensor] / 16));
pasadas_media = PASES_MEDIA;
selecciona_siguiente_sensor();
}
}
}
reset_timer1();
}
}

//****************************************************************************//
//*   RESET DEL TIMER1
//****************************************************************************//
void reset_timer1()
{
TMR1L   = 0;
TMR1H   = 0;
TMR1ON  = 1;
}

//****************************************************************************//
//*   SELECCIONAR SIGUIENTE CANAL CPS
//****************************************************************************//
void selecciona_siguiente_sensor()
{
num_sensor++;
if(num_sensor >= NUMSENSORES)
{
num_sensor = 0;
}
CPSCON1 = num_sensor;    //Selecciona el siguiente pin CPS0..CPS15
}

//****************************************************************************//
//*   BUCLE PRINCIPAL
//****************************************************************************//
void main(void)
{
char tecla1;
Init();
num_sensor = 0;          // comenzamos con el primer canal

while(true)
{
GIE       = 0;
tecla1=tecla;
GIE       = 1;
if (tecla1>0) //si se localiza una tecla pulsada
{
output_high(LED); //enciende el led
printf(”T%c”,tecla1); //lo envia por el puerto serie
delay_ms(100);
}

while(tecla1>0) //espera que se suelten todas las teclas
{
GIE       = 0;
tecla1=tecla;
GIE       = 1;
delay_ms(50);
}
output_low(LED); //apagar el led
}
}

//****************************************************************************//
// nombre:  tecladocap.h
// Autor: Félix Sasián
// Fecha: enero 2009
// Proposito: mostrar el uso del modulo de sensado capacitivo
//****************************************************************************//

//*********************definiciones del registro ************************
#byte OSCCON = 0×90
#byte OPTION = 0×81
#byte T1CON = 0×10
#byte T1GCON = 0×8f
#byte CPSCON0 = 0×108
#byte INTCON = 0×0b
#byte CPSCON1 = 0×109
#byte PIE1 = 0×8c
#byte PIR1 = 0×0c
#byte TMR1L = 0×0e
#byte TMR1H = 0×0f

// T1CON bits
#bit TMR1ON = T1CON.0

// INTCON bits
#bit GIE = INTCON.7
#bit PEIE = INTCON.6
#bit T0IE = INTCON.5
#bit T0IF = INTCON.2

// PIE1 bits
#bit TMR1GIE = PIE1.7

// PIR1 bits
#bit TMR1GIF = PIR1.7

//****************************************************************************//
//   DEFINICIONES
//****************************************************************************//
#define   NUMSENSORES          16
#define   PASES_MEDIA      3
#define   PASES_ESTABILIZACION     50
#define   VALOR_HISTERESIS    30
#define   UMBRAL    220
//****************************************************************************//
//*   DEFINICIONES DE I/O
//****************************************************************************//

#define LED            PIN_C1

Espero que sea útil

One Response to “mTouch™ un teclado capacitivo con sólo un PIC”

  1. MJose Says:

    Hola ,
    Quisiera contactar contigo para poder comentarte acerca de un proyecto de laboratorio. Gracias

Leave a Reply

You must be logged in to post a comment.