PDA

View Full Version : Teensy 3.0 capactive touch



rockfirstlast
12-30-2012, 08:45 AM
How do you initialize a pin for built-in capacitive touch?

pinMode(1, ???? )

I know everything is really new, but is there any example documentation for the new touchRead feature? Thanks!

PaulStoffregen
12-30-2012, 10:11 AM
Just use touchRead(pin) and it will automatically configure the pin for you, just like analogRead() does.

rockfirstlast
12-30-2012, 12:04 PM
Thanks!

I also found an example for those searching the forums about how to implement touchRead.

http://www.instructables.com/id/Overbalanced-Wheel-Fake-Perpetual-Motion-Machine-/step7/Programming-the-Teensy/

LarryP
01-28-2013, 04:50 PM
Greetings all,

First off, I'm quite impressed with the resolution of touchRead measurements. 1/20 of a pF is way more sensitivity than I would have expected!

Due to my control-systems perspective, I'm wary a measurement that can take a variable time to return. So, I decided to code up a time bounded variant of Paul's touchRead() function. TouchReadTimeLim() takes an additional parameter, a maximum number of microseconds for the measurement. If the measurement reaches the max time before completion, it returns a negative value, usually -1, but occasionally the negative of a somewhat sane looking capacitance measurement. I've left all the other capacitance measuring parameters exactly as in touchRead().

@Paul,
I don't know what your preferred form is for patches; so please forgive me if pasting in longish chunks of code in a forum post isn't what you want. Please let me know if you'd like me to send you the modified files.

I modified two files, touch.c and core_pins.h and wrote a simple test script, TestTouchReadTimeLim. I'll paste the mods and the test code at the end of this post. I'm using the beta12 software on a Windows7 machine.

For testing, I put a short wire on a pin that does touchRead plus a 22 pF cap to ground (in addition to the capacitance from a solderless breadboard.) Here's a test run using 250 uSec for the timeout parameter:

1931 -- 22 pF cap + wire
1940
1939
1963
1932
1942
2217 -- 22 pF cap + wire + me touching wire's insulation
2219
2284
2307
2233
2287
-1 -- 22 pF cap + wire + me touching wire itself adds enough capacitance to trigger the timeout
-1
-1
-1
-1

====================
Code added to the end of touch.c:

/* ************************************************** ************
* touchReadTimeLim: a time-bounded version of Paul's touchRead()
* Larry Pfeffer, ursine @t gmail d0t c0m
* 27Jan2012: tested OK with sketch touchReadTestTimeBound
*
* To make it accessable, I've added a function
* prototype for touchReadTimeLim(...)to file core_pins.h,
* below the prototype for touchRead() itself:
*
* int touchReadTimeLim(uint8_t pin, unsigned Tmax); // Experimental LEP
*
************************************************** ************ */


#include <limits.h> /* for ULONG_MAX. Eventually move to top of
*file with other includes */

#include <stdlib.h> /* For abs(), if not included elsewhere.
*Ditto re moving to top of file */


unsigned long unwrapMicros(unsigned long curr, unsigned long prev)

/* Utility function to calculate the delta T between results
* of two calls to micros(). Robust to one rollover of the
* micros() counter.
*
* Eventually this function could be moved into some file/lib
* separate from touchRead* and renamed unwrapUL(?)
*/

{
if (curr >= prev) {
return (curr - prev);
} else {
/* the casts below may not be absolutely neccessary,
* but using them is a bit of extra insurance. */

return (unsigned long)( (ULONG_MAX - (unsigned long long)prev)
+ ((unsigned long long)curr + 1) );

} // ends if/else
}


int touchReadTimeLim(uint8_t pin, unsigned Tmax) // Tmax in uSec

