CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

CVD touch button with pic12F615
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Sun Jun 08, 2014 9:24 pm     Reply with quote

Ttelmah wrote:
There is also a big misunderstanding going on.

A _single_ touch pin requires two ADC inputs. The code as written implements one touch pad only.
You can re-use the same two inputs to give a second touch input on the second pin, by reversing the selections done in the code. The application note is the key thing to read here.

The touch pad would normally be done as a pad, with a ground ring around it. The measurement is of the change in capacitance between the pad and the ring.
The circuit misses the protection diodes shown in Mike's circuit. Needed or you can quite quickly kill the chip.
There are problems with the pin numbers. Didn't check these, but on most 8pin PIC's, A3, is input only, so can't be used as the second pin AN3, is on A4.

So i make a capacitive in pin A4 and change code :channel 0 => channel 4
=> ok?
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Sun Jun 08, 2014 9:25 pm     Reply with quote

PCM programmer wrote:
Quote:
int16 get_touch()
{
output_high(PIN_A0); //set AN0 driven high
set_adc_channel(sAN0); //connect it to the ADC
output_low(PIN_A3); //set AN3 to drive low
output_float(PIN_A3); //set it as an input
set_adc_channel(sAN3); //now connect this to the ADC
delay_us(10); //wait for Tacq
return read_adc(); //and get reading.
}

This is a coding bug. The set_adc_channel() function does not use a sANx
constant as the parameter. The parameter is the ADC channel. The
parameter should be a number such as 0, 1, 2, 3.

Look at the definitions of the sANx constants from the 12F615.h file:
Code:

#define sAN0      1         
#define sAN1      2
#define sAN2      4
#define sAN3      8

