A lightweight, fast library for reading standard 4-wire resistive touch panels using nothing more than the standard Arduino Framework pin functions.
The library is designed to be portable across Arduino Framework compatible platforms while still providing enough configurability to achieve fast, reliable touch detection.
The library returns raw touch coordinates, allowing the application (or a higher-level UI library such as InputEventsTouchUI) to perform its own calibration and mapping.
- Supports standard 4-wire resistive touch panels
- Uses only standard Arduino pin functions
- Configurable for virtually any Arduino-compatible board/display combination
- Works when either the positive or negative touch panel pins are the analogue-capable pair
- Median filtering for improved noise immunity
- Configurable sample count
- Configurable GPIO settling delay - crucial for accurate analog reads
- Optional X and Y axis mirroring
- Touch detection using a configurable threshold to suit any board, screen or wiring
- Minimal RAM usage
- No display or graphics dependencies
- Works with 10 or 12bit ADCs (12bit useful for mapping to higher resolution displays)
The library does not report 'pressure' - the
TouchPoint_s.zis populated with either0or1to denoted 'touched'.
This is a deliberate design choice as most applications simply need to know where the display was touched, not how hard. Reading pressure requires two more analogRead()s and some processor intensive maths - a cost not worth bearing unless you are writing a drawing app where perhaps pressure equates to pen width. If you are doing this, then pull requests are welcome!
If pressure is ever included, it will be optional to ensure performance can be maintained.
On an Arduino UNO, Adafruit's TouchScreen will return a touch point in ~800μs. With exactly the same parameters (2 samples, no settling delay), this library will return a touch point in ~610μs. That can be further tuned with accurate and repeatable results down to ~325μs - on an UNO.
With an Adafruit 1770 display connected to a Teensy 4.1, the time is down to ~70μs (15μs settling, single sample).
Repeatable results at 100ms interval on an UNO (with a nice 4D Systems touch panel):
X: 553 Y: 592 Z: 1 μs: 324
X: 553 Y: 592 Z: 1 μs: 324
X: 553 Y: 592 Z: 1 μs: 324
X: 553 Y: 592 Z: 1 μs: 328
Teensy 4.1 with Adafruit 1770 display:
X: 632 Y: 546 Z: 1 μs: 67
X: 633 Y: 546 Z: 1 μs: 67
X: 633 Y: 546 Z: 1 μs: 67
X: 633 Y: 546 Z: 1 μs: 67
I've been asked, so:
"Why use the ResistiveTouchScreen library rather than Adafruit's TouchScreen?"
Lady Ada's library has become the defacto standard and I have used it for many years - primarily on Adafruit displays (I encourage you to support her by buying her products).
However, The Adafruit TouchScreen is written for Adafruit products (as it should be), is limited to 10bit ADCs and has no configuration or tuning opportunities.
For example, the X & Y are always flipped to suit the hardware (this behaviour can be replicated in ResistiveTouchScreen with mirrorX() and mirrorY()) and the pin settling is only applied (non-optionally) to ARM processoers. Sampling is baked in at 2 samples.
The Adafruit library does provide Z pressure, but that comes at a cost and is not needed by the majority of applications.
Feedback and bug reports are welcome or if you have any questions, drop by for a chat on Discord 
Install the ResistiveTouchScreen library via the Arduino IDE Libary Manager.
Add the following to your platformio.ini file:
lib_deps =
stutchbury/ResistiveTouchScreen@^1.1.1
Where XP, YP, XN & YN are your X+, Y+, X- & Y- pins respectively:
#include <ResistiveTouchScreen.h>
ResistiveTouchScreen rts(XP, YP, XM, YM);
void setup() {
Serial.begin(9600);
delay(1000);
}
void loop() {
// Get the touch point
TouchPoint_s tp = rts.getTouchPoint();
// Print to serial if higher than the touched threshold
if ( tp.z > 0 ) {
Serial.print("X:\t");
Serial.print(tp.x);
Serial.print("\tY:\t");
Serial.print(tp.y);
Serial.print("\tZ:\t");
Serial.println(tp.z);
}
delay(100); //Don't scroll too fast! (for the example only - don't use delay() in your sketches)
}There are four examples - for basic use, configuration parameters, tuning and threshold.
Methods for configuring and adapting to different hardware. These allow wiring errors or constraints to be fixed in software.
Set the threshold above which screen will be deemed touched.
The minimum returned X or Y value for most displays is usually greater than 100, so this is the default.
- If the
TouchPoint_s.zalways returns1then you need to increase the threshold. - if the lower value edges of the touch panel do not respond to touch, you need to lower the threshold.
rts.setThreshold(105);
Use X- and Y- to analogRead() the resistance values rather than X+ and Y+.
Pass either true or false
Useful if your routing conflicts or dual use of the four pins means the X+ and Y+ can't do analog (looking at you, EastRising)
rts.useNegativeReadPins(bool); Will configure both X & Y pins (default true).
rts.useNegativeReadPins(bool, bool); Will configure X & Y pins individually.
Mirror either axis to suit panel orientation.
Pass either true or false
rts.mirrorX();
rts.mirrorY();
Methods for tuning performance for different boards and display combinations.
Our goal here is consistency of read - ie repeatablility. When you press and hold a single point on the touch panel (with a touch pen or finger nail) the resulting X & Y coordinates should change as little as possible.
It turns out that the settling time yields better results than multiple samples. The price of a few microseconds delay before a single read is lower than taking more than one sample. The two layers of the touch panel have some inherant capacitance so we must wait for that to settle before reading.
Set the the number of micros seconds to wait between setting pin mode and analogRead()ing. Default is 20μs (microseconds)
Different MCUs, boards and screens (or combinations of) will require different settings. Higher values are likely to be required on cheaper touch panels.
Usually in the range 0 to 50μs.
Hint: Ensure number of samples to 1 and tune this parameter first.
rts.setPinSettlingUs(20);
Set the number of analogRead() samples to take.
Default is 1, maximum is 5.
rts.setNumSamples(2);
Increasing the sample count improves noise rejection at the expense of read speed.
This library deliberately only returns raw ADC values for X & Y rather than calibrated display coordinates.
Touch to display calibration, rotation and mapping are application-specific concerns and are better handled by the graphics or UI framework.
The InputEventsTouchUI provides all this functionality and more!
GPL v2
If you'd like to know how resistive touch panels work, this is a very helpful resource from Infineon: Interface to Four-Wire Resistive Touchscreen - I used it extensively for this library