// Like touchRead, but always returns within Tmax microseconds
{
uint32_t ch;
unsigned long Tstart;

Tstart = micros(); // First thing, record start time

if (pin >= NUM_DIGITAL_PINS) return 0;
ch = pin2tsi[pin];
if (ch == 255) return 0;

*portConfigRegister(pin) = PORT_PCR_MUX(0);
SIM_SCGC5 |= SIM_SCGC5_TSI;
TSI0_GENCS = 0;
TSI0_PEN = (1 << ch);
TSI0_SCANC = TSI_SCANC_REFCHRG(3) | TSI_SCANC_EXTCHRG(CURRENT);
TSI0_GENCS = TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_PS(PRESCALE) | TSI_GENCS_TSIEN | TSI_GENCS_SWTS;

delayMicroseconds(10);

/* Must unwrap the result from micros()
* to avoid getting wrong results when -- rarely but possibly --
* micros() rolls over during the measurment.
*/

/* while we haven't yet reached the timeout:
* note that the unwrap gives a deltaT,
* so must compare to Tmax, not to (Tstart + Tmax) */

while (unwrapMicros(micros(), Tstart) < (Tmax))
{
if (TSI0_GENCS & TSI_GENCS_SCNIP) { // if not ready
delayMicroseconds(1); // wait
} else {
delayMicroseconds(1); // not sure delay still necc.

// Normal return
return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
}
} // ends while micros()

// If we timeout, return negative of probably garbage value
// note extra -1, so timeout result is neg even if register
// reads zero when read before the measurment completes.

return -1 - abs(*((volatile uint16_t *)(&TSI0_CNTR1) + ch));
}

====================
One line of code added to core_pins.h, just below the prototype for touchRead():

int touchReadTimeLim(uint8_t pin, unsigned Tmax); // Experimental LEP

====================
The test sketch:


/* TestTouchReadTimeLim: a sketch to test function touchReadTimeLim, which
* is a time-bounded variant of touchRead.

#include <limits.h>

/* Note: for this test, core_pins now has declaration of touchReadTimeLim" */

//int touchReadTimeLim(uint8_t pin, unsigned long int Tmax); // should go into a header file when working

#define CAP_PIN (A8) /* change to whatever pin you use */
#define TOUCH_MAX_USEC (250) /* Paul's touchRead comment says 250 uSec for approx 33 pF */

void setup() {
Serial.begin(115200);
}

int touchReadAvg(int pin, int nSamp, long int maxT)
{
int i;
int runningSum = 0;
int cap;

for(i=0; i<nSamp; i++) {
cap = touchReadTimeLim(pin, maxT);
if (cap >= 0) {
runningSum = runningSum + cap;
} else {
// Serial.print("Timeout in touchReadTimeLim: ");
// Serial.println(cap);
return -1; // error return if any sample times out
}
}
return runningSum/nSamp;
}


void loop()
{
//Serial.println(touchReadAvg(CAP_PIN, 32, TOUCH_MAX_USEC)); // with averaging

Serial.println(touchReadTimeLim(CAP_PIN, TOUCH_MAX_USEC)); // without averaging

delay(500);
}
====================

LarryP
01-28-2013, 05:09 PM
Nuts, the forum software ate my code's indenting.

@Paul,
I tried to attach the files, but I'm getting invalid file type errors for .c, ,h and .ino files. Am I doing something wrong, or are those file types blocked for some reason? :confused:

Larry

ZTiK.nl
01-28-2013, 06:16 PM
If you put your code inside [ CODE] and [ /CODE] (remove spaces though), then the indentation should stick.
I never uploaded a file here except images, so I can't help with that, sry

(below the quick-reply box is a button 'Go Advanced' which will show more options like the [CODE] tags

LarryP
01-28-2013, 08:24 PM
Here are the three chunks of code for touchReadTimeLim -- this time with their indentation preserved. :)
If you have any comments or corrections, please let me know.

Thanks,

Larry

====================
Code added to the end of touch.c:



/* ************************************************** ************
* touchReadTimeLim: a time-bounded version of Paul's touchRead()
* Larry Pfeffer, ursine @t gmail d0t c0m
* 27Jan2012: tested OK with sketch touchReadTestTimeBound
*
* To make it accessable, I've added a function
* prototype for touchReadTimeLim(...)to file core_pins.h,
* below the prototype for touchRead() itself:
*
* int touchReadTimeLim(uint8_t pin, unsigned Tmax); // Experimental LEP
*
************************************************** ************ */


#include <limits.h> /* for ULONG_MAX. Eventually move to top of
*file with other includes */

#include <stdlib.h> /* For abs(), if not included elsewhere.
*Ditto re moving to top of file */


unsigned long unwrapMicros(unsigned long curr, unsigned long prev)

/* Utility function to calculate the delta T between results
* of two calls to micros(). Robust to one rollover of the
* micros() counter.
*
* Eventually this function could be moved into some file/lib
* separate from touchRead* and renamed unwrapUL(?)
*/

