Autor Tema: mTOUCH con pic16f88x y CCSC c  (Leído 4943 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado epir

  • PIC10
  • *
  • Mensajes: 8
mTOUCH con pic16f88x y CCSC c
« en: 14 de Marzo de 2012, 18:36:16 »
Bueno después de tanto buscar y leer algunos temas de ayuda de microchip por fin logre echar andar el proyecto de teclado de detección capacitiva y como en este foro he encontrado mucha ayuda pues lo menos que puedo es colaborar con toda la gente que propone sus temas y proyectos con el fin de ayudar a los demás.

Les dejo un programa con el PIC 16F887 para detección capacitiva, en el cual se emplean los dos comparadores que este trae en conjunto con el Timer1  para conteo de pulsos y el timer0 para control del periodo, como se observa en al figura despues del codigo.


 
Este información está disponible en las notas de ayuda de microchip Nota AN110, AN1102, AN1103 y AN1101. Basado en esta información se realizo el programa tanto para el PIC16F887, con detección por frecuencia junto con  latch SR como  por CVD para el PIC12F683.  El esquematico esta en la nota en la que dejo el hipervinculo, aunque en este caso no se monto la LCD.

Aqui el programa para el PIC16F887 en CCSc
Código: [Seleccionar]

/*
NOMBRE:
--------
MTOUCHFF.C

Realizado por:
--------------
Edpilo

Objetivo:
----------

Este programa se hace con el fin de implementar detección capacitiva implementando frecuencia, este método
se basa en la idea de tener una frecuencia base y un contador de pulsos. Se crea un periodo fijo en el
cual se toma un conteo de pulsos que en promedio es el mismo si la frecuencia no cambia, ese es el principio
fundamenta, ya que al cambiar la frecuencia disminuye el conteo de pulsos, por esta razón siempre se emplean 2
timer; en el primero se fija el periodo y en el segundo se realiza el conteo de pulsos.

Esto se logra aprovechando que las teclas generan una capacitancia parasita mas la capacitancia producida al colocar
el dedo en la placa este cambia la capacitancia y por ende la frecuencia.


NOTA:

-Para entender el concepto completo dirigirse a las notas de microchip
 AN1101, AN1102, AN1103 y AN1104
 
-La trama de datos se ha organizado para poder emplear la herramienta de microchip
 mtouch CVD framework PIC16F.


*/

#include <16F887.h>
#fuses INTRC,WDT,NOPROTECT,BROWNOUT,PUT,NOLVP,NOFCMEN,NOIESO,NODEBUG
#use delay(clock=8000000,restart_wdt)
#use RS232(BAUD=115200, BITS=8, PARITY=N, XMIT=PIN_C6, RCV=PIN_C7, RESTART_WDT,ERRORS)


#byte port_a=5
#byte port_b=6
#byte port_c=7
#byte port_d=8
#byte port_e=9

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)

#byte INTCON=0X0B          //Registro de control de interrupciones
#byte CM1CON0=0x107        //Registro de control del comparador 1
#byte CM2CON0=0X108        //Registro de control del comparador 2
#byte CM2CON1=0X109        //Registro de control 2 del comparador 2
#byte VRCON=0X097          //Registro de control del voltaje de referencia del comparador  
#byte SRCON=0X185          //Registro de control del latc SR
#byte ANSEL=0X188          //Registro de control de configuracion de entradas analogas
#byte ANSELH=0X189         //Registro de control 2 de entradas analogas.


//////////////////////////////////// VARIABLES ///////////////////////////////////////////
//-------------------- hardware
#define led    PIN_B2
#define led4   PIN_B4
#define led3   PIN_B5
#define led2   PIN_B6
#define led1   PIN_B7
#define pul    PIN_B0

//---------------------constantes hardware
#define hyst   14

//----------------------Variables ram
signed long int average[4]={0,0,0,0};  
long int lecturas[4]={0,0,0,0};  
long int trip[4]={23,34,33,16};           //La diferencia entre el maximo y valor minimo con el dedo presionado y a esta se le sac el 80%.
long int raw=0;
int      index=0;
short    bandera=0;
int    prueba=0;


//Banderas para indicar si hay no presionado boton
struct {
 byte BTN0:1;
 byte BTN1:1;
 byte BTN2:1;
 byte BTN3:1;
 
 }Buttons;    


