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
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.