touchRead() speed

Status
Not open for further replies.

Davidelvig

Well-known member
I'm using 4 pins to rapidly detect changes in finger touches. The pins connect through 3-4" patch wires to a small round-headed screw.
A set of four reads (one of each pin) takes about 600 microseconds to complete when no screw heads are touched.
Loop Count: 464056 Last Loop Time: 598 microseconds
Loop Count: 464057 Last Loop Time: 597 microseconds
Loop Count: 464058 Last Loop Time: 595 microseconds
Loop Count: 464059 Last Loop Time: 598 microseconds
Loop Count: 464060 Last Loop Time: 600 microseconds
Loop Count: 464061 Last Loop Time: 598 microseconds
Loop Count: 464062 Last Loop Time: 598 microseconds
Loop Count: 464063 Last Loop Time: 598 microseconds
Loop Count: 464064 Last Loop Time: 594 microseconds
Loop Count: 464065 Last Loop Time: 600 microseconds

When all four screw heads are touched, the time increases to about 3000 microseconds.
Loop Count: 826493 Last Loop Time: 3139 microseconds
Loop Count: 826494 Last Loop Time: 2972 microseconds
Loop Count: 826495 Last Loop Time: 3147 microseconds
Loop Count: 826496 Last Loop Time: 3069 microseconds
Loop Count: 826504 Last Loop Time: 3029 microseconds
Loop Count: 826505 Last Loop Time: 3109 microseconds
Loop Count: 826506 Last Loop Time: 3095 microseconds
Loop Count: 826507 Last Loop Time: 3120 microseconds
Loop Count: 826508 Last Loop Time: 3063 microseconds

Each pin "rests" untouched at about a touchRead value of 800-1100 (second column below - arbitrary units as far as I know),
Valve LastTouchVal TouchTime IsPressed Pin Length
1 869 127 0 16 2
2 1057 151 0 17 1
3 837 122 0 1 3
4 842 123 0 0 5

and spikes to 5000-6500 when touched (all four screws touched here)

Valve LastTouchVal TouchTime IsPressed Pin Length
1 6470 868 1 16 2
2 6420 860 1 17 1
3 5895 789 1 1 3
4 5299 713 1 0 5

I think I can live with the 3000 micros, though it seems as though I have some headroom.

Any way to adjust touchRead to stop and return when it reaches a threshold (above which you don't care how high it gets)?

I saw a post about this in the past (on perhaps truncating the time of touchRead() above certain time thresholds), though I can't find it now.
 
Last edited:
I think I know the spot to address in touch.c

Here's touch.c
Code:
int touchRead(uint8_t pin)
{
	uint32_t ch;

	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;
#if defined(HAS_KINETIS_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);
	while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
	delayMicroseconds(1);
	return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
#elif defined(HAS_KINETIS_TSI_LITE)
	TSI0_GENCS = TSI_GENCS_REFCHRG(4) | TSI_GENCS_EXTCHRG(3) | TSI_GENCS_PS(PRESCALE)
		| TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_TSIEN | TSI_GENCS_EOSF;
	TSI0_DATA = TSI_DATA_TSICH(ch) | TSI_DATA_SWTS;
	delayMicroseconds(10);
	while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
	delayMicroseconds(1);
	return TSI0_DATA & 0xFFFF;
#endif
}
in one of the lines above like:
Code:
while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
add an OR (||) condition of time passing that would exit the while() loop, and that same time condition would return from the function with a value indicating "touched"

In fact, maybe I need to just create a new library called pinTouched() with an optional passed-in argument indicating how long to wait before calling it "touched"
 
I've written a library called touchablePin based on Paul's touchRead.c.
https://github.com/Davidelvig/touchablePin

A quick sketch to demonstrate it is here:
Code:
#include <touchablePin.h>

#define TOUCH_PIN 16
touchablePin pin(TOUCH_PIN);

void setup() { 
      Serial.begin(115200);
      delay(1000);
      Serial.print("Started...");
      pin.initUntouched();
      Serial.println("...Finished");
}
unsigned long lastLoopTime = 0,
              mainLoopCount = 0;

void loop() {
    unsigned long timeStart = micros();   
    bool y = pin.isTouched();
    unsigned long timeEnd = micros();    

    Serial.printf("Count: %d\tisTouched() = %d in %d microseconds\n",
                  mainLoopCount, y , timeEnd - timeStart); 
    mainLoopCount++;
}

Paul, I thought there might have been a library change to this in he past, though I couldn't find a link about it.
If there's not this functionality in place, perhaps others might find this one useful.
 
Last edited:
Status
Not open for further replies.
Back
Top