Add ADC Touchscreen

This commit is contained in:
fvanroie 2020-04-05 11:07:16 +02:00
parent e6e990a2b5
commit 02b92200f6
13 changed files with 690 additions and 0 deletions

View File

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View File

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

52
lib/TouchScreen/README.md Normal file
View File

@ -0,0 +1,52 @@
# Adafruit TouchScreen with mod for ESP32 UNO
This is the 4-wire resistive touch screen firmware for Arduino. Works with all Arduinos and Teensy
To install, click DOWNLOAD SOURCE in the top right corner, and rename the uncompressed folder "TouchScreen". See our tutorial at http://www.ladyada.net/library/arduino/libraries.html on Arduino Library installation
Added modification to allow the 4-wire resistive touchscreen of MCU Friend LCDs with parallel data interfaces to be used with ESP32 UNO style boards whilst WiFi is enabled. Tested on a red board MCU Friend with default touchscreen wiring.
## Reason for Modification
ESP32 WiFi removes access to ADC2 channel so pins 4 and 15 attached to the touchscreen no longer have analog input capability. Pin 15 already shares a connection with analog pin 35, so an additional connection is made between pin 4 and analog pin 39. Pins 35 and 39 now provide the analog input. Pins 35 and 39 are input only so always present a high impedance to avoid the risk of two outputs shorting.
## Prerequisites
An extra wiring mod is needed in addition to those shown in the [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) instructions, but do not affect the software functionality or configuration.
Wiring for ESP UNO type board, with extra wire shown in green:
![image1](extras/wiring.jpg)
## Installing
Download and install the library using your IDE, eg Arduino.
The modification uses conditional compilation. To enable the changes, modify TouchScreen.h to uncomment #define ESP32_WIFI_TOUCH
```
// ESP32 specific
//#define ESP32_WIFI_TOUCH // uncomment to use parallel MCU Friend LCD touchscreen with ESP32 UNO Wifi
#ifdef ESP32
#define ADC_MAX 4095 // maximum value for ESP32 ADC (default 11db, 12 bits)
#define aXM 35 // analog input pin connected to LCD_RS
#define aYP 39 // analog input pin connected to LCD_WR
#else
#define ADC_MAX 1023 // Arduino
#endif
#define NOISE_LEVEL 4 // Allow small amount of measurement noise
```
## Using
No changes are required to existing sketches, just recompilation.
Compatible with both [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) and [MCUFRIEND_kbv](https://github.com/prenticedavid/MCUFRIEND_kbv/) libraries
Touchscreen needs to be calibrated before use, either manually using included [ESP32testTouch](examples/ESP32testTouch) or eg [TouchScreen_Calibr_native](https://github.com/prenticedavid/MCUFRIEND_kbv/tree/master/examples/TouchScreen_Calibr_native)
![image3](extras/example.jpg)

View File

@ -0,0 +1,4 @@
This is the 4-wire resistive touch screen firmware for Arduino. Works with all Arduinos and Teensy
To install, click DOWNLOAD SOURCE in the top right corner, and rename the uncompressed folder "TouchScreen". See our tutorial at http://www.ladyada.net/library/arduino/libraries.html on Arduino Library installation

View File

@ -0,0 +1,289 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// (c) ladyada / adafruit
// Code under MIT License
// Code under MIT License
#include "Arduino.h"
#include "pins_arduino.h"
#ifdef __AVR
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#endif
#include "TouchScreen.h"
// increase or decrease the touchscreen oversampling. This is a little different than you make think:
// 1 is no oversampling, whatever data we get is immediately returned
// 2 is double-sampling and we only return valid data if both points are the same
// 3+ uses insert sort to get the median value.
// We found 2 is precise yet not too slow so we suggest sticking with it!
#define NUMSAMPLES 2
TSPoint::TSPoint(void) {
x = y = 0;
}
TSPoint::TSPoint(int16_t x0, int16_t y0, int16_t z0) {
x = x0;
y = y0;
z = z0;
}
bool TSPoint::operator==(TSPoint p1) {
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
}
bool TSPoint::operator!=(TSPoint p1) {
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
}
#if (NUMSAMPLES > 2)
static void insert_sort(int array[], uint8_t size) {
uint8_t j;
int save;
for (int i = 1; i < size; i++) {
save = array[i];
for (j = i; j >= 1 && save < array[j - 1]; j--)
array[j] = array[j - 1];
array[j] = save;
}
}
#endif
TSPoint TouchScreen::getPoint(void) {
int x, y, z;
int samples[NUMSAMPLES];
uint8_t i, valid;
valid = 1;
pinMode(_yp, INPUT);
pinMode(_ym, INPUT);
pinMode(_xp, OUTPUT);
pinMode(_xm, OUTPUT);
#if defined (USE_FAST_PINIO)
*xp_port |= xp_pin;
*xm_port &= ~xm_pin;
#else
digitalWrite(_xp, HIGH);
digitalWrite(_xm, LOW);
#endif
#ifdef __arm__
delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle
#endif
for (i=0; i<NUMSAMPLES; i++) {
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
samples[i] = analogRead(aYP);
#else
samples[i] = analogRead(_yp);
#endif
}
#if NUMSAMPLES > 2
insert_sort(samples, NUMSAMPLES);
#endif
#if NUMSAMPLES == 2
// Allow small amount of measurement noise, because capacitive
// coupling to a TFT display's signals can induce some noise.
if (samples[0] - samples[1] < -NOISE_LEVEL || samples[0] - samples[1] > NOISE_LEVEL) {
valid = 0;
} else {
samples[1] = (samples[0] + samples[1]) >> 1; // average 2 samples
}
#endif
x = (ADC_MAX-samples[NUMSAMPLES/2]);
pinMode(_xp, INPUT);
pinMode(_xm, INPUT);
pinMode(_yp, OUTPUT);
pinMode(_ym, OUTPUT);
#if defined (USE_FAST_PINIO)
*ym_port &= ~ym_pin;
*yp_port |= yp_pin;
#else
digitalWrite(_ym, LOW);
digitalWrite(_yp, HIGH);
#endif
#ifdef __arm__
delayMicroseconds(20); // Fast ARM chips need to allow voltages to settle
#endif
for (i=0; i<NUMSAMPLES; i++) {
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
samples[i] = analogRead(aXM);
#else
samples[i] = analogRead(_xm);
#endif
}
#if NUMSAMPLES > 2
insert_sort(samples, NUMSAMPLES);
#endif
#if NUMSAMPLES == 2
// Allow small amount of measurement noise, because capacitive
// coupling to a TFT display's signals can induce some noise.
if (samples[0] - samples[1] < -NOISE_LEVEL || samples[0] - samples[1] > NOISE_LEVEL) {
valid = 0;
} else {
samples[1] = (samples[0] + samples[1]) >> 1; // average 2 samples
}
#endif
y = (ADC_MAX-samples[NUMSAMPLES/2]);
// Set X+ to ground
// Set Y- to VCC
// Hi-Z X- and Y+
pinMode(_xp, OUTPUT);
pinMode(_yp, INPUT);
#if defined (USE_FAST_PINIO)
*xp_port &= ~xp_pin;
*ym_port |= ym_pin;
#else
digitalWrite(_xp, LOW);
digitalWrite(_ym, HIGH);
#endif
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
int z1 = analogRead(aXM);
int z2 = analogRead(aYP);
#else
int z1 = analogRead(_xm);
int z2 = analogRead(_yp);
#endif
if (_rxplate != 0) {
// now read the x
float rtouch;
rtouch = z2;
rtouch /= z1;
rtouch -= 1;
rtouch *= x;
rtouch *= _rxplate;
rtouch /= ADC_MAX+1;
z = rtouch;
} else {
z = (ADC_MAX-(z2-z1));
}
if (! valid) {
z = 0;
}
return TSPoint(x, y, z);
}
TouchScreen::TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym,
uint16_t rxplate=0) {
_yp = yp;
_xm = xm;
_ym = ym;
_xp = xp;
_rxplate = rxplate;
#if defined (USE_FAST_PINIO)
xp_port = portOutputRegister(digitalPinToPort(_xp));
yp_port = portOutputRegister(digitalPinToPort(_yp));
xm_port = portOutputRegister(digitalPinToPort(_xm));
ym_port = portOutputRegister(digitalPinToPort(_ym));
xp_pin = digitalPinToBitMask(_xp);
yp_pin = digitalPinToBitMask(_yp);
xm_pin = digitalPinToBitMask(_xm);
ym_pin = digitalPinToBitMask(_ym);
#endif
pressureThreshhold = 10;
}
int TouchScreen::readTouchX(void) {
pinMode(_yp, INPUT);
pinMode(_ym, INPUT);
digitalWrite(_yp, LOW);
digitalWrite(_ym, LOW);
pinMode(_xp, OUTPUT);
digitalWrite(_xp, HIGH);
pinMode(_xm, OUTPUT);
digitalWrite(_xm, LOW);
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
return (ADC_MAX-analogRead(aYP));
#else
return (ADC_MAX-analogRead(_yp));
#endif
}
int TouchScreen::readTouchY(void) {
pinMode(_xp, INPUT);
pinMode(_xm, INPUT);
digitalWrite(_xp, LOW);
digitalWrite(_xm, LOW);
pinMode(_yp, OUTPUT);
digitalWrite(_yp, HIGH);
pinMode(_ym, OUTPUT);
digitalWrite(_ym, LOW);
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
return (ADC_MAX-analogRead(aXM));
#else
return (ADC_MAX-analogRead(_xm));
#endif
}
uint16_t TouchScreen::pressure(void) {
// Set X+ to ground
pinMode(_xp, OUTPUT);
digitalWrite(_xp, LOW);
// Set Y- to VCC
pinMode(_ym, OUTPUT);
digitalWrite(_ym, HIGH);
// Hi-Z X- and Y+
digitalWrite(_xm, LOW);
pinMode(_xm, INPUT);
digitalWrite(_yp, LOW);
pinMode(_yp, INPUT);
#if defined (ESP32_WIFI_TOUCH) && defined (ESP32)
int z1 = analogRead(aXM);
int z2 = analogRead(aYP);
#else
int z1 = analogRead(_xm);
int z2 = analogRead(_yp);
#endif
if (_rxplate != 0) {
// now read the x
float rtouch;
rtouch = z2;
rtouch /= z1;
rtouch -= 1;
rtouch *= readTouchX();
rtouch *= _rxplate;
rtouch /= ADC_MAX+1;
return rtouch;
} else {
return (ADC_MAX-(z2-z1));
}
}

View File

@ -0,0 +1,65 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// (c) ladyada / adafruit
// Code under MIT License
#ifndef _ADAFRUIT_TOUCHSCREEN_H_
#define _ADAFRUIT_TOUCHSCREEN_H_
#include <stdint.h>
// ESP32 specific
#define ESP32_WIFI_TOUCH // uncomment to use parallel MCU Friend LCD touchscreen with ESP32 UNO Wifi
#ifdef ESP32
#define ADC_MAX 4095 // maximum value for ESP32 ADC (default 11db, 12 bits)
#define aXM 35 // analog input pin connected to LCD_RS
#define aYP 39 // analog input pin connected to LCD_WR
#else
#define ADC_MAX 1023 // Arduino
#endif
#define NOISE_LEVEL 4 // Allow small amount of measurement noise
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__) || defined(TEENSYDUINO) || defined(__AVR_ATmega2560__)
typedef volatile uint8_t RwReg;
#endif
#if defined(ARDUINO_STM32_FEATHER)
typedef volatile uint32 RwReg;
#endif
#if defined(ARDUINO_FEATHER52) || defined(ESP32)
typedef volatile uint32_t RwReg;
#endif
#if defined(__AVR__) || defined(TEENSYDUINO) || defined(ARDUINO_ARCH_SAMD)
#define USE_FAST_PINIO
#endif
class TSPoint {
public:
TSPoint(void);
TSPoint(int16_t x, int16_t y, int16_t z);
bool operator==(TSPoint);
bool operator!=(TSPoint);
int16_t x, y, z;
};
class TouchScreen {
public:
TouchScreen(uint8_t xp, uint8_t yp, uint8_t xm, uint8_t ym, uint16_t rx);
bool isTouching(void);
uint16_t pressure(void);
int readTouchY();
int readTouchX();
TSPoint getPoint();
int16_t pressureThreshhold;
private:
uint8_t _yp, _ym, _xm, _xp;
uint16_t _rxplate;
volatile RwReg *xp_port, *yp_port, *xm_port, *ym_port;
RwReg xp_pin, xm_pin, yp_pin, ym_pin;
};
#endif

