ArduiTouch 3 - Zeichnen am Touch Screen - AZ-Delivery


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 ;)

 

DisplaysEsp-32Projekte für fortgeschrittene

3 Kommentare

OlliBaba

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é

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

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 ?

Kommentar hinterlassen

Alle Kommentare werden von einem Moderator vor der Veröffentlichung überprüft

Empfohlene Blogbeiträge

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery