PICmicro & dsPIC >> PICmicro & dsPIC

Pages: 1
twiga
stranger


Reged: Aug 18 2009
Posts: 2
CapSense - mTouch
      #133332 - Thu Nov 05 2009 04:02 AM

Has anyone tried capacitive touch (mTouch) using the newly released 16F1937 chip? I downloaded a sample project from microchip that works for the 737 chip, but I can't get it working on the new chip. It compiles, but the buttons don't work.

Post Extras: Print Post   Remind Me!   Notify Moderator  
twiga
stranger


Reged: Aug 18 2009
Posts: 2
Re: CapSense - mTouch [Re: twiga]
      #133342 - Thu Nov 05 2009 04:06 AM

Here is the code I have, using the 9.7 compiler.

Code:

// *****************************************************************************
// Filename: Main727.c
// Date: Dec. 13, 2007
// Purpose: Illustrate the use of the Capacitive Sensing Module
// This program scans 16 pads on a PCB. Each pad is sensed by the Capacitive
// Sensing Module at a fixed interval. The frequency of each pad at rest is averaged.l
// When a pad is touched, the frequency on the Cap. sensing module changes due to the
// extra capacitance from the finger. The change in frequency is noted and the LEDs
// light up to indicate which button was pressed.
// *****************************************************************************
//
// Compiler: Hi-Tech PIC-C v.9.60
// *****************************************************************************

#include
#include "Cap_Sense.h"

#define METHOD 2 // 1= Timer0 Base; 2= Timer2 Base; 3= WDT base; 4=WDT Sleep Base

#if METHOD == 4
//__CONFIG(INTIO & WDTEN & PWRTEN & MCLRDIS & UNPROTECT);
#else
//__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT);
#endif

