Non-blocking (no wait) touch sense (touchRead) routine for Teensy 3.2

Lalbert

Member
Here is a suggestion for an alternative method to read touch inputs on the Teensy 3.2. The Teensyduino library function touchRead() waits for the result before returning, so it may be too slow or cause excess delay to other tasks in some applications. Such was the case with an application I am developing. (It's a MIDI EWI synth. The maximum tolerable latency to read all 12 touch pads is about 10ms.)

My suggested method defines 3 new functions: touchSenseInit(pin), touchSenseDone() and touchSenseRead(). A test sketch is attached to show how (up to) 12 touch input readings can be acquired (continuously updated) without "blocking", i.e. without causing delay to other "background" tasks executing in the main loop. Note: The test sketch does not include any code to output the touch readings. This is left to the reader to implement. You could use the (USB) Serial library functions to output readings to the host PC running a terminal emulator (e.g. PuTTY -- or the Arduino "Serial Monitor").

I vaguely remember reading somewhere that the touchRead() function's maximum reading is 60,000, but I can't find anywhere in the code where this limit is imposed. Using my scheme, a time-out can be easily imposed. This would further reduce any latency due to touch sensing. There is another post somewhere on this forum which explains how the 10us delay can also be removed from the touchRead() function.
View attachment teensy32_touch_sense.ino

Oops... the program I attached to my post contains an error. Here is the corrected version.
The forum page says I can edit posts, but I can't see how. If anyone can enlighten me, I would be grateful.
View attachment 24050
 
Last edited by a moderator:
Have you looked at https://forum.pjrc.com/threads/13987-Teensy-3-0-capactive-touch?highlight=touchread+timeout ?

I think there's a need for a library on GitHub to support non-blocking touch sense. Posting code on the forum is great for working out issues, but not as effective as putting the code into an open source code repository. I mention GitHub because lots of other Teensy stuff is there.

Would be good to add debounce functionality, too. Bounce2 doesn't support capacitive touch.
 
Thanks for the suggestion... I will consider putting something up on GitHub. The library could include a couple more functions... one to return the "on/off" state of a given touch switch and another to detect button "hits" (transitions from "not touched" to "touched", with debounce).
 
Have you looked at https://forum.pjrc.com/threads/13987-Teensy-3-0-capactive-touch?highlight=touchread+timeout ?

I think there's a need for a library on GitHub to support non-blocking touch sense. Posting code on the forum is great for working out issues, but not as effective as putting the code into an open source code repository. I mention GitHub because lots of other Teensy stuff is there.

Would be good to add debounce functionality, too. Bounce2 doesn't support capacitive touch.

I started working on such a library, the existing code is tested on a Teensy 3.6.

https://github.com/arjuna-dev/TeensyTouch
 
cool library, thank you Lalbert / Arjuna !:)

seen that all new Teensy 4.x does not have a touch pin is a nightmare:mad: .. do you have any idea to get your library running for the new Teensy 4.0 (without touch pins) ? I would not have a problem if some external would RC needed (e.g. 10M resitors). I have my doubts that the 3.x will ever be available again, so i assume we all need any touchread() function (non waiting of course). All i find in net is using the 'old' https://www.pjrc.com/teensy/td_libs_CapacitiveSensor.html Arduino Library, or the https://github.com/adrianfreed/FastTouch library .. but all force waiting multiple at least 1ms (which i can't). So having your 'non-waiting' solution migrated to Teensy 4.0 would be awesome. any idea ?
 
Kalo, I agree, it would be a shame if Teensy 3.x is discontinued forever. But it is certainly possible to implement touch sensing on MCUs without hardware support, using only one resistor per touch-pad! The MCU must have I/O pins that can be configured as either analog inputs or logic GPIO. (What MCU doesn't these days? -- Most do.) Also, the application must be able to tolerate a short delay (no more than 10 microseconds), periodically, with all interrupts dsiabled. So it's "almost" non-blocking. The method is very similar to that used by the CTMU (charge time measurement unit) in some of the PIC family MCUs, e.g. PIC18FxxK22, which I have used in another project. Actually, CTMU is a misnomer, because the "charge time" is constant! The ADC measures the voltage on the touch-pad input at the end of the (constant) charge time. Of course the charge rate, hence measured voltage, will vary depending on the capacitance to ground. I have not so far documented the method or tested it, but I will do so and publish the document somewhere. Meanwhile, see attached scribble which I did a while back. I hope you can make some sense of it.

Touch Sense without CTMU.jpg
 
Cool input :) .. thank you Lalbert ! .. i might need some time to get all details, lol. Anyhow, i got your general idea .. so yes, could be an option, but it is still a pity that the PJRC team decided to go without Tocuh Pins in moment. No idea why. And i hope they will rethink again .. and producing any next Teensy updates with Touch Pins back.

