In diesem Beitrag möchte ich die Möglichkeiten meiner TouchEvent Library zeigen. Sie ermöglicht es sehr einfach auf Ereignisse am Touch-Screen zu reagieren. Die Library könnt ihr ganz einfach von GitHub herunterladen und in das Arduino libraries Verzeichnis kopieren. Es gibt in den Beispielen ein Demo-Programm, das die Anwendung zeigt. Anhand dieses Demo-Programms werde ich in diesem Beitrag die einzelnen Funktionen der Bibliothejk erläutern.
Als Hardware benötigen wir einen ArduiTouch mit ESP32-Prozessor.
Code:
/* this example demonstrates the usage of the TouchEvent library * it uses a 2.4 inch TFT display with resistive touch screen * the display uses an ILI9341 controller * and the touch screen a XPT2046 * the module is used together with an ESP32 but any other * arduino compatible processor should work * For the used pins see definitions in the code */ //required libraries #include <SPI.h> #include "Adafruit_GFX.h" #include "Adafruit_ILI9341.h" #include <XPT2046_Touchscreen.h> #include <Fonts/FreeSans9pt7b.h> //used font5 #include "TouchEvent.h" //used pins #define TFT_CS 5 //diplay chip select #define TFT_DC 4 //display d/c #define TFT_MOSI 23 //diplay MOSI #define TFT_CLK 18 //display clock #define TFT_RST 22 //display reset #define TFT_MISO 19 //display MISO #define TFT_LED 15 //display background LED #define TOUCH_CS 14 //touch screen chip select #define TOUCH_IRQ 2 //touch screen interrupt //prepare driver for display and touch screen Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); XPT2046_Touchscreen touch(TOUCH_CS, TOUCH_IRQ); //init TouchEvent with pointer to the touch screen driver TouchEvent tevent(touch); // some global variables int scr = 0; uint16_t bg[4] = {ILI9341_WHITE,ILI9341_RED,ILI9341_GREEN,ILI9341_YELLOW}; TS_Point last; boolean draw; //swipe event void onSwipe(uint8_t dir) { switch(dir) { case 0: if (scr <3) { //right to left switch to next screen scr++; draw_screen(scr); } break; case 1: if (scr > 0) { //left to right switch to previous screen scr--; draw_screen(scr); } break; } tevent.setDrawMode(scr==0); } void onClick(TS_Point p) { if (scr > 0) { //on any screen except 0 show the click position tft.setFont(&FreeSans9pt7b); tft.fillRect(0,40,240,70,ILI9341_WHITE); tft.setTextColor(ILI9341_BLACK,ILI9341_WHITE); tft.setCursor(10,60); tft.println("Clicked"); tft.println(p.x); tft.println(p.y); } } void onDblClick(TS_Point p) { if (scr > 0) { //on any screen except 0 show double click position tft.fillRect(0,40,240,70,ILI9341_WHITE); tft.setFont(&FreeSans9pt7b); tft.setTextColor(ILI9341_BLACK,ILI9341_WHITE); tft.setCursor(10,60); tft.println("Doubleclick"); tft.println(p.x); tft.println(p.y); } else { tevent.setDrawMode(false); } } void onDraw(TS_Point p) { //draw a line from the last position to the current position if (draw) tft.drawLine(last.x,last.y,p.x,p.y,ILI9341_BLACK); last = p; } void onTouch(TS_Point p) { last = p; draw = true; } void onUntouch(TS_Point p) { draw = false; } void onLongClick(TS_Point p) { if (scr > 0) { //on any screen except 0 show double click position tft.setFont(&FreeSans9pt7b); tft.fillRect(0,40,240,70,ILI9341_WHITE); tft.setTextColor(ILI9341_BLACK,ILI9341_WHITE); tft.setCursor(10,60); tft.println("Long Click"); tft.println(p.x); tft.println(p.y); } } void setup() { Serial.begin(115200); pinMode(TFT_LED, OUTPUT); digitalWrite(TFT_LED, HIGH); // switch display on //start drivers tft.begin(); touch.begin(); //show the displays resolution Serial.print("tftx ="); Serial.print(tft.width()); Serial.print(" tfty ="); Serial.println(tft.height()); //init TouchEvent instance tevent.setResolution(tft.width(),tft.height()); tevent.setDblClick(300); tevent.registerOnTouchSwipe(onSwipe); tevent.registerOnTouchClick(onClick); tevent.registerOnTouchDblClick(onDblClick); tevent.registerOnTouchLong(onLongClick); tevent.registerOnTouchDraw(onDraw); tevent.registerOnTouchDown(onTouch); tevent.registerOnTouchUp(onUntouch); //display draw_screen(scr); } //fill screen with different colors for different screen numbers void draw_screen(uint8_t nr) { tft.fillScreen(bg[nr]); tft.setFont(&FreeSans9pt7b); tft.setTextColor(ILI9341_BLACK,ILI9341_WHITE); tft.setCursor(10,20); tft.print("Screen Nr. "); tft.print(nr); } void loop() { //poll for touch events tevent.pollTouchScreen(); }
Die TouchEvent Klasse holt in ihrer Hauptfunktion pollTouchScreen() die aktuellen Werte vom Touch-Screen und versucht Ereignisse zu erkennen. Wurde ein Ereignis erkannt und eine Callback-Funktion für dieses Ereignis registriert, so wird diese Funktion mit der aktuellen Position in Bildschirm-Koordinaten aufgerufen. Eine Ausnahme ist die Callback-Funktion für das Swipe-Ereignis, in diesem Fall wird die Richtung der Wischbewegung als Parameter übergeben.
Für folgende Ereignisse kann eine Callback-Funktion registriert werden.
- onTouchDown(TS_Point p) diese Funktion wird immer dann aufgerufen, wenn der Schirm berührt wird.
- onTouchUp(void (TS_Point p) diese Funktion wird immer dann aufgerufen wenn die Schirmberührung endet.
- onTouchClick(void (TS_Point p) diese Funktion wird dann aufgerufen, wenn der Schirm kurz berührt wurde. Die Berührung darf nicht länger sein als die Zeit, die für den langen Klick eingestellt wurde. (Default 1 Sekunde)
- onTouchDblClick(TS_Point p) diese Funktion wird aufgerufen wenn der Schirm innerhals beiner einstellbaren Zeit (Default 500 ms) zweimal kurz berührt wurde. Jedes Doppelklick Ereignis löst beim ersten Klick auch ein Klick-Ereignis aus.
- onTouchLong(TS_Point p) diese Funktion wird dann aufgerufen wenn der Schirm mindestens eine einstellbare Zeit (Default 1 s) berührt wurde. In diesem Fall wird kein Klick-Ereignis ausgelöst.
- onTouchDraw(TS_Point p) diese Funktion wird aufgerufen wenn der Berührungspunkt während der Berührung verändert wird. Über den einstellbaren Wert moveThreshold (Default = 10) kann die Empfindlichkeit variiert werden. Das Ereignis wird nur aufgerufen wenn der Draw-Mode aktiv ist.
-
onTouchSwipe(uint8_t direction) diese Funktion wird aufgerufen, wenn über den Bildschirm gewischt wird. Die mindest Wischlänge kann für x (default = 500) und y (default = 700) eingestellt werden. Der Funktion wird als parameter die Richtung migegeben. 0 = von rechts nach links, 1=vonlinks nach rechts, 2 = von oben nach unten und 3=von unten nach oben. Dieses Ereignis wird nicht ausgelöst, wenn der Draw-Mode nicht aktiv ist.
Als Zusammenfassung hier noch einmal alle Funktionen der Klasse:
-
pollTouchScreen();
die aktuelle Position des Touch-Screen wird abgefragt und je nach erkannten Ereignissen werden registrierte Callback-Funktionen aufgerufen -
void setResolution(int16_t xResolution, int16_t yResolution);
die Auflösung des Bildschirms in Pixel kann eingestellt werden (default 240 und 320) -
void setDrawMode(boolean drawMode);
schaltet den Zeichen-Modus ein oder aus (default = aus). -
void calibrate(uint16_t xMin, uint16_t yMin, uint16_t xMax, uint16_t yMax);
dient zur Kalibrierung des Touch-Screens. Die Werte geben die linke obere und die rechte untere Ecke in Touch-Screen Koordinaten an (default = 230, 350, 3700 und 3900). -
void setMoveTreshold(uint16_t threshold);
setzt die Änderung in Touch-Screen Koordinaten die auftreten muß, damit ein onDraw Ereignis erkannt wird (default = 10). -
void setSwipe(uint16_t swipeX, uint16_t swipeY);
setzt die Länge für den Wischvorgang in Touch-Screen Koordinaten damit ein Wisch-Ereignis erkannt wird (defaul = 500,700). -
void setLongClick(uint16_t clickLong);
setzt die Zeit in ms wie lange eine Berührung dauern muss damit ein langer Klick erkannt wird (default = 1000ms). -
void setDblClick(uint16_t dblclick);
setzt die maximale Zeit zwischen 2 Klicks in ms damit ein Doppelklick erkannt wird (default = 500ms). -
void registerOnTouchDown(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchDown Ereignis. -
void registerOnTouchUp(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchUp Ereignis. -
void registerOnTouchClick(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchClick Ereignis. -
void registerOnTouchDblClick(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchDblClick Ereignis. -
void registerOnTouchLong(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchLong Ereignis. -
void registerOnTouchDraw(void (*callback)(TS_Point p));
registriert eine Callback-Funktion für das onTouchDraw Ereignis. -
void registerOnTouchSwipe(void (*callback)(uint8_t direction));
registriert eine Callback-Funktion für das onSwipeDown Ereignis. -
boolean isInArea(TS_Point p, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
Hilfsfuntion gibt whar zurück wenn der Punkte p innerhalb des Rechtecks x1, y1 und x2, y2 liegt.
Nachdem das Demo-Programm gestartet wurde wird die erste Seite "Screen Nr. 0" mit weißem Hintergrund angezeigt. Auf dieser Seite ist der Zeichen-Modus aktiv und man kann mit dem Finger oder besser mit einem weichen stumpfen Bleistift zeichnen.
Mit einem Doppelklick wird der Zeichen-Modus beendet. Nun kann man durch Wischen zwischen den Seiten hin und her schalten. Seite 1 mit rotem Hintergrund, Seite 2 gelb und Seite 3 grün. Auf allen Seiten außer Seite 0 werden Klick, Doppelklickk und langer Klick mit Position angezeigt. Beim Wechsel auf Seite 0 wird automatisch wieder der Zeichen-Modus aktiviert.
Viel Spass beim Klicken und Wischen ;)
3 comments
OlliBaba
Der Touch funktioniert nur mit 2 Änderungen:
Für das 2,4" mod Touch Display muss es heißen:
#define TOUCH_IRQ 27 //touch screen interrupt 27 anstatt 2 bei altem Display
und die Änderung von Manfred muss auch drin stehen:
digitalWrite(TFT_LED, LOW); // Display-Beleuchtung einschalten —>LOW nicht HIGH
André
Ja,
digitalWrite(TFT_LED, LOW); // Display-Beleuchtung einschalten
ist richtig
Die Lösung für die Touch fuktion ist:
Jumper von GPIO2 entfernen!
Für den TouchScreen Interrupt wird der GPIO2 Pin verwendet, der zum Flashen des ESP32 auf Low sein muss. Da der Interrupt Ausgang des Touchscreen Controller einen Pull Up Widerstand hat ist dieser Pin nicht auf Low, sodass das Hochladen des Programms nicht funktioniert.
Manfred
Der Touch funktioniert nicht !
Diese Zeile ist falsch ,
digitalWrite(TFT_LED, HIGH); // Display-Beleuchtung einschalten
digitalWrite(TFT_LED, LOW); // Display-Beleuchtung einschalten
das ist richtig!
was ist noch falsch ?