there are a couple of old threads I found while investigating if I could speed up the time taken by touchRead() function on teensy 3.6.
a few threads noted that when moving from T3.2 to T3.6, the speed of the capacitive touch dropped significantly, which can be an issue for responsiveness, especially when time-multiplexing touch inputs. but there's good news!
the threads all contained useful snippets, and indicated that the 3.6 chip has a slightly more limited touch unit inside it, but none of them came to a firm conclusion in one place. so I just wanted to jot down my findings, drawn from those threads and just experimenting with the register settings, in case they are useful for others:
there's a simple change you can make to touchRead() to make it roughly an order of magnitude faster by increasing the drive current. it's a trivial change to a register configuration, but it's not provided by the arduino-compatible API, so I thought I'd jot it down here for anyone passing by here looking for a way to speed things up.
the bottom line is to extract the teensy 'TSI lite' specific code from the core touch.c, thus:
here I've renamed touchRead to myTouchReadT36, and split it into two halves - start and end.
in this way you can do a kind of non-blocking read if you want - call myTouchReadT36Start, do some other work (eg servicing some I2C, or reading an ADC, or whatever), and then myTouchReadT36End.
and the key to making it faster is simply to change the values in the line that sets the TSI0_GENCS register, in particular the TSI_GENCS_REFCHRG and TSI_GENCS_EXTCHRG settings.
you'll need to tune it for your electrodes, the defaults are as above (4, 3) - I found that I changed to 7,7 (maximum drive!) and it worked well for my electrodes with relatively high 'base' (untouched) capacitance - the default routine was returning around 4000, rising to 9000 when touched, taking over a millisecond.
with some tuning, I still got a wide range of values but times under 200 microseconds.
you can also tune the NSCAN and PRESCALE defines to configure how many averageing passes and how much prescales the counter (?) - but the key change is to increase the charge values. I think I ended up with NSCAN 7 and PRESCALE 3, tho this felt quite application dependent.
anyway I hope that by pulling together info that is already out there on this forum in one 'it works! you can make it faster!' post will be helpful to someone.
a few threads noted that when moving from T3.2 to T3.6, the speed of the capacitive touch dropped significantly, which can be an issue for responsiveness, especially when time-multiplexing touch inputs. but there's good news!
the threads all contained useful snippets, and indicated that the 3.6 chip has a slightly more limited touch unit inside it, but none of them came to a firm conclusion in one place. so I just wanted to jot down my findings, drawn from those threads and just experimenting with the register settings, in case they are useful for others:
there's a simple change you can make to touchRead() to make it roughly an order of magnitude faster by increasing the drive current. it's a trivial change to a register configuration, but it's not provided by the arduino-compatible API, so I thought I'd jot it down here for anyone passing by here looking for a way to speed things up.
the bottom line is to extract the teensy 'TSI lite' specific code from the core touch.c, thus:
Code:
#define NSCAN 9
#define PRESCALE 2
void myTouchReadT36Start(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;
// change TSI_GENCS_REFCHRG and TSI_GENCS_EXTCHRG to 7 for higher drive current & speed
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;
}
int myTouchReadT36End()
{
while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
delayMicroseconds(1);
return TSI0_DATA & 0xFFFF;
}
int myTouchReadT36(uint8_t pin) {
myTouchReadT36Start(pin);
delayMicroseconds(10);
return myTouchReadT36End();
}
here I've renamed touchRead to myTouchReadT36, and split it into two halves - start and end.
in this way you can do a kind of non-blocking read if you want - call myTouchReadT36Start, do some other work (eg servicing some I2C, or reading an ADC, or whatever), and then myTouchReadT36End.
and the key to making it faster is simply to change the values in the line that sets the TSI0_GENCS register, in particular the TSI_GENCS_REFCHRG and TSI_GENCS_EXTCHRG settings.
you'll need to tune it for your electrodes, the defaults are as above (4, 3) - I found that I changed to 7,7 (maximum drive!) and it worked well for my electrodes with relatively high 'base' (untouched) capacitance - the default routine was returning around 4000, rising to 9000 when touched, taking over a millisecond.
with some tuning, I still got a wide range of values but times under 200 microseconds.
you can also tune the NSCAN and PRESCALE defines to configure how many averageing passes and how much prescales the counter (?) - but the key change is to increase the charge values. I think I ended up with NSCAN 7 and PRESCALE 3, tho this felt quite application dependent.
anyway I hope that by pulling together info that is already out there on this forum in one 'it works! you can make it faster!' post will be helpful to someone.