Btw: an interesting related thread see here: touchRead value bouncing all over the place (as i still love the Flicker Library most)
 
Cool input :) but it is still a pity that the PJRC team decided to go without Tocuh Pins in moment. No idea why. And i hope they will rethink again .. and producing any next Teensy updates with Touch Pins back.
My guess the PJRC team (Paul and Robin) may not have that much pull with NXP corporation, to have them update the IMXRT chips to add in the capacitive touch sensing, that is in the K66 processor. Could be wrong.
 
Of course NXP will not modify or upgrade a mature MCU chip design, but they will cause grief to loyal customers if production of devices already supporting capacitive touch is terminated.

Anyhow, no worries... I have successfully tested a technique to implement touch-sense on a micro-controller without on-chip touch-sense hardware (ATmega328p, as found in Arduino Uno, Nano, etc). I am not claiming originality for this technique, but I have not seen it described anywhere.

The scheme requires one resistor and one diode for each touch-pad. The idea is based on the operation of the "CTMU" module found in some PIC18 devices. The CTMU is not necessary... its function can be replicated in software with the aid of a timer/counter peripheral, without causing excessive delays to other tasks. (The touch-sense "service routine" takes less than 30 microseconds per touch input.)

If your chosen MCU does not have enough ADC inputs for the required number of pads, then maybe an analog multiplexer chip could be used, or upgrade to an MCU with more ADC inputs!

When I finish documenting the technique, I will post it on various sites, including my own website, GitHub, and Elektor Labs. I'll also post a link on this forum for you guys.

Cheers - MJB
 
Made a copper foil board here somewhere that worked - seems it was T_4.x beta?

This code copyright 2009 seems to be similar and is updated to support T_4.x (based on #ifdef 1062 - even has a one left over from 1052 early T_4.0 bets :) )

...\hardware\teensy\avr\libraries\CapacitiveSensor\CapacitiveSensor.cpp

See : pjrc.com/teensy/td_libs_CapacitiveSensor.html
seems similar but longer timeout window when not 5V ... maybe it needs updated ... refined ...

Link Here: playground.arduino.cc/Main/CapacitiveSensor/

Has 11 year old uTube video of Paul Demo: https://www.youtube.com/watch?v=BHQPqQ_5ulc

As far as the NXP 1062 in use - the focus on and function at high speed of 600 MHz seems to have focused or limited design to include a few things ...
 
Hi defragster. Thanks for the links. I had found the PJRC CapacitiveSensor page (and GitHub repo) previously, but I have a short attention span... the lack of a concise description of Paul's touch algorithm, plus the complexity of the C++ code library, discouraged me from looking into his scheme in-depth.

Other forum posts have suggested that some touch-sense methods consume too much processor time, cause delays to other processes, etc. Not saying this applies to Pauls's method, but without any clear notes, who knows? So, I keep re-inventing the wheel! (At least I know how to make my wheel work as I want it.) Cheers!
 
In a brief look at the .cpp yesterday I saw a 5V #ifdef that uses a 10 us - but the other code - maybe a holdover for supporting slower architectures - still has timeout in ms so that could present a long wait. Being 15 years old it has been around and with those devices in mind. It does work with #ifdef code in for the T_4.x's 1062 MCU's.

I didn't build and test - haven't found my proto board with the copper tape I made. Also haven't done testing to monitor the blocking time of the reads on that code, or looked at the code enough to really know the code paths and likely behavior.
 
Many components...

Of course NXP will not modify or upgrade a mature MCU chip design, but they will cause grief to loyal customers if production of devices already supporting capacitive touch is terminated.

Anyhow, no worries... I have successfully tested a technique to implement touch-sense on a micro-controller without on-chip touch-sense hardware (ATmega328p, as found in Arduino Uno, Nano, etc). I am not claiming originality for this technique, but I have not seen it described anywhere.

The scheme requires one resistor and one diode for each touch-pad. The idea is based on the operation of the "CTMU" module found in some PIC18 devices. The CTMU is not necessary... its function can be replicated in software with the aid of a timer/counter peripheral, without causing excessive delays to other tasks. (The touch-sense "service routine" takes less than 30 microseconds per touch input.)

If your chosen MCU does not have enough ADC inputs for the required number of pads, then maybe an analog multiplexer chip could be used, or upgrade to an MCU with more ADC inputs!

When I finish documenting the technique, I will post it on various sites, including my own website, GitHub, and Elektor Labs. I'll also post a link on this forum for you guys.

Cheers - MJB

No offense Lalbert, but one diode and one resistor per pad is a lot more overhead than no external components! As far as I remember there is an atmega328 library that just uses internal pullups?
 
Back
Top