//En la siguiente variables se organizan los bits de cada registro de control de los comparadores.
/*Para el comparador 1:

En cada caso se activa el comparador(C1ON) y se hace que su salida sea invertida (C1POL). Igualmente se seleciona el
canal con el mux para cada comparador (Recordar que esta familia trae 2 comparadores con cuatro entradas),
para que cada pin C12INx-  del comparador 1 se conecte con C1VIN- del comparador 1.  
Muy importante el bit(C1R), con el cual se selecciona tanto la referencia externa pin (C1Vin+) como la interna
C1Vref. En este caso se ha configura internamente a la salida de C1Vref, este voltaje de referencia se fija con
el registro VRCON aprosimadamente en 2/3 de Vdd.  

Para el comparador 2.

Igua que en el anterior en cada caso se activa el comparador (C2ON), se hace que su salida sea no invertida (C2POL), se
habilita la salida del comparador (C2OUT); cuidado, se debe configura A5 o el pin que corresponda como salida. Este comparador tambien
es posible conectarle su voltaje de referencia tanto extenamente (C2IN+) como internamente(V2REF), en este caso (C2R) se configura
para que  para que el pin  C2IN+(RA2) se conecte con C2VIN del comparador o le que seria que la referencia sera externa.  En este caso
se conecta el oscilador RC tal cual como se encuentra en las datasheet AN1101, AN1102,AN1103 y AN1104 de microchip.


*/

                //C12INx
int COMP1[4] = {0x94, 0x95, 0x96, 0x97};  
int COMP2[4] = {0xA0, 0xA1, 0xA2, 0xA3};

///////////////////////////////////////////////////////////////////////////////
/*
Subrutina para configurar los diferentes registros empleados para la deteccion capacitiva.
*/
void config_hard()
{
   setup_adc_ports(sAN0|sAN1|sAN2|sAN9|sAN10);        //Se configura en el registro ANSEL y ANSELH las entradas analogas.
   set_tris_a(0b00000111);   //RA0,RA1 (C12IN<0:1>)  y RA2 (C2IN+)  como entradas el resto salidas
   set_tris_b(0b00001011);   //RB2 y RB3 como entradas analogas (C12IN<3:2>) el resto salidas
   set_tris_c(0b10000001);   //RC0 entrada (T1CKI), RC7 entrada (rs232), el resto salidas
   set_tris_d(0);            //salidas
   set_tris_e(0);            //salidas
  
   CM1CON0=COMP1[0];         //Se configura el canal C12IN0
   CM2CON0=COMP2[0];         //Se configura el canal C12IN0
   CM2CON1=0X20;             //Se conecta CVref a la entrada de C1Vin+ del comparador 1
   SRCON=0XF0;               //En este registro se comfigura para que la salida del comparador 2 se conecte con /Q y el comparador 1 con Q y ambos
                             //empleen el latch SR.  
   VRCON=0X86;               //Se activa Vref para el comparador 1 (VREN), se activa (VRR) para alto rango formula con la que se determina
                             //el votaje de referencia para este caso: Vdd/4 + (VR<3:0>/32)*Vdd => 5/4+(6/32)*5=2.1875, VR se puede cambiar
                             //segun la tolerancia de los componentes RC empleados.  
    
   SETUP_TIMER_0(T0_INTERNAL | RTCC_DIV_64);  //Se configura el timer 0 con un prescaler de 32 (4) segun recomendacion AN1103
   SETUP_TIMER_1(T1_EXTERNAL|T1_DIV_BY_1 );   //Se activa el timer 1 para conteo de pulsos reloj externo sin prescaler.
   //SETUP_TIMER_1(T1_EXTERNAL|T1_GATE|T1_DIV_BY_1 );
   Buttons.BTN0 = 0;
   Buttons.BTN1 = 0;                                  //Bandera de botone en ceros                      
   Buttons.BTN2 = 0;
   Buttons.BTN3 = 0;
   port_b=0;
   port_a=0;
   port_c=0;
   port_d=0;
   port_e=0;
      
  
}