__CONFIG (FOSC_INTOSC & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
__CONFIG (WRT_OFF & VCAPEN_OFF & PLLEN_OFF & STVREN_ON & BORV_19 & DEBUG_OFF & LVP_OFF);


/** Variables **/

bank1 unsigned int reading[NUM_BTTNS]; // current reading for each button
bank1 unsigned int average[NUM_BTTNS]; // running average for each button
bank1 unsigned int threshold; // threshold value is req'd # counts decrease from avg
unsigned char index; // index value relates ea. button and scanning sequence

bank2 unsigned int threshold128; // Threshold of 1/128th = 1/128th of the average value
bank2 unsigned int threshold64; // ... used in computation of threshold variable
bank2 unsigned int threshold32; // ... threshold is a selection of the sum of these
bank2 unsigned int threshold16; // "
bank2 unsigned int threshold8; // "
bank2 unsigned int threshold4; // "
bank2 unsigned int threshold2; // Threshold value for 1/2

FFlags Flags; // Flags struct variable contains application status
BButtons Buttons; // Buttons struct variable indicates button presses

unsigned int bigval; // current button bigval - for averaging technique
unsigned int smallavg; // current button smallavg - for averaging technique

/** Constants **/



/** Prototypes **/
void Init(void);
void RestartTimers(void);
void RestartTimer1(void);
void SetNextChannel(void);
void CapInit(void);
void DisplayLEDs(char i);
void interrupt isr(void);
void SLEEP_NOP(void);
void beep(void);

/*====================================================================
======================== PROGRAM CODE ==============================
====================================================================*/

//*********************************************************************
// main() ************************************************************
// Main loop. Will turn on the LEDs based on button detected during**
// ISR execution. ***********************************************
// ********************************************************************
void main(void) {

Init();
CLRWDT();
index = 0; // Begin program scanning channel 0

beep();

while (1) { // Loop forever

// React to button presses in application main-loop
if (Buttons.BTN0)
beep();//DisplayLEDs(0); // Structuring code based off each button takes up
if (Buttons.BTN1) // more application code, but reduces isr code.
beep();//DisplayLEDs(1); // IFt also allows reaction to different buttons at
if (Buttons.BTN2) // the same time.
beep();//DisplayLEDs(2);
if (Buttons.BTN3) // ALTERNATIVE:
beep();//DisplayLEDs(3); // For ea. case in the isr, create and set a variable
if (Buttons.BTN4) // called 'button_pressed' s.t. button_pressed=index.
beep();//DisplayLEDs(4); // Then, main loop code would simply require:
if (Buttons.BTN5) // DisplayLEDs(button_pressed);
beep();//DisplayLEDs(5);
if (Buttons.BTN6)
beep();//DisplayLEDs(6);
if (Buttons.BTN7)
beep();//DisplayLEDs(7);
if (Buttons.BTN8)
beep();//DisplayLEDs(8);
if (Buttons.BTN9)
beep();//DisplayLEDs(9);
if (Buttons.BTN10)
beep();//DisplayLEDs(10);
if (Buttons.BTN11)
beep();//DisplayLEDs(11);
if (Buttons.BTN12)
beep();//DisplayLEDs(12);
if (Buttons.BTN13)
beep();//DisplayLEDs(13);
if (Buttons.BTN14)
beep();//DisplayLEDs(14);
if (Buttons.BTN15)
beep();//DisplayLEDs(15);

#if METHOD == 4
SLEEP_NOP();
#endif
}
}



// ************************************************************************************
// Function: Init() *******************************************************************
// Purpose: Initialize PORTS, Capacitive Sensing Module and Selected Time Base
// ************************************************************************************
void Init(void)
{

// *********************************************************************************
// PORT and LED Setup **************************************************************
//**********************************************************************************
// Pin usage for this sample application
//--------------------------------------------------------------------------
// 7 6 5 4 3 2 1 0 |
// PORTA . . CPS7 CPS6 . . LED LED |
// PORTB . . CPS5 CPS4 CPS3 CPS2 CPS1 CPS0 |
// PORTC . . . . . . . . |
// PORTD CPS15 CPS14 CPS13 CPS12 CPS11 CPS10 CPS9 CPS8 |
// PORTE X X X X . LED . LED |
//--------------------------------------------------------------------------

TRISA0 = ANSA0 = 0; // Set LED outs as digital outputs
TRISE2 = ANSE2 = 0; // All others remain as inputs (default)
TRISE0 = ANSE0 = 0;
TRISA1 = ANSA1 = 0;
LED0 = OFF; // Init to off state
LED1 = OFF; // ..
LED2 = OFF; // ..
LED3 = OFF; // ..

TRISA |= 0b00110000; // Set as analog inputs
ANSELA |= 0b00110000; // (should be default)
TRISB |= 0b00111111; // "
ANSELB |= 0b00111111; // "
TRISD |= 0b11111111; // "
ANSELD |= 0b11111111; // "

OSCTUNE = 0b00100000;
//OSCCON = 0x70;
// *********************************************************************************
// Initialize Cap Module
// *********************************************************************************

CapInit();


GIE = 1;
}

void beep()
{

unsigned char beep_counter;
TRISC1 = 0;
for (beep_counter=0;beep_counter<4;beep_counter++)
{
RC1 = 1;
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
RC1 = 0;
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
SLEEP_NOP();
}
RC1 = 0;
TRISC1 = 1;

}

//// *************************************************************************************
//// Function: SLEEP_NOP()
//// Purpose: Sleep function with NOP
//// *************************************************************************************
void SLEEP_NOP(void)
{
SLEEP();
#asm
NOP
#endasm
SLEEP();
#asm
NOP
#endasm

}


// *************************************************************************************
// Function: CapInit()
// Purpose: Initialize the Capacitive Sense Module and Time Base Modules
// *************************************************************************************

void CapInit(void)
{

// Set up variables
for (index=0; index<16; index++) {
average[index] = 0;
reading[index] = 0;
}
// ********************************************************************************
// Initialize for Timer0 time base ************************************************
// ********************************************************************************
#if METHOD==1 // Timer0 set as time base
OPTION_REG = 0b11000100; // Timer0 init
TMR0IF = 0; // enable tmr0 intpt
TMR0IE = 1;
T1CON = 0b01000101; // Timer1 enable, system clock, 1:1 prescale,
T1GCON = 0b11100001; // Timer1 gate init
#endif

// ********************************************************************************
// Inititialize for Timer2 time base **********************************************
// ********************************************************************************
#if METHOD==2 // Timer2 set as time base
// Tmr2 setup
// module setup
T2CON = 0b00000100; // T2ON, prescale & postscale = 1:1
T2CON |=0b00000001; // adjust prescalar
T1CON = 0b01000101; // Timer1 enable, system clock, 1:1 prescale,
T1GCON = 0b11100001; // Timer1 gate init
T1GCON &=0b11111100; // clr T1GSS bits
T1GCON |=0b00000010; // set T1GSS for Timer2 match PR2
PR2 = 0xB4; // pr2 for use w/timer2 .. w/pres.1:4, 0xB4 sets 500us scan rate.
TMR2IF = 0;
TMR2IE = 1;
#endif

// **********************************************************************************
// Initialize for WDT time base *****************************************************
// **********************************************************************************
#if (METHOD==3 | METHOD==4)
OPTION_REG = 0b11001000; // Assign Prescaler to WDT
T1CON = 0b01000101; // Timer1 enable, system clock, 1:1 prescale,
T1GCON = 0b11100011; // Set T1GSS for WDT gate
#endif

// **********************************************************************************
// Cap Sense Module *****************************************************************
// **********************************************************************************
CPSCON0 = 0b10001100; // control settings
CPSCON1 = 0x00; // init to channel select = 0 (4 LSb's)
index = CPSCON1; // Start program ready to scan first channel

// **********************************************************************************
// Gate Setup ***********************************************************************
// **********************************************************************************
TMR1GIF = 0; // clear gate intpt flag
TMR1GIE = 1; // enable gate intpt
PEIE = 1; // enable peripheral intpts


}

//********************************************************************
// ISR() *************************************************************
// Interrupt Service Routine
// Reads values of TMR1 corresponding to each button/sensor
// and makes decision if button/sensor has been touched.
//********************************************************************
//********************************************************************

void interrupt isr(void)
{

CLRWDT();
// Timer0 Interrupt
// ...
if (TMR0IE && TMR0IF)
{
TMR0IF = 0; // Clear T0IF every time
}

// Timer2 Interrupt
// ...
if (TMR2IE && TMR2IF)
{
TMR2IF = 0; // Clear T2IF every time
}

// Timer1 Gate Interrupt

if (TMR1GIF && TMR1GIE)
{
// Perform touch reading

TMR1GIF = 0; // clear intpt flag
TMR1ON = 0; // Timer1 off

bigval = TMR1L + (unsigned int)(TMR1H << 8);
bigval = bigval * 16;
reading[index] = bigval;
smallavg = average[index] / 16;

threshold128 = average[index] >> 7; // avg >> 7 = 1/128 = 0.78% as a threshold value below average
threshold64 = average[index] >> 6; // avg >> 6 = 1/64 = 1.56% as a threshold value below average
threshold32 = average[index] >> 5; // avg >> 5 = 1/32 = 3.12% as a threshold value below average
threshold16 = average[index] >> 4; // avg >> 4 = 1/16 = 6.25% as a threshold value below average
threshold8 = average[index] >> 3; // avg >> 3 = 1/8 = 12.5% as a threshold value below average
threshold4 = average[index] >> 2; // avg >> 2 = 1/4 = 25% as a threshold value below average
threshold2 = average[index] >> 1; // avg >> 1 = 1/2 = 50% as a threshold value below average

threshold = threshold4; // ratiometric threshold from avail above (& combinations)

if (bigval < average[index] - threshold)
{
switch (index)
{
case 0: Buttons.BTN0 = 1; break; // The current button is pressed
case 1: Buttons.BTN1 = 1; break; // Relay button pressed information to application
case 2: Buttons.BTN2 = 1; break;
case 3: Buttons.BTN3 = 1; break;
case 4: Buttons.BTN4 = 1; break;
case 5: Buttons.BTN5 = 1; break;
case 6: Buttons.BTN6 = 1; break;
case 7: Buttons.BTN7 = 1; break;
case 8: Buttons.BTN8 = 1; break;
case 9: Buttons.BTN9 = 1; break;
case 10: Buttons.BTN10 = 1; break;
case 11: Buttons.BTN11 = 1; break;
case 12: Buttons.BTN12 = 1; break;
case 13: Buttons.BTN13 = 1; break;
case 14: Buttons.BTN14 = 1; break;
case 15: Buttons.BTN15 = 1; break;
default: break;
}
}
else
{
// Button unpressed (no hysteresis provided)
switch (index)
{
case 0: Buttons.BTN0 = 0; break; // The current button is unpressed
case 1: Buttons.BTN1 = 0; break; // Relay button pressed information to application
case 2: Buttons.BTN2 = 0; break;
case 3: Buttons.BTN3 = 0; break;
case 4: Buttons.BTN4 = 0; break;
case 5: Buttons.BTN5 = 0; break;
case 6: Buttons.BTN6 = 0; break;
case 7: Buttons.BTN7 = 0; break;
case 8: Buttons.BTN8 = 0; break;
case 9: Buttons.BTN9 = 0; break;
case 10: Buttons.BTN11 = 0; break;
case 12: Buttons.BTN10 = 0; break;
case 11: Buttons.BTN12 = 0; break;
case 13: Buttons.BTN13 = 0; break;
case 14: Buttons.BTN14 = 0; break;
case 15: Buttons.BTN15 = 0; break;
default: break;
}

// Perform average after detection comparison
average[index] += bigval/16 - smallavg;

}
SetNextChannel(); // Set up for next channel
RestartTimer1(); // Restart timer1
}

}





//*********************************************************************
//Function: RestartTimers() *******************************************
// Purpose: Resets and restarts timers 0 & 1 used for capacitive sensing.
// Based on original method before Timer1 Gate peripheral features
//. added to 72x. *****************************************************
//*********************************************************************
void RestartTimers(void)
{

TMR1L = 0; // reset Timer1
TMR1H = 0; // " "
TMR1ON = 1; // restart Timer1
TMR0 = 0; // reset Timer0
TMR0IF = 0; // clear the interrupt
}



// ********************************************************************
// RestartTimer1() ****************************************************
// Resets and restarts timer 1 (used for capacitive sensing).
// Used for Timer0 and T1GCON in toggle mode for automatic shutoff
// of Timer1 (better for consistent and repeated measurements).
// Also has same use with toggle & single pulse mode Tmr1 gate.
// ********************************************************************
void RestartTimer1(void)
{
TMR1L = 0; // Reset Timer1
TMR1H = 0; // " "
TMR1ON = 1; // Restart Timer1
CLRWDT();
}



//**********************************************************************
// SetNextChannel() **************************************************
// Sets the next channel for the oscillator to measure, ***********
// configures all hardware appropriately, internal, and if ************
// applicable external. ***********************************************
// *********************************************************************
void SetNextChannel(void)
{
index = (++index) & 0x0F; // cycle index state 0-15 w/rollover
// if (index >> 0x0E)
// index = 0;
CPSCON1 = index; // Select external pin CPS0..CPS15
}

//************************************************************************
// Function: DisplayLEDs() ***********************************************
// Display ouput button on LEDS based ************************************
// binary button number **************************************************
// ***********************************************************************

void DisplayLEDs(char i)
{

// Display the
switch (i)
{
case 0xFF: // 0xFF is special value for off (same as 0).
case 0: LED0 = OFF; LED1 = OFF; LED2 = OFF; LED3 = OFF; break; // Binary counting
case 1: LED0 = ON; LED1 = OFF; LED2 = OFF; LED3 = OFF; break; // for LEDs
case 2: LED0 = OFF; LED1 = ON; LED2 = OFF; LED3 = OFF; break;
case 3: LED0 = ON; LED1 = ON; LED2 = OFF; LED3 = OFF; break;
case 4: LED0 = OFF; LED1 = OFF; LED2 = ON; LED3 = OFF; break;
case 5: LED0 = ON; LED1 = OFF; LED2 = ON; LED3 = OFF; break;
case 6: LED0 = OFF; LED1 = ON; LED2 = ON; LED3 = OFF; break;
case 7: LED0 = ON; LED1 = ON; LED2 = ON; LED3 = OFF; break;
case 8: LED0 = OFF; LED1 = OFF; LED2 = OFF; LED3 = ON; break;
case 9: LED0 = ON; LED1 = OFF; LED2 = OFF; LED3 = ON; break;
case 10: LED0 = OFF; LED1 = ON; LED2 = OFF; LED3 = ON; break;
case 11: LED0 = ON; LED1 = ON; LED2 = OFF; LED3 = ON; break;
case 12: LED0 = OFF; LED1 = OFF; LED2 = ON; LED3 = ON; break;
case 13: LED0 = ON; LED1 = OFF; LED2 = ON; LED3 = ON; break;
case 14: LED0 = OFF; LED1 = ON; LED2 = ON; LED3 = ON; break;
case 15: LED0 = ON; LED1 = ON; LED2 = ON; LED3 = ON; break;
default: break;
}

}




Post Extras: Print Post   Remind Me!   Notify Moderator  
Pages: 1



Extra information
0 registered and 42 anonymous users are browsing this forum.

Moderator:  mikerj, jtemples, jeff, Dan Henry, Andrew L 

Print Topic

Forum Permissions
      You cannot start new topics
      You cannot reply to topics
      HTML is enabled
      UBBCode is enabled

Rating:
Topic views: 3847

Rate this topic

Jump to

Contact Us | Privacy statement HI-TECH Software

Powered by UBB.threads™ 6.5.5