View File

@ -0,0 +1,126 @@
/*
Test MCU Friend parallel display and resistive touchscreen by drawing touch points
on screen, use something pointed for more accuracy
Need this modified Touchscreen library and one of:
- TFT_eSPI much faster for ESP32, must select correct display driver
- MCUFRIEND_kbv more display driver support, auto detects display driver
*/
#define TFT_eSPIlib // comment out to use MCUFRIEND_kbv
#ifdef TFT_eSPIlib
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
#else
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#endif
#include <TouchScreen.h>
// adjust pressure sensitivity - note works 'backwards'
#define MINPRESSURE 200
#define MAXPRESSURE 1000
// some colours to play with
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Either run TouchScreen_Calibr_native.ino and apply results to the arrays below
// or just use trial and error from drawing on screen
// ESP32 coordinates at default 12 bit resolution have range 0 - 4095
// however the ADC cannot read voltages below 150mv and tops out around 3.15V
// so the actual coordinates will not be at the extremes
// each library and driver may have different coordination and rotation sequence
const int coords[] = {3800, 500, 300, 3800}; // portrait - left, right, top, bottom
const int rotation = 0; // in rotation order - portrait, landscape, etc
const int XP = 27, XM = 15, YP = 4, YM = 14; // default ESP32 Uno touchscreen pins
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
void setup() {
Serial.begin(115200);
#ifdef TFT_eSPIlib
Serial.println("TFT_eSPI library");
tft.begin();
#else
Serial.println("MCUFRIEND_kbv library");
idDisplay();
#endif
// screen orientation and background
String orientation;
switch (rotation) {
case 0:
orientation = "Portrait";
break;
case 1:
orientation = "Landscape";
break;
case 2:
orientation = "Portrait Inverted";
break;
case 3:
orientation = "Landscape Inverted";
break;
}
Serial.println(orientation);
tft.setRotation(rotation);
tft.fillScreen(BLACK);
}
void loop() {
// display touched point with colored dot
uint16_t pixel_x, pixel_y;
boolean pressed = Touch_getXY(&pixel_x, &pixel_y, true);
}
boolean Touch_getXY(uint16_t *x, uint16_t *y, boolean showTouch) {
TSPoint p = ts.getPoint();
pinMode(YP, OUTPUT); //restore shared pins
pinMode(XM, OUTPUT);
digitalWrite(YP, HIGH); //because TFT control pins
digitalWrite(XM, HIGH);
bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
if (pressed) {
switch (rotation) {
case 0: // portrait
*x = map(p.x, coords[0], coords[1], 0, tft.width());
*y = map(p.y, coords[2], coords[3], 0, tft.height());
break;
case 1: // landscape
*x = map(p.y, coords[1], coords[0], 0, tft.width());
*y = map(p.x, coords[2], coords[3], 0, tft.height());
break;
case 2: // portrait inverted
*x = map(p.x, coords[1], coords[0], 0, tft.width());
*y = map(p.y, coords[3], coords[2], 0, tft.height());
break;
case 3: // landscape inverted
*x = map(p.y, coords[0], coords[1], 0, tft.width());
*y = map(p.x, coords[3], coords[2], 0, tft.height());
break;
}
if (showTouch) tft.fillCircle(*x, *y, 2, YELLOW);
}
return pressed;
}
#ifndef TFT_eSPIlib
void idDisplay() {
// MCUFRIEND_kbv library only
uint16_t ID = tft.readID();
Serial.print("TFT ID = 0x");
Serial.println(ID, HEX);
if (ID == 0xD3D3) ID = 0x9486; // write-only shield
tft.begin(ID);
}
#endif