Your code above which uses the sANx constants is actually selecting
ADC channels 1 and 8 (which doesn't even exist). This will totally screw
up your program. Fix this by using 0 and 3 as the channel parameters
for set_adc_channel().

i change code like to you say. But it not running!
Ttelmah



Joined: 11 Mar 2010
Posts: 19811

View user's profile Send private message

PostPosted: Mon Jun 09, 2014 12:22 am     Reply with quote

You need to use:

Code:

int16 get_touch()
{
   output_high(PIN_A0); //set AN0 driven high
   set_adc_channel(0); //connect it to the ADC
   output_low(PIN_A4); //set AN3 to drive low
   output_float(PIN_A4); //set it as an input
   set_adc_channel(3); //now connect this to the ADC
   delay_us(10); //wait for Tacq
   return read_adc(); //and get reading.
}

Two problems the sANx defines are the bit masks used for channel _enabling_, not selection. I didn't spot this when copying from your code, since I'd always normally 'name' channels, and so was used to using names like this. Selections for the ADC, are just the channel number (0,1,2 etc.).
Then the AN3 channel is on A4, not A3.

A3 on the 8pin PIC's is a 'part pin'. Can't be used for output, and doesn't have an analog channel on it.
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Tue Jun 17, 2014 12:07 am     Reply with quote

Ttelmah wrote:
You need to use:

Code:

int16 get_touch()
{
   output_high(PIN_A0); //set AN0 driven high
   set_adc_channel(0); //connect it to the ADC
   output_low(PIN_A4); //set AN3 to drive low
   output_float(PIN_A4); //set it as an input
   set_adc_channel(3); //now connect this to the ADC
   delay_us(10); //wait for Tacq
   return read_adc(); //and get reading.
}

Two problems the sANx defines are the bit masks used for channel _enabling_, not selection. I didn't spot this when copying from your code, since I'd always normally 'name' channels, and so was used to using names like this. Selections for the ADC, are just the channel number (0,1,2 etc.).
Then the AN3 channel is on A4, not A3.

A3 on the 8pin PIC's is a 'part pin'. Can't be used for output, and doesn't have an analog channel on it.

Thanks Ttelmah
In AN1298 :
Sensing Steps
To perform the sensing, do the following:
1. Drive secondary channel to VDD as digital
output.
2. Point ADC to the secondary VDD pin (charges
CHOLD to VDD).
3. Ground sensor line.
4. Turn sensor line as input (TRISx = 1).
5. Point ADC to sensor channel (voltage divider
from sensor to CHOLD).
6. Begin ADC conversion.
7. Reading is in ADRESH:ADRESL.
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Tue Jun 17, 2014 4:01 am     Reply with quote

Ttelmah wrote:
There is also a big misunderstanding going on.

A _single_ touch pin requires two ADC inputs. The code as written implements one touch pad only.
You can re-use the same two inputs to give a second touch input on the second pin, by reversing the selections done in the code. The application note is the key thing to read here.

The touch pad would normally be done as a pad, with a ground ring around it. The measurement is of the change in capacitance between the pad and the ring.
The circuit misses the protection diodes shown in Mike's circuit. Needed or you can quite quickly kill the chip.
There are problems with the pin numbers. Didn't check these, but on most 8pin PIC's, A3, is input only, so can't be used as the second pin AN3, is on A4.

So i can use AN1, A1?
Code:
   output_low(PIN_A4); //set AN3 to drive low
   output_float(PIN_A4); //set it as an input
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Tue Jun 17, 2014 10:11 pm     Reply with quote

Ttelmah wrote:

Hi Ttelmah
This is the first time i working with Mtouch CVD.
So I do not have experience.
Thank you for the help.
This is the hardware touch button.
Please check help me :
Ttelmah



Joined: 11 Mar 2010
Posts: 19811

View user's profile Send private message

PostPosted: Tue Jun 17, 2014 11:51 pm     Reply with quote

What's the circuit with the transistor to Vref for?.

Vref for the touch, is the supply. When you send 'output_high', on the pin connected to the ADC, you charge the internal ADC capacitor to this voltage. No extra circuitry needed.
Again read the application note.
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Wed Jun 18, 2014 12:48 am     Reply with quote

Ttelmah wrote:
What's the circuit with the transistor to Vref for?.

Vref for the touch, is the supply. When you send 'output_high', on the pin connected to the ADC, you charge the internal ADC capacitor to this voltage. No extra circuitry needed.
Again read the application note.

Vref not for touch.
Vref for another application.(PWM signal controll)


Code:

/*========================================================================
   Mo ta: Mach dimmer
         
   Phan cung: Pic 12F615
   
   Thach anh: Internal 4Mhz
   
   Thoi gian: 5.2014

=========================================================================*/

/****************************Bo tien xu li********************************/
#include <12F615.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR                     //Master Clear pin enabled
#FUSES NOPUT                    //No Power Up Timer
#FUSES RESERVED                 //Used to set the reserved FUSE bits
#use delay(internal=4000000)


/*=======================================================================*/
/****************************Khai bao bien toan cuc **********************/

  int16 temp=0,Touch;
  unsigned char dem=0;
/*=======================================================================*/
/**************************** Khai bao ham  ******************************/
/*===========================Ham doc touch button========================*/
int16 get_touch()
{
   output_high(PIN_A0);
   delay_us(10);
   set_adc_channel(0);
   output_low(PIN_A4);
   output_float(PIN_A4);
   set_adc_channel(1);
   delay_us(10);
   return read_adc();
}
/*==========================Ham doc gia tri =============================*/
void Touch_read()
{
   Touch=get_touch();
   if(Touch<temp)dem++;
   else {;}
}
/*=========================Ham duty cycle================================*/
void duty_cycle()
{
      switch(dem)
      {
      case 1:
      {
      setup_ccp1(CCP_PWM);
      setup_timer_2(T2_DIV_BY_16, 112, 1);
      set_pwm1_duty(113);break;}
      case 2:
      {set_pwm1_duty(56);break;}
      case 3:
      {set_pwm1_duty(13);break;}
      case 4:
      {set_pwm1_duty(56);break;}
      case 5:
      {set_pwm1_duty(113);break;}
     
    }
}
/*=======================================================================*/
/***************************** Ham chinh *********************************/
void main()
{
   unsigned char i;
   setup_adc_ports(sAN1|sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_8);
   
   for(i=0;i<5;i++)// lay mau 5 lan
   {
      temp += get_touch();
      delay_us(8);
   }
 
   temp = temp/5 ;
   
   while(TRUE)
   {
      delay_us(10);
      touch_read();
      duty_cycle();
      delay_ms(1000);
      if(dem==5)dem=1;   
   }
}
/*************************************************************************/

Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Jun 18, 2014 2:08 pm     Reply with quote

You are making things too complex.
You say your real issue is with the touch pad.
Concentrate on that.
Ignore everything else.

Mike
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Tue Jun 24, 2014 10:39 pm     Reply with quote

Mike Walne wrote:
You are making things too complex.
You say your real issue is with the touch pad.
Concentrate on that.
Ignore everything else.

Mike

Dear Mike walne.
As you say.
i must code for simple test.
but it dont running.
Please check help me!
Code:


#include <12F615.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR                     //Master Clear pin enabled
#FUSES NOPUT                    //No Power Up Timer
#FUSES RESERVED                 //Used to set the reserved FUSE bits
#use delay(internal=4000000)
#use fast_io(A)
 
  int16 temp=0,Touch;
  unsigned char i,dem=0;

int16 get_touch()
{
   output_high(PIN_A0);
   set_adc_channel(0);
   delay_us(10);
   output_low(PIN_A4);
   output_float(PIN_A4);
   set_adc_channel(3);
   delay_us(10);
   return read_adc();
}

void touch_read()
{
   Touch=get_touch();
   if(Touch<temp)output_high(PIN_A5);
   else output_low(PIN_A5);
   
}

void main()

   
   setup_adc_ports(sAN1|sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_8);
   
   for(i=0;i<32;i++)
   {
      temp += get_touch();
      delay_us(8);
   }
 
   temp = temp/32 ;
   
   while(TRUE)
   {
      delay_us(10);
      touch_read();
      delay_ms(1000);
   }
}


viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Wed Jun 25, 2014 4:00 am     Reply with quote

Ttelmah wrote:
Code:

#include <12F615.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR                     //Master Clear pin enabled
#FUSES NOPUT                    //No Power Up Timer
#FUSES RESERVED                 //Used to set the reserved FUSE bits
#use delay(internal=4000000)

int16 get_touch()
{
   output_high(PIN_A0);   //set AN0 driven high
   set_adc_channel(sAN0); //connect it to the ADC
   output_low(PIN_A3); //set AN3 to drive low
   output_float(PIN_A3); //set it as an input
   set_adc_channel(sAN3); //now connect this to the ADC
   delay_us(10); //wait for Tacq
   return read_adc();  //and get reading.
}

void touch_read()
{
   touch=get_touch();
   if(Touch<temp) dem++;
}

void main()
{
   int16 temp=0;
   setup_adc_ports(sAN3|sAN0|VSS_VDD);
   //you need to enable both channels
   setup_adc(ADC_CLOCK_DIV_8);
   //Using the internal clock degrades accuracy.
   for(i=0;i<5;i++)       //lay mau 5 lan
   {
      temp+ = get_touch();
      delay_us(8);
   }
   //because you had the ADC set to 16bit, the 16bit sum would overflow
   temp = temp/5;// Lay gia tri trung binh
   while(TRUE)
   {
      delay_us(100);//slow the loop a little
      touch_read();
      duty_cycle();
      if(dem==6)dem=1;   
   }
}


Key big error is running the ADC in 16bit mode (no more accuracy doing this), then summing five readings in an int16. Overflow....

If you look at the code, you can see it follows the steps in the application note exactly.

I'd suggest ignoring your PWM adjustment for a moment, and just sending the ADC readings from the touch calls to a serial port, and then seeing what happens to the readings as capacitance changes. Reading will go up with increased capacitance, so testing if the value is less than the calibration value, may not be correct....


Problem:
if you want to use : output_high(PIN_A); output_low() ; output_float();
you must include : #use fast_io(A);
But when i include #use fast_io(A) => Moduel PWM in pic12F615 not running.
jeremiah



Joined: 20 Jul 2010
Posts: 1387

View user's profile Send private message

PostPosted: Wed Jun 25, 2014 8:48 am     Reply with quote

viethung_tdh wrote:

