 |
 |
View previous topic :: View next topic |
Author |
Message |
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Sun Jun 08, 2014 9:24 pm |
|
|
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
|
|
Posted: Sun Jun 08, 2014 9:25 pm |
|
|
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
|
|
Posted: Mon Jun 09, 2014 12:22 am |
|
|
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
|
|
Posted: Tue Jun 17, 2014 12:07 am |
|
|
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
|
|
Posted: Tue Jun 17, 2014 4:01 am |
|
|
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
|
|
Posted: Tue Jun 17, 2014 10:11 pm |
|
|
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
|
|
Posted: Tue Jun 17, 2014 11:51 pm |
|
|
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
|
|
Posted: Wed Jun 18, 2014 12:48 am |
|
|
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
|
|
Posted: Wed Jun 18, 2014 2:08 pm |
|
|
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
|
|
Posted: Tue Jun 24, 2014 10:39 pm |
|
|
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
|
|
Posted: Wed Jun 25, 2014 4:00 am |
|
|
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
|
|
Posted: Wed Jun 25, 2014 8:48 am |
|
|
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
|
|
Posted: Wed Jun 25, 2014 7:38 pm |
|
|
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
|
|
Posted: Wed Jun 25, 2014 8:22 pm |
|
|
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
|
|
Posted: Wed Jun 25, 2014 8:35 pm |
|
|
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? |
|
 |
|
|
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
|