{
if (curr >= prev) {
return (curr - prev);
} else {
/* the casts below may not be absolutely neccessary,
* but using them is a bit of extra insurance. */

return (unsigned long)( (ULONG_MAX - (unsigned long long)prev)
+ ((unsigned long long)curr + 1) );

} // ends if/else
}


int touchReadTimeLim(uint8_t pin, unsigned Tmax) // Tmax in uSec

// Like touchRead, but always returns within Tmax microseconds
{
uint32_t ch;
unsigned long Tstart;

Tstart = micros(); // First thing, record start time

if (pin >= NUM_DIGITAL_PINS) return 0;
ch = pin2tsi[pin];
if (ch == 255) return 0;

*portConfigRegister(pin) = PORT_PCR_MUX(0);
SIM_SCGC5 |= SIM_SCGC5_TSI;
TSI0_GENCS = 0;
TSI0_PEN = (1 << ch);
TSI0_SCANC = TSI_SCANC_REFCHRG(3) | TSI_SCANC_EXTCHRG(CURRENT);
TSI0_GENCS = TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_PS(PRESCALE) | TSI_GENCS_TSIEN | TSI_GENCS_SWTS;

delayMicroseconds(10);

/* Must unwrap the result from micros()
* to avoid getting wrong results when -- rarely but possibly --
* micros() rolls over during the measurment.
*/

/* while we haven't yet reached the timeout:
* note that the unwrap gives a deltaT,
* so must compare to Tmax, not to (Tstart + Tmax) */

while (unwrapMicros(micros(), Tstart) < (Tmax))
{
if (TSI0_GENCS & TSI_GENCS_SCNIP) { // if not ready
delayMicroseconds(1); // wait
} else {
delayMicroseconds(1); // not sure delay still necc.

// Normal return
return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
}
} // ends while micros()

// If we timeout, return negative of probably garbage value
// note extra -1, so timeout result is neg even if register
// reads zero when read before the measurment completes.

return -1 - abs(*((volatile uint16_t *)(&TSI0_CNTR1) + ch));
}




====================
One line of code added to core_pins.h, just below the prototype for touchRead():



int touchReadTimeLim(uint8_t pin, unsigned Tmax); // Experimental LEP


====================
The test sketch:




/* TestTouchReadTimeLim: a sketch to test function touchReadTimeLim, which
* is a time-bounded variant of touchRead.

#include <limits.h>

/* Note: for this test, core_pins now has declaration of touchReadTimeLim" */

//int touchReadTimeLim(uint8_t pin, unsigned long int Tmax); // should go into a header file when working

#define CAP_PIN (A8) /* change to whatever pin you use */
#define TOUCH_MAX_USEC (250) /* Paul's touchRead comment says 250 uSec for approx 33 pF */

void setup() {
Serial.begin(115200);
}

int touchReadAvg(int pin, int nSamp, long int maxT)
{
int i;
int runningSum = 0;
int cap;

for(i=0; i<nSamp; i++) {
cap = touchReadTimeLim(pin, maxT);
if (cap >= 0) {
runningSum = runningSum + cap;
} else {
// Serial.print("Timeout in touchReadTimeLim: ");
// Serial.println(cap);
return -1; // error return if any sample times out
}
}
return runningSum/nSamp;
}


void loop()
{
//Serial.println(touchReadAvg(CAP_PIN, 32, TOUCH_MAX_USEC)); // with averaging

Serial.println(touchReadTimeLim(CAP_PIN, TOUCH_MAX_USEC)); // without averaging

delay(500);
}


====================

Robin
01-28-2013, 10:13 PM
Nuts, the forum software ate my code's indenting.

@Paul,
I tried to attach the files, but I'm getting invalid file type errors for .c, ,h and .ino files. Am I doing something wrong, or are those file types blocked for some reason? :confused:

Larry

You didn't do anything wrong. I've updated the forum configuration to allow the following file types:
.c
.cpp
.h
.ino
.pde

LarryP
01-28-2013, 11:08 PM
You didn't do anything wrong. I've updated the forum configuration to allow the following file types:
.c
.cpp
.h
.ino
.pde

Robin,

Thanks for making those file types uploadable. I think that'll make it easier for people on this forum to help one another.

Larry

LarryP
01-28-2013, 11:20 PM
If all goes well, the two modified files in the Arduino_1.0.3 and Paul's beta12 teensy3 software, namely touch.c and core_pins.h should be attached to this forum post. Also included is the Arduino sketch that produced the test results in my first post in this thread.

Larry