Problem:
if you want to use : output_high(PIN_A); output_low() ; output_float();
you must include : #use fast_io(A);

This is incorrect. #use fast_io() is not a requirement to use those functions. They work using the default io mode.
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Wed Jun 25, 2014 7:38 pm     Reply with quote

jeremiah wrote:
viethung_tdh wrote:

Problem:
if you want to use : output_high(PIN_A); output_low() ; output_float();
you must include : #use fast_io(A);

This is incorrect. #use fast_io() is not a requirement to use those functions. They work using the default io mode.


But In CCS help.
output_high( )

--------------------------------------------------------------------------------



Syntax:
output_high (pin)



Parameters:
Pin to write to. Pins are defined in the devices .h file. The actual value is a bit address. For example, port a (byte 5) bit 3 would have a value of 5*8+3 or 43. This is defined as follows: #define PIN_A3 43. The PIN could also be a variable. The variable must have a value equal to one of the constants (like PIN_A1) to work properly. The tristate register is updated unless the FAST_I0 mode is set on port A. Note that doing I/0 with a variable instead of a constant will take much longer time.

Function:
Sets a given pin to the high state. The method of I/O used is dependent on the last USE *_IO directive.

Availability:All devices.

Requires: Pin constants are defined in the devices .h file
viethung_tdh



Joined: 31 May 2014
Posts: 18

View user's profile Send private message

PostPosted: Wed Jun 25, 2014 8:22 pm     Reply with quote

Microchip code sample(but not for CCS):
Code:

/*********************************************************************
* file: cmtouch.c                                                  *
* auth: t. perme                                                     *
* date:                                                              *
*
* modf: 25 Jun 2009
* date: 25 Jun 2009
* desc:
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology
* Incorporated (the "Company") is intended and supplied to you, the
* Company’s customer, for use solely and exclusively on Microchip
* products. The software is owned by the Company and/or its supplier,
* and is protected under applicable copyright laws. All rights are
* reserved. Any use in violation of the foregoing restrictions may
* subject the user to criminal sanctions under applicable laws, as
* well as to civil liability for the breach of the terms and
* conditions of this license.
*
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*********************************************************************/


#include "main.h"
#include "cmtouch.h"

/** Variables **/
// Global
unsigned int         average[NUM_SENSORS];
unsigned int         reading[NUM_SENSORS];
unsigned long          stdev[NUM_SENSORS];
unsigned int           delta;
unsigned char   button_press[NUM_SENSORS];
unsigned char button_pressed;
unsigned char debounce_count[NUM_SENSORS];
char                   index;
char                avgindex;

// Local
char                  warmup;


/** Protoypes **/
// Global
void CapInit(void);
void GetReading(void);
void SetNextChannel(void);
// Local


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


/*********************************************************************
*   CapInit()
*
*.      Any special initialization the cap sensing method requires
*********************************************************************/
void CapInit(void) {

   // Req to init ADC
   ADCON0  = 0b10000001;            // ch0, idle, en
   ADCON1  = 0b10000000;            // right justified,

   // CVD Method
   VDDPIN  = 1;                  // Put the vddpin, to charge adc cap to vdd.

   // Initialize Variables
   for (index=0; index<NUM_SENSORS; index++)
      reading[index] = 0;            // clear the reading variable

   warmup = 100;                  // use first N samples to establish average, allows system stabilization time
}