//---------------------------------------------------
void enviar(void)
{
     restart_wdt();    
printf("00000; ");
//printf("%05Ld; %05Ld; %05Ld; %05Ld\r\n",average[0],average[1],average[2],average[3]);  //Se envia esta trama para realizar los calculos
//printf("%05Ld; %05Ld; %05Ld; %05Ld\r\n",lecturas[0],lecturas[1],lecturas[2],lecturas[3]);  //deatos crudos sin promedio de cada lectura
printf("%05Ld; %05Ld; %05Ld; %05Ld\r\n",average[2],lecturas[2],average[3],lecturas[3]);  //para verificar promedio y datos crudos de dos botones.
bandera=0;


}
///////////////////////////////////////////////////////////////////////////////
void main()
{

   config_hard();

   output_high(LED);
   delay_ms(10);
   output_low(LED);
      
  
   INTCON=0;                        //No olvidar emplear esta instruacción antes de configurar cualquier vector de interrupción                                                                                      
   set_timer1(0);
   set_rtcc(0);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RTCC);
  

    
    while(true)
   {
       restart_wdt();               //Codigo para activar los leds de cada tecla
       if(Buttons.BTN0)
          output_high(LED1);
       else
          output_low(LED1);                          
       if(Buttons.BTN1)
          output_high(LED2);
       else
          output_low(LED2);  
          
       if(Buttons.BTN2)
          output_high(LED3);
       else
          output_low(LED3);
            
       if(Buttons.BTN3)
          output_high(LED4);
       else
          output_low(LED4);  
       if(bandera)
          enviar();  
          
    
       if(input(pul))                      //Entrada digital para pulsador
       {
        output_high(LED2);
        delay_ms(50);
        output_low(LED2);
        delay_ms(50);
        output_high(LED2);
        delay_ms(50);      
        output_low(LED2);
        delay_ms(50);    
       }          

    
    
        
   }    
  
  
}

////////////////////////////// INTERRUPCIONES /////////////////////////////////////

#INT_RTCC
void isr_timero(void)
{
    restart_wdt();
    raw=GET_TIMER1();  
    lecturas[index]=raw;
    //prueba++;  
    
 
    if (raw < (average[index] - trip[index]) ) //si
    {
    // Button Pressed
    // 1. Se setea el flag del Button segun el numero del index
    // 2. No se requiere realizar el codigo del promedio en esta acción
    // 1
       switch(index)
        {
            case 0:
              Buttons.BTN0 = 1;
            break;
            case 1:
              Buttons.BTN1 = 1;
            break;          
            case 2:
              Buttons.BTN2 = 1;
            break;          
            case 3:
              Buttons.BTN3 = 1;
            break;          
            
        }
   }
   else if (raw > (average[index] - (trip[index] - hyst)))
   {
        // Button unpressed
        // 1. se borra el flag de Boton segun el numero del index
        // 2. Se continua cargando datos al algorito de promedio en el tiempo (Promedio movil)
        
        // 1
        switch(index)
         {
            case 0:
              Buttons.BTN0 = 0;
            break;
            case 1:
             Buttons.BTN1 = 0;
            break;            
            case 2:
              Buttons.BTN2 = 0;
            break;            
            case 3:
              Buttons.BTN3 = 0;
            break;          
            
         }
        // 2          
        average[index] = average[index] + (raw-average[index])/16;
            
   }
  
    if(index < 3)
       index++;
    else
    {
        index=0;
        bandera=1;
    }
   CM1CON0=COMP1[index];
   CM2CON0=COMP2[index];      
   set_timer1(0);
   set_rtcc(0);
}


/*
PARA TENER EN CUENTA EN LA CONFIGURACIÓN


   Nota:  
  
   Como el timer1 puede ser controlado externamente por T1G o por el comparador 2, se debe tener cuidado en la configuración de los
   siguientes registros, si no se desea inhabiliar el Timer1 durante un conteo involuntariamente  por RB5/T1G, este pin se debe dejar como salida en ceros, de
   lo contrario si este pin se coloca en alto el timer1 no cuenta, con las siguiente configuracion.
  
   Solución:  
   ---------
   Luego es posible dejar este pin como entrada y de esta manera no se inhabilitara el timer1 por conteo, al terminar de usar timer1
   el pin se puede configurar como sea.  
  
   Opcion 1        
   si       CM2CON1=0B00100010
                            ||
                            | - CSYNC=0 Salida sincrona con flanco de bajado timer1
                             ---T1GSS=1 Fuente de disparo externa T1G
   y con
              T1CON=0B01000111
                       |   |||
                       |   || --TMRON=1  Timer1 habilitado
                       |   | ---TMR1CS=1 Fuente de reloj externo  
                       |    --- T1SYNC=1 No sincronizado
                        --------TMR1GE=1 Conteo del timer 1 controlado por la funcion de disparo (Gate function)  SETUP_TIMER_1(T1_EXTERNAL|T1_GATE|T1_DIV_BY_1 );
              
  
   -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------                        
  Opcion 2
  
  O se puede evitar inhabilitar timer1 por conteo por RB5/T1G con la siguiente configuracioa pero el pin RB5/T1G se vera afectado por la convinacion comparador2 y timer1, si el pin esta configurado
  como salida. Por lo tanto se debe tener cuidado con el hardware conectado a este pin ya que al ponerlo en alto, se ve reflejada la salida del comparador 2 por este pin.
                                  
   si       CM2CON1=0B00100000
                            ||
                            | - CSYNC=0 Salida sincrona con flanco de bajado timer1
                             ---T1GSS=0 fuente de disparo timer1 es SYNCC2OUT
   y con
              T1CON=0B01000111
                       |   |||
                       |   || --TMRON=1  Timer1 habilitado
                       |   | ---TMR1CS=1 Fuente de reloj externo  
                       |    --- T1SYNC=1 No sincronizado
                        --------TMR1GE=1 Conteo del timer 1 controlado por la funcion de disparo (Gate function)  SETUP_TIMER_1(T1_EXTERNAL|T1_GATE|T1_DIV_BY_1 );
   -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------                          
   Opcion 3
  
   Tambien con esta otra configuración, con la cual esta este programa.                        
   si       CM2CON1=0B00100000
                            ||
                            | - CSYNC=0 Salida sincrona con flanco de bajado timer1
                             ---T1GSS=0 fuente de disparo timer1 es SYNCC2OUT
   y con
              T1CON=0B00000111
                       |   |||
                       |   || --TMRON=1  Timer1 habilitado
                       |   | ---TMR1CS=1 Fuente de reloj externo  
                       |    --- T1SYNC=1 No sincronizado
                        --------TMR1GE=0 Timer1 configurado para conteo  SETUP_TIMER_1(T1_EXTERNAL|T1_DIV_BY_1 );
                            

  



*/

