View previous topic :: View next topic |
Author |
Message |
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
CVD touch button with pic12F615 |
Posted: Sun Jun 01, 2014 1:03 am |
|
|
Hi guys.
i have a problems with CVD touch button :
I want use touch buttton to controll PWM signal from pic12f615:
code:
Code: |
/*========================================================================
Phan cung: Pic 12F615
Thach anh: Internal 4Mhz
Tac gia: Dang Viet Hung
Thoi gian: 5.2014
=========================================================================*/
/****************************Bo tien xu li********************************/
#include <12F615.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR //Master Clear pin enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(internal=4000000)
//#use fast_io(a)
/*************************************************************************/
/****************************Khai bao bien toan cuc **********************/
int16 average[5];
int16 temp=0,Touch=0;
unsigned char i,dem;
/*************************************************************************/
/**************************** Khai bao ham ******************************/
/*===========================Ham doc touch button========================*/
void touch_read()
{
set_adc_channel(sAN3);
delay_us(10);
Touch = read_adc();
delay_us(10);
if(Touch<temp) dem++;
}
/*=========================Ham duty cycle================================*/
void duty_cycle()
{
switch(dem)
{
case 1:
{
setup_ccp1(CCP_PWM); // che do PWM
setup_timer_2(T2_DIV_BY_16, 112, 1);
set_pwm1_duty(0);break;}
case 2:
{set_pwm1_duty(0);break;}
case 3:
{set_pwm1_duty(56);break;}
case 4:
{set_pwm1_duty(101);break;}
case 5:
{set_pwm1_duty(56);break;}
}
}
/*************************************************************************/
/***************************** Ham chinh *********************************/
void main()
{
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(adc_clock_internal);
set_adc_channel(sAN3);//chon kenh 0 lam analog in
delay_us(10);
for(i=0;i<5;i++) //lay mau 5 lan
{
average[i] = read_adc();
delay_us(8);
temp = temp + average[i]; //cong don va lay gia tri trung bình
}
temp = temp/5;// Lay gia tri trung binh
while(TRUE)
{
touch_read();
duty_cycle();
if(dem==6)dem=1;
}
}
/*************************************************************************/
|
it not running!
please help me.
my CCS Version 4.104 |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Re: CVD touch button with pic12F615 |
Posted: Sun Jun 01, 2014 1:50 am |
|
|
viethung_tdh wrote: | Hi guys.
i have a problems with CVD touch button :
I want use touch buttton to controll PWM signal from pic12f615:
code:
Code: |
......
......
#include <12F615.h>
#device ADC=16
.....
.....
while(TRUE)
{
touch_read();
duty_cycle();
if(dem==6)dem=1;
}
}
/*************************************************************************/
|
it not running!
please help me.
my CCS Version 4.104 |
You need to learn to debug.
Saying "it not running!" is as useful as a chocolate fire guard.
Tell us:-
1) Whether your PIC is running at all.
2) What is working
3) What is not working.
4) What the initial value of 'dem' is
5) What happens to duty if dem happens to be 6.
6) How the system resets if dem > 6.
Start with an LED flasher.
Write test code to check that each function is working as intended.
Mike |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
Re: CVD touch button with pic12F615 |
Posted: Sun Jun 01, 2014 2:56 am |
|
|
Mike Walne wrote: | viethung_tdh wrote: | Hi guys.
i have a problems with CVD touch button :
I want use touch buttton to controll PWM signal from pic12f615:
code:
Code: |
......
......
#include <12F615.h>
#device ADC=16
.....
.....
while(TRUE)
{
touch_read();
duty_cycle();
if(dem==6)dem=1;
}
}
/*************************************************************************/
|
it not running!
please help me.
my CCS Version 4.104 |
You need to learn to debug.
Saying "it not running!" is as useful as a chocolate fire guard.
Tell us:-
1) Whether your PIC is running at all.
2) What is working
3) What is not working.
4) What the initial value of 'dem' is
5) What happens to duty if dem happens to be 6.
6) How the system resets if dem > 6.
Start with an LED flasher.
Write test code to check that each function is working as intended.
Mike |
Dear Mike.
My application:
I want use touch buttton to controll PWM signal from pic12f615:
The first touch : Duty cycle =0% (550hz :setup_timer_2(T2_DIV_BY_16, 112, 1); ) and dem =1 .
The second touch : Duty cycle = 50% => dem= 2
3rd touch : Duty cycle = 10% => dem =3
if dem== 6 => dem =2 return duty cycle =50%
.............................
i checked the program with replace the touch button by button and the program running good
you can see:
Code: |
#include <12F615.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR //Master Clear pin enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(internal=4000000)
//#use fast_io(a)
#define Button PIN_A4
//fine LED1 PIN_A0
//efine LED2 PIN_A1
//efine LED3 PIN_A2
void main()
{
unsigned char dem;
//setup_adc(adc_clock_internal);
//setup_adc_ports(NO_ANALOG|VSS_VDD);
setup_comparator(NC_NC_NC_NC);
//set_adc_channel(4);
delay_ms(10);
set_tris_A(0b00010000);
output_A(0xff);
dem=0;
while(TRUE)
{
//adc=read_adc();
if(!input(Button))// Neu nut bam duoc bam
{
dem++;
switch(dem)
{
case 1:
{
setup_ccp1(CCP_PWM); // che do PWM
setup_timer_2(T2_DIV_BY_16, 112, 1);
set_pwm1_duty(0);break;}
case 2:
{set_pwm1_duty(0);break;}
case 3:
{set_pwm1_duty(56);break;}
case 4:
{set_pwm1_duty(101);break;}
case 5:
{set_pwm1_duty(56);break;}
}
while(!input(Button));// cho den khi nut bam nha ra moi thuc hien lenh
delay_ms(20);
if(dem==6)
dem=2;
}
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sun Jun 01, 2014 3:34 am |
|
|
The code as written, has nothing to do with touch buttons at all!......
You are calling a function 'touch_read', but all it is doing is reading the ADC.
For 'touch', what happens is that the ADC internal capacitor is charged to the supply (using a second ADC input). Then you ground the ADC pin for a moment. Set it back to being an open circuit (input), then connect it to the ADC, and take the reading. The reading then reflects the ratio between the internal capacitance, and the capacitance on the pin.
Look at AN1298.
The neat thing is that using two pins, you can use these alternately to charge and measure, to give two inputs from the two pins, but two ADC inputs minimum are required. You can't do it with one pin.... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 01, 2014 3:38 am |
|
|
OK. Your PIC is running.
You do not have any de-bounce.
This bit and your code don't agree, but I will let you sort that out. Quote: | My application:
I want use touch buttton to controll PWM signal from pic12f615:
The first touch : Duty cycle =0% (550hz :setup_timer_2(T2_DIV_BY_16, 112, 1); ) and dem =1 .
The second touch : Duty cycle = 50% => dem= 2
3rd touch : Duty cycle = 10% => dem =3
if dem== 6 => dem =2 return duty cycle =50% |
From your original code:-
1) Which part have you not tested?
2) What do you have to do next?
Mike
EDIT Mr T. has given you a big hint. |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Sun Jun 01, 2014 3:57 am |
|
|
Ttelmah wrote: | The code as written, has nothing to do with touch buttons at all!......
You are calling a function 'touch_read', but all it is doing is reading the ADC.
For 'touch', what happens is that the ADC internal capacitor is charged to the supply (using a second ADC input). Then you ground the ADC pin for a moment. Set it back to being an open circuit (input), then connect it to the ADC, and take the reading. The reading then reflects the ratio between the internal capacitance, and the capacitance on the pin.
Look at AN1298.
The neat thing is that using two pins, you can use these alternately to charge and measure, to give two inputs from the two pins, but two ADC inputs minimum are required. You can't do it with one pin.... |
So i must use 2 channel ADC?
You can code help me! |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Sun Jun 01, 2014 3:57 am |
|
|
Mike Walne wrote: | OK. Your PIC is running.
You do not have any de-bounce.
This bit and your code don't agree, but I will let you sort that out. Quote: | My application:
I want use touch buttton to controll PWM signal from pic12f615:
The first touch : Duty cycle =0% (550hz :setup_timer_2(T2_DIV_BY_16, 112, 1); ) and dem =1 .
The second touch : Duty cycle = 50% => dem= 2
3rd touch : Duty cycle = 10% => dem =3
if dem== 6 => dem =2 return duty cycle =50% |
From your original code:-
1) Which part have you not tested?
2) What do you have to do next?
Mike
EDIT Mr T. has given you a big hint. |
[img][/img] |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jun 01, 2014 7:59 am |
|
|
Ttelmah has told you what to do.
Read the application note AN1298.
It explains both hardware and software, in detail.
Mike |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Tue Jun 03, 2014 4:58 am |
|
|
Hi Mike Walne and Ttelmah
I change code for mtouch use two channel ADC:
Code: |
/*========================================================================
Mo ta:
Phan cung: Pic 12F615
Thach anh: Internal 4Mhz
Tac gia:
Thoi gian: 5.2014
=========================================================================*/
/****************************Bo tien xu li********************************/
#include <12F615.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR
#FUSES IOSC8
#FUSES NOMCLR //Master Clear pin enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(internal=4000000)
#use fast_io(a)
/*************************************************************************/
/****************************Khai bao bien toan cuc **********************/
int16 average[5];
int16 temp=0,Touch=0;
unsigned char i,dem;
/*************************************************************************/
/**************************** Khai bao ham ******************************/
/*===========================Ham doc touch button========================*/
void touch_read()
{
set_adc_channel(sAN0);
set_tris_a(0);
output_bit(PIN_A0,1);
output_bit(PIN_A3,0);
set_tris_a(0b00011011);
set_adc_channel(sAN3);
delay_us(10);
Touch = read_adc();
delay_us(10);
if(Touch<temp) dem++;
}
/*=========================Ham duty cycle================================*/
void duty_cycle()
{
switch(dem)
{
case 1:
{
setup_ccp1(CCP_PWM); // che do PWM
setup_timer_2(T2_DIV_BY_16, 112, 1);
set_pwm1_duty(0);break;}
case 2:
{set_pwm1_duty(0);break;}
case 3:
{set_pwm1_duty(56);break;}
case 4:
{set_pwm1_duty(101);break;}
case 5:
{set_pwm1_duty(56);break;}
}
}
/*************************************************************************/
/***************************** Ham chinh *********************************/
void main()
{
setup_adc_ports(sAN3|VSS_VDD);
setup_adc(adc_clock_internal);
set_adc_channel(sAN0);
set_tris_a(0);
output_bit(PIN_A0,1);
output_bit(PIN_A3,0);
set_tris_a(0b00011011);
set_adc_channel(sAN3);
for(i=0;i<5;i++) //lay mau 5 lan
{
average[i] = read_adc();
delay_us(8);
temp = temp + average[i]; //cong don va lay gia tri trung bình
}
temp = temp/5;// Lay gia tri trung binh
while(TRUE)
{
touch_read();
duty_cycle();
if(dem==6)dem=1;
}
}
/*************************************************************************/
|
please help me check it!
Thank you very much! |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Jun 03, 2014 7:25 am |
|
|
Reduce your code to testing the touch switch only. (Probably no more than 10 lines of code.)
Get to the stage where you know it is working correctly.
I don't have your touch switch, so there is little point in me duplicating your efforts.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Tue Jun 03, 2014 7:28 am |
|
|
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.... |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Wed Jun 04, 2014 12:47 am |
|
|
Mike Walne wrote: | Reduce your code to testing the touch switch only. (Probably no more than 10 lines of code.)
Get to the stage where you know it is working correctly.
I don't have your touch switch, so there is little point in me duplicating your efforts.
Mike |
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.... |
I will create a circuit test and show the results to you! |
|
|
viethung_tdh
Joined: 31 May 2014 Posts: 18
|
|
Posted: Sat Jun 07, 2014 12:38 pm |
|
|
Hi Ttelmah and Mike Walne
I created a circuit test.You can see the schematic:
and PCB:
I think the touch 1 running not good so i make the touch 2.
Code:
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)
/*************************************************************************/
/****************************Khai bao bien toan cuc **********************/
int16 temp=0,Touch=0;
unsigned char i,dem;
/*************************************************************************/
/**************************** Khai bao ham ******************************/
/*===========================Ham doc touch button========================*/
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.
}
/*==========================Ham doc gia tri =============================*/
void touch_read()
{
touch=get_touch();
if(Touch<temp) dem++;
}
/*=========================Ham duty cycle================================*/
void duty_cycle()
{
switch(dem)
{
case 1:
{
setup_ccp1(CCP_PWM); // che do PWM
setup_timer_2(T2_DIV_BY_16, 112, 1);
set_pwm1_duty(0);break;}
case 2:
{set_pwm1_duty(0);break;}
case 3:
{set_pwm1_duty(56);break;}
case 4:
{set_pwm1_duty(101);break;}
case 5:
{set_pwm1_duty(56);break;}
}
}
/*************************************************************************/
/***************************** Ham chinh *********************************/
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;
}
}
/*************************************************************************/
|
But it not good :
you can see:
if you dont touch:
and press touch 1:
and press touch 2:
So i change the code:
Code: | if(Touch<temp) dem++; | by Code: | if(Touch>temp) dem++; |
and the signal :
+ Dont touch :
+Touch 1 :
+ Touch 2:
Can you help me?
i think the error from code. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jun 07, 2014 3:59 pm |
|
|
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(). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19496
|
|
Posted: Sun Jun 08, 2014 1:07 am |
|
|
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. |
|
|
|