View File

@ -0,0 +1,35 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// This demo code returns raw readings, public domain
#include <stdint.h>
#include "TouchScreen.h"
#define YP A2 // must be an analog pin, use "An" notation!
#define XM A3 // must be an analog pin, use "An" notation!
#define YM 8 // can be a digital pin
#define XP 9 // can be a digital pin
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
// a point object holds x y and z coordinates
TSPoint p = ts.getPoint();
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (p.z > ts.pressureThreshhold) {
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
}
delay(100);
}

View File

@ -0,0 +1,37 @@
// Touch screen library with X Y and Z (pressure) readings as well
// as oversampling to avoid 'bouncing'
// This demo code returns raw readings, public domain
#include <stdint.h>
#include "TouchScreen.h"
// These are the pins for the shield!
#define YP A1 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 7 // can be a digital pin
#define XP 6 // can be a digital pin
#define MINPRESSURE 10
#define MAXPRESSURE 1000
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
// a point object holds x y and z coordinates
TSPoint p = ts.getPoint();
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print("\tPressure = "); Serial.println(p.z);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1,9 @@
name=Adafruit TouchScreen
version=1.0.1
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Adafruit TouchScreen display library.
paragraph=Adafruit TouchScreen display library.
category=Display
url=https://github.com/s60sc/Adafruit_TouchScreen
architectures=*

View File

@ -40,6 +40,7 @@ ESP8266WebServer * webClient; // for snatshot
#endif #endif
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
#include "Touchscreen.h" // For Uno Shield or ADC based resistive touchscreens
#include <WebServer.h> #include <WebServer.h>
WebServer * webClient; // for snatshot WebServer * webClient; // for snatshot
#endif // ESP32 #endif // ESP32