« Última modificación: 15 de Marzo de 2012, 01:34:40 por epir »

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #1 en: 14 de Marzo de 2012, 18:50:51 »
un video de como funciona ;-)
hasta que distancia logras detectar si le pones otro dielectrico sobre tus teclas?
"Nada es imposible, no si puedes imaginarlo"

Desconectado epir

  • PIC10
  • *
  • Mensajes: 8
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #2 en: 14 de Marzo de 2012, 19:05:25 »
un video de como funciona ;-)
hasta que distancia logras detectar si le pones otro dielectrico sobre tus teclas?


Bueno las teclas se diseñaron segun AN1103 y estoy utilizando acrilico de un espesor de 3mm sobre la placa impresa, para verificar los datos empleo la herramienta de Microchip mtouch CVD framework para PIC16f

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #3 en: 14 de Marzo de 2012, 19:49:14 »
Al menos una imagen de tu placa funcionando, si no es molestia, podrías poner aquí??
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado epir

  • PIC10
  • *
  • Mensajes: 8
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #4 en: 15 de Marzo de 2012, 01:20:10 »
Al menos una imagen de tu placa funcionando, si no es molestia, podrías poner aquí??

Publique el articulo por que estoy trabajando en este proyecto y funciona muy bien,  realize un teclado y todo esta montado en protoboar.  Hasta el momento no hay un diseño final ya que estamos evaluando todos los pic con entradas de detección capacitiva, ahora llegan los pic que traen los modulos CSM y CTMU. Como lo que se esta evaluando es para trabajar con recubrimiento metalico estamos en etapa de diseño.   Aquí encontre un tema relacionado con el pic16f727, no lo he probado por que no tengo aun el tema pero basado en lo que he probado el programa se ve que funciona.   
El motivo de no pubicar placa es por que el diseño se habia contemplado con el PIC16F883, el cual adquirimos uno pocos, el problema fue que al programar ninguno se reconocio y por eso se tomo el PIC16F887 para realizar la practica.

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #5 en: 15 de Marzo de 2012, 08:35:44 »
Si la detección va a ser con recubrimiento metálico, va a ser el primero en utilizarla aquí, seria interesante que lo compartas, en este o en nuevo hilo...
Es interesante por donde lo mires...
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado adolfoly

  • PIC10
  • *
  • Mensajes: 1
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #6 en: 08 de Abril de 2012, 03:52:20 »
Hola epir

esta muy interesante tu artículo, quisiera entender mas a fondo de como funciona el sensor capacitivo con el PIC16F887

sabes de algún manual en español o podrías colocar tu esquemático completo para analizarlo?

tu programa se puede correr en "mickroC PRO for PIC"

Gracias

Desconectado juliozv

  • PIC10
  • *
  • Mensajes: 37
Re: mTOUCH con pic16f88x y CCSC c
« Respuesta #7 en: 09 de Abril de 2012, 00:16:03 »
Esto esta exelente, considerando que es un plus al poder utilizar este MCU para estas funciones, esperamos nuevas publicaciones sobre este tema ya que es parte aguas para los que deseamos incluir botones touch.
Firma en Construcción!


 

anything