View previous topic :: View next topic |
Author |
Message |
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
Touch Sensor - I hope you can help me?!? |
Posted: Mon Dec 21, 2015 1:26 pm |
|
|
Hi!
I'm new to the whole Microcontroller thing. I think I read everything (in this forum) about the Touch functions CCS offers, but I have not found a solution I understood. I am only a Web programmer ;P
First of all here is my code so far.
Code: |
//Cap Touch Testing
#include <16f726.h>
#fuses NOWDT,NOPROTECT,MCLR
#use delay (INTERNAL=4M)
#use TOUCHPAD (Range=H,scantime=32ms,threshold=6,PIN_B0='A',PIN_B1='B',PIN_B2='C',PIN_B3='D')
#define LED1 PIN_A0
#define LED2 PIN_A1
void main(){
char c;
TOUCHPAD_STATE(1);
enable_interrupts(GLOBAL);
output_low(LED1);
output_low(LED2);
for (;;){
if (TOUCHPAD_HIT()){
c=TOUCHPAD_GETC();
switch (c) {
case 'A':
output_high(LED1);
delay_ms(500);
break;
case 'B':
output_high(LED2);
break;
case 'C':
output_high(LED1);
output_high(LED2);
break;
case 'D':
output_high(LED1);
break;
}
output_low(LED1);
output_low(LED2);
}
}
}
|
The first question:
I want my touch fields to work like that: the LED should be ON as long as I am pressing the Touch field... is there something similar to output_toggle or output_high that can solve my Problem?
And my second question:
I read something about the possibility to program a multi-touch function by using the test-mode (touchpad_state(2)) and read the values directly from the "touchdata"-array... Is it possible to get a coding-example? It is much easier for me to understand than an explanation. Both would be perfect!
Thank for all your help and sorry for my bad English
Clemens |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Mon Dec 21, 2015 2:43 pm |
|
|
Web programming, and hardware programming are very different things.
The touchpad library using getc, is designed to replicate a keyboard, and avoid having to think about numbers read, etc..
However, you need to access the next layer 'lower'.
If you call 'touchpad_state(2)', the library puts the actual numeric values read from the pins, into the array CTMU_THRESHOLD[x], where 'x' is the number of keys defined in the setup. The number is the value read from the hardware. You have to decide how high you want the number before you accept it.
You can then test for multiple keys at the same time, and continuous 'touch', rather than just 'change'.
Have a look at this thread. As you will see the manual is wrong, but he got a slider working based on using the threshold numbers:
<http://www.ccsinfo.com/forum/viewtopic.php?t=52358&highlight=touchpad>
Also note they are int8, not int16... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Dec 21, 2015 6:18 pm |
|
|
Are you able to test your code with an actual pic and a circuit,
or is this for emulation/simulation? |
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Tue Dec 22, 2015 2:01 am |
|
|
Hi Ttelmah and asmboy!
Yeah... At first it looked similar to PHP... but that was totaly wrong
Ok... lets see if i got that
The code till "void main" stays the same:
Code: |
//Cap Touch Testing
#include <16f726.h>
#fuses NOWDT,NOPROTECT,MCLR
#use delay (INTERNAL=4M)
#use TOUCHPAD (Range=H,scantime=32ms,threshold=6,PIN_B0='A',PIN_B1='B',PIN_B2='C',PIN_B3='D')
#define LED1 PIN_A0
#define LED2 PIN_A1
|
In my "Void main" i just have to call the Touchpad_State(2); and set the LEDs to output_low (like before).
Am I right, that CTMU_Treshold [0] would be my Pad A, CTMU_Treshold[1] would be my Pad B and so on?
If this is correct i just have to write something like this in my main function?
Code: |
if (CTMU_TRESHOLD[0] > 600){
output_high(LED1);
}else{
output_low(LED1);
}
|
So the first thing i need to know is the "standard" capacitiy of each pad.
Is there any stored standard value that i can use to calculate my threshold (like before %)
@ asmboy
Yeah i have real hardware... The PIC i am using is the 16f726... an the programmer is the DIAMEX PIC PROGAMMER (PIC KIT 2).
Thank you for your help!
Clemens |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Tue Dec 22, 2015 2:29 am |
|
|
Now, 'no guarantees' on this. I haven't got one of those chips to test at present, or anything else setup to use the CTMU.
However comments:
At the end of the thread I pointed to earlier, the poster said that CCS would fix the array name in the next release. A quick look at the symbol file, says they have done this. So I'm using the array name from the manual.
This duplicates your existing code, except that the LED's should remain on while the pad is held, and if both pad a, and pad b are touched together, the first LED should toggle (to show a 'double key' detection). Also since the scanning is sequential other than this, if you held pad a and pad c, both LED's would come on.
As I say, 'no guarantees', but this is where I would be starting:
Code: |
#include <16f726.h>
#fuses NOWDT,NOPROTECT,MCLR
#use delay (INTERNAL=4M)
#use TOUCHPAD (Range=H,scantime=32ms,threshold=6,PIN_B0='A',PIN_B1='B',PIN_B2='C',PIN_B3='D')
#define KEYS 4
int16 touch_init[KEYS]; //global array for initial state
#define THRESHOLD 6 //threshold for the raw data
#define LED1 PIN_A0
#define LED2 PIN_A1
#define KEYA 0
#define KEYB 1
#define KEYC 2
#define KEYD 3 //defines for the key positions in the data array
int16 change(int8 keyno)
{
//routine to return the change value from the selected key number
if (TOUCHDATA[keyno]<touch_init[keyno])
{
touch_init[keyno]=TOUCHDATA[keyno];
return 0;
} //handle error that capacitance has dropped since initialisation
return TOUCHDATA[keyno]-touch_init[keyno]; //return change value
}
#define KEYON(keyno) change(keyno)>THRESHOLD
void main(void)
{
int8 ctr;
int1 flag=FALSE;
TOUCHPAD_STATE(1);
enable_interrupts(GLOBAL);
delay_ms(300);
//now store the initial values
for (ctr=0;ctr<KEYS;ctr++)
touch_init[ctr]=TOUCHDATA[ctr];
output_low(LED1);
output_low(LED2);
for (;;)
{
delay_ms(32); //allow touch to rescan
flag=FALSE; //flag for a key being seen
if (KEYON(KEYA))
{
//now check a second key here
if (KEYON(KEYB))
{
output_toggle(LED1);
continue; //no further checking for the double key
}
output_high(LED1);
flag=TRUE; //a key has been seen
}
if (KEYON(KEYB))
{
output_high(LED2);
flag=TRUE;
}
if (KEYON(KEYC))
{
output_high(LED1);
output_high(LED2);
flag=TRUE;
}
if (KEYON(KEYD))
{
output_high(LED1);
flag=TRUE;
}
if (flag==FALSE)
{
//here no key is pressed
output_low(LED1);
output_low(LED2);
}
}
}
|
There is also a TOUCPADSTATUS variable, which should (I think), contain bits corresponding to whether a key is pressed. If I'm right on this (haven't got time to disassemble the listing and see if this is right), then instead one could use:
Code: |
#define KEYON(keyno) bit_test(TOUCHPADSTATUS,keyno)
|
|
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Tue Dec 22, 2015 3:33 am |
|
|
Hi Ttelmah!
All i can say is WWOOWW!!
I think it will take some time to understand that!
Please tell me if i am right:
The "new" threshold you are using in this code is not a precentage limit, am i right?
Code: | #define THRESHOLD 6 //threshold for the raw data |
You used it here:
Code: | int16 change(int8 keyno)
{
//routine to return the change value from the selected key number
if (TOUCHDATA[keyno]<touch_init[keyno])
{
touch_init[keyno]=TOUCHDATA[keyno];
return 0;
} //handle error that capacitance has dropped since initialisation
return TOUCHDATA[keyno]-touch_init[keyno]; //return change value
}
#define KEYON(keyno) change(keyno)>THRESHOLD |
This means if the difference between the stored "standard-value" and the current value of the button pressed is bigger than 6 (not 6%) KEYNO stores the Keynumber pressed... am i right?
Thank you for your help!... I can hardly wait for testing this... after work in 6 hours
Thank you!
Clemens |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Tue Dec 22, 2015 4:23 am |
|
|
It's 'counts' on the CTMU value returned.
The raw array, returns the numeric values physically read from the CTMU (or CSM) peripheral, for each connection. So if these rise by more than 'THRESHOLD' from the initial values read, I'm treating this as a 'pressed' action. These should be updated every 'scantime' (done by a timer interrupt), so there is no point in re-trying more frequently than this (hence the delay in the loop). Now how CCS actually scale the values returned I don't know, without dismantling what they do, so 'experiment' will definitely be needed!...
|
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Tue Dec 22, 2015 1:29 pm |
|
|
OK... So far so good...
I tried it... and you were right. The version with Touchpadstatus worked, the other one didnt worked at all... but the problem is that the LED's go on, but they doesnt go off... is it possible that there is someting worng with the flags?
An other Problem is that if i am pressing pad-D LED1 and LED2 are going on...
I tried the following:
Code: | if (KEYON(KEYA))
{
output_toggle(LED1);
flag=TRUE; //a key has been seen
}
|
If i am touching Key A the led starts blinking rapidly! And the funny thing is if i am pressing Key D the LED1 blinks and LED 2 is just on!
Is it a problem that i am using the compiler version 4.140...?
Thank you!
Clemens |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Tue Dec 22, 2015 3:45 pm |
|
|
Try increasing the threshold in the #use touchpad line.
It's behaving as if it is still seeing one of the pads being touched. 6 is quite a low threshold. Something like 20 is more typical to be needed.
The LED's will only clear if all the pads are seen as 'off'.
Simplify it to just access (say) two pads.
Then you can have one LED for each pad.
Will make debugging easier. Then add a third etc.. |
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Tue Dec 22, 2015 3:58 pm |
|
|
No... doesnt change anything...
Is it possible that there is a wrong value for the untouched value stored? So if i pressed the button the "pressed"-value becomes the new unpressed-value?
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Wed Dec 23, 2015 4:43 am |
|
|
The 'untouched' value is stored by the CCS code, when you call touchpad_state(1). That is what this does. So as simplified test code:
Code: |
#include <16f726.h>
#fuses NOWDT,NOPROTECT,MCLR
#use delay (INTERNAL=4M)
#use TOUCHPAD (Range=H,scantime=32ms,threshold=16,PIN_B0='A',PIN_B1='B',PIN_B2='C',PIN_B3='D')
#define LED1 PIN_A0
#define LED2 PIN_A1
#define KEYA 0
#define KEYB 1
#define KEYC 2
#define KEYD 3 //defines for the key positions in the data array
#define KEYON(keyno) bit_test(TOUCHPADSTATUS,keyno)
void main(void)
{
int8 ctr;
enable_interrupts(GLOBAL);
delay_ms(300);
//Allow time for the touchpad code to have scanned the pads
TOUCHPAD_STATE(1); //This 'calibrates' the touchpad
//The touchpad needs to be running _before_ you call this
output_low(LED1);
output_low(LED2);
//now simplified code to just turn each LED on/off for a touchpad
for (;;)
{
delay_ms(32); //allow touch to rescan
if (KEYON(KEYA))
output_high(LED1);
else
output_low(LED1);
if (KEYON(KEYB))
output_high(LED2);
else
output_low(LED2);
}
}
|
|
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Wed Dec 23, 2015 4:57 am |
|
|
I am studying your code for hours now... but i don't understand two thing... maybe three
Can you tell me what the line does exactly?
Code: | #define KEYON(keyno) bit_test (TOUCHPADSTATUS, keyno) |
What is behind TOUCHPADSTATUS?
My next question is why are you calculating the difference between the current reading of the Pad (=i think this is TOUCHDATA) and the stored Value (Touch_init)? Where do you use the value?
In this If-query you say that if the current reading is smaller than the stored one, the current reading is equal to the stored one and returns 0... I don't understand why you are setting them equal?
I just saw you wrote a simplified test code... I'll try that!
Is keyno a variable that is already in the CCS code??
Thank you! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Wed Dec 23, 2015 8:30 am |
|
|
You said that the delta version did not work. So I don't use the delta values. They are removed in this code.
TOUCHPADSTATUS is a bit array created by the compiler, with 1's for every pad that has a value 'threshold' above it's calibration value.
There are two arrays created for you. TOUCHDATA, which is an int16 array, and TOUCHPADSTATUS. The former contains the raw data (in my original code I was using this and looking for the actual value to change), and the status array which contains the 'I am touched' status for each pad. You said the status version was working, so I have used this. There have been numerous changes since the touchpad functions were added, and I was not sure whether your compiler was supporting these. |
|
|
igelkotze
Joined: 15 Dec 2015 Posts: 12
|
|
Posted: Wed Dec 23, 2015 11:22 am |
|
|
Hmm... They are still always "on" if i touch the pad... the only difference is that just the right one is on, the other one is off. With the last code they were always on...
Do you have any further ideas??
Thank you |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed Dec 23, 2015 11:36 am |
|
|
Can you post the circuit schematic you are using so a hardware issue might be dismissed ? |
|
|
|