/*********************************************************************
*  Function:
*      GetReading()
*   
*  Description:
*    Gets the reading for the sensor, and places it in the variable
*    "reading".                                                   
*********************************************************************/
void GetReading(void) {

   // CVD Method
   
   // Put VDD on ADC's Chold
   TRISA0  = 0;
   RA0     = 1;                                          // Output 5V on AN0 to charge ADC's Chold to VDD
   ADCON0 &= 0b11000011;                                    // Set CHS<3:0> to zero for Ch0


   // Now setup sensor prior to taking reading
   switch(index) {
      //~~~~~~~~~ ground the sensor ~~~~~ set as input ~~~~~~~ set adc ch ~~~~~~~~~~~ // idx  key  port/pin  an
      // Cap Eval Kit 16F Board
      case 0:      TRISB0 = 0;  RB0 = 0;  TRISB0 = 1;  ADCON0 = 0b01110001;  break;   // 3   5   rb0         12
      case 1:      TRISB1 = 0;  RB1 = 0;  TRISB1 = 1;  ADCON0 = 0b01101001;  break;   // 0   1   rb1         10
      case 2:      TRISB2 = 0;  RB2 = 0;  TRISB2 = 1;  ADCON0 = 0b01100001;  break;   // 1   2   rb2         8
      case 3:      TRISB3 = 0;  RB3 = 0;  TRISB3 = 1;  ADCON0 = 0b01100101;  break;   // 4   6   rb3         9
      case 4:      TRISB4 = 0;  RB4 = 0;  TRISB4 = 1;  ADCON0 = 0b01101101;  break;   // 2   3   rb4         11
      case 5:      TRISB5 = 0;  RB5 = 0;  TRISB5 = 1;  ADCON0 = 0b01110101;  break;   // 5   7   rb5         13
      case 6:      TRISA5 = 0;  RA5 = 0;  TRISA5 = 1;  ADCON0 = 0b01010001;  break;   // 6   8   ra5         4
      // Notes:
      // THIS IS THE CRITICAL SCANNING SEQUENCE, GIVEN PREPARATION OF VDDPIN BEFOREHAND(ABOVE).
      // The sequence horizontally is very specific & mandatory for an ADC sensor!
      // This is also where the index is bound to the ADC channel number.
      // The case value is the index, and is the variable 'index' (the switch)
      default:   break;
   }
   // Begin conversion
   GODONE = 1;                                             // Start ADC reading
   while (GODONE);                                          // Ensure ADC ready to be read
   reading[index] = ADRES;                                    // ReadADC
   reading[index] = reading[index]*16;                           // scale the reading by 16 (for 16 point averaging in decode, will maintain resolution)

   // Ground all sensors is simpler than grounding previously used
   TRISB  &= 0b11000000;
   PORTB  &= 0b11000000;
   TRISA5  = 0;
   RA5     = 0;


   // Once acquired reading, if just powered up, establish average and return
   if (warmup > 0) {
      warmup--;
      average[index] = reading[index];
      stdev[index] = 0;
      return;
   }


   

}




/*********************************************************************
*   SetNextChannel()
*
*      Sets the index for the next channel.
*********************************************************************/
void SetNextChannel(void) {
   if (++index >= NUM_SENSORS)      // increment index 0->(NUM_SENSORS-1) with rollover
      index = 0;
}
jeremiah



Joined: 20 Jul 2010
Posts: 1387

View user's profile Send private message

PostPosted: Wed Jun 25, 2014 8:35 pm     Reply with quote

viethung_tdh wrote:


But In CCS help.
output_high( )

--------------------------------------------------------------------------------



Syntax:
output_high (pin)



Parameters:
Pin to write to. Pins are defined in the devices .h file. The actual value is a bit address. For example, port a (byte 5) bit 3 would have a value of 5*8+3 or 43. This is defined as follows: #define PIN_A3 43. The PIN could also be a variable. The variable must have a value equal to one of the constants (like PIN_A1) to work properly. The tristate register is updated unless the FAST_I0 mode is set on port A. Note that doing I/0 with a variable instead of a constant will take much longer time.

Function:
Sets a given pin to the high state. The method of I/O used is dependent on the last USE *_IO directive.

Availability:All devices.

Requires: Pin constants are defined in the devices .h file


None of that says it is required. What it is saying is fast_io changes how the methods work. They work differently depending on if fast_io, standard_io, and fixed_io are used. I've been programming for a very long time using output_high and output_low and have never needed to use fast_io (not that you can't use it...but not required).

As an example:
Without fast_io, output_high(PIN_A1) does the following:
Sets the TRIS for A1 to output
Sets the level of A1 to high

Conversely, output_high() with fast_io set does the following:
Sets the level of A1 to high

See the difference in the two settings? In both scenarios, output_high() worked, but they worked differently.

Make sense?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group