Touch-Buttons definieren und einer Funktion zuordnen

Hallo, ich bin absoluter Anfänger, habe aber voriges Jahr ein Arduino-Baukasten geschenkt bekommen. Nach ersten Versuchen bin ich nun hier. Mein Ziel ist es, die bisherige Steuerung eines Reifeschrankes durch einen Arduino mit Touch-TFT zu ersetzen. Ein paar Zeilen habe ich schon geschrieben, Temperatur und Feuchte kann ich messen. Nun würde ich gern die Sollwerte mit Buttons verändern wollen. Genau das aber, bekomme ich nicht hin. Habe mehrere Stunden gefummelt und probiert. Ich raffe es einfach nicht. Vielleicht kann mir hier jemand behilflich sein. Der TFT ist einer von LCDWIKI, scheinbar funktionieren auch nur diese Bibliotheken. Hier der Code.

#include <TouchScreen.h> //touch library
#include <LCDWIKI_GUI.h> //Core graphics library
#include <LCDWIKI_KBV.h> //Hardware-specific library
#include <DHT.h>


LCDWIKI_KBV my_lcd(NV3029C, A3, A2, A1, A0, A4);

#define DHTPIN 10
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);


#define BLACK        0x0000  /*   0,   0,   0 */
#define BLUE         0x001F  /*   0,   0, 255 */
#define RED          0xF800  /* 255,   0,   0 */
#define GREEN        0x07E0  /*   0, 255,   0 */
#define CYAN         0x07FF  /*   0, 255, 255 */
#define MAGENTA      0xF81F  /* 255,   0, 255 */
#define YELLOW       0xFFE0  /* 255, 255,   0 */
#define WHITE        0xFFFF  /* 255, 255, 255 */
#define NAVY         0x000F  /*   0,   0, 128 */
#define DARKGREEN    0x03E0  /*   0, 128,   0 */
#define DARKCYAN     0x03EF  /*   0, 128, 128 */
#define MAROON       0x7800  /* 128,   0,   0 */
#define PURPLE       0x780F  /* 128,   0, 128 */
#define OLIVE        0x7BE0  /* 128, 128,   0 */
#define LIGHTGREY    0xC618  /* 192, 192, 192 */
#define DARKGREY     0x7BEF  /* 128, 128, 128 */
#define ORANGE       0xFD20  /* 255, 165,   0 */
#define GREENYELLOW  0xAFE5  /* 173, 255,  47 */
#define PINK         0xF81F  /* 255,   0, 255 */



#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin

//param calibration from kbv
//touch sensitivity for X
#define TS_MINX 908
#define TS_MAXX 120

//touch sensitivity for Y
#define TS_MINY 147 
#define TS_MAXY 945

// We have a status line for like, is FONA working
#define STATUS_X 10
#define STATUS_Y 65

//touch sensitivity for press
#define MINPRESSURE 10
#define MAXPRESSURE 1000

#define RELAY_TEMPERATURE_PIN 11
#define RELAY_HUMIDITY_PIN 12

#define Temperature
#define Humidity

#define Heater 
#define Fogger 

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

                           
void setup(void) 
{
  Serial.begin(9600);
  
   dht.begin();
   delay(2000);
    my_lcd.Init_LCD();
   Serial.println(my_lcd.Read_ID(), HEX);
   //my_lcd.Set_Text_Back_colour(BLACK);
   my_lcd.Set_Rotation(3);
   my_lcd.Set_Text_Size(2);
  my_lcd.Set_Text_colour(WHITE);
  my_lcd.Fill_Screen(BLACK);
 

  pinMode(RELAY_TEMPERATURE_PIN, OUTPUT);
  pinMode(RELAY_HUMIDITY_PIN, OUTPUT);

}

void drawButtons()
{
  my_lcd.Set_Text_colour(WHITE);
  my_lcd.Fill_Rect(5, 160, 60, 40, YELLOW); // Plus-Temp Button
  my_lcd.Fill_Rect(70, 160, 60, 40, YELLOW); // Minus-Temp Button
  my_lcd.Fill_Rect(140, 160, 60, 40, YELLOW); // Plus-Humid Button
  my_lcd.Fill_Rect(205, 160, 60, 40, YELLOW); // Minus-Humid Button

  my_lcd.Set_Text_colour(BLACK);
  my_lcd.Set_Text_Size(2);
  my_lcd.Print_String("+", 30, 175); // Plus-Temp Text
  my_lcd.Print_String("-", 95, 175); // Minus-Temp Text
  my_lcd.Print_String("+", 165, 175); // Plus-Humid Text
  my_lcd.Print_String("-", 230, 175); // Minus-Humid Text
  
}

float tempSetpoint = 16;
int humidSetpoint = 90;







void loop(void)
{
  uint16_t i;
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  TSPoint touch = ts.getPoint();





  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {
    //p.x = my_lcd.Get_Display_Width()-map(p.x, TS_MINX, TS_MAXX, my_lcd.Get_Display_Width(), 0);
    //p.y = my_lcd.Get_Display_Height()-map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(), 0);
    p.x = map(p.x, TS_MINX, TS_MAXX, 0, my_lcd.Get_Display_Width());
    p.y = map(p.y, TS_MINY, TS_MAXY, my_lcd.Get_Display_Height(),0);}
     
    



  

  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Print_String("Kaese-Reifeschrank", 60, 5);
  my_lcd.Set_Text_colour(WHITE);

  my_lcd.Print_String(String(Temperature) + "Ist Temp", 10, 30);
  my_lcd.Print_String(String(t, 1) + "0 C", 140, 30);
  my_lcd.Print_String(String(Humidity) + "Ist RH", 10, 50);
  my_lcd.Print_String(String(h, 1) + "0 %", 140, 50);
  my_lcd.Print_String("Soll Temp ", 10, 70);
  my_lcd.Print_String(String(tempSetpoint) + " C", 140, 70);
  my_lcd.Print_String("Soll RH ", 10, 90);
  my_lcd.Print_String(String(humidSetpoint) + ".00 %", 140, 90);
 
 
 
  if (temperature < tempSetpoint)
  {
    my_lcd.Print_String(String (Heater) + "Heizung    AN" ,10, 110);
    digitalWrite(RELAY_TEMPERATURE_PIN, HIGH);
  } else 
  {
    my_lcd.Print_String(String (Heater) + "Heizung    AUS" ,10, 110);
    digitalWrite(RELAY_TEMPERATURE_PIN, LOW);
  }

  // Überprüfe die Luftfeuchtigkeitsschwelle
  if (humidity < humidSetpoint) {
    my_lcd.Print_String(String (Fogger) + "Dunst      AN" ,10, 130);
    digitalWrite(RELAY_HUMIDITY_PIN, HIGH);
  } else {
    my_lcd.Print_String(String (Fogger) + "Dunst      AUS" ,10, 130);
    digitalWrite(RELAY_HUMIDITY_PIN, LOW);
  }
 drawButtons();
}

Setze Deinen Code bitte in Codetags. Wie das geht, steht hier.

Gruß Tommy

Danke, habe es geändert und hoffe es richtig gemacht zu haben.

Touch-Teile funktionieren fast alle gleich.

Über die Anschlüsse X1 + X2 // Y1 + y2. bekommst du 2 Koordinaten. Diese 2 Koordinaten geben 2 Punkt an. Von einen Rechteck. Und zwar immer OBEN-Rechts und UNTEN Links.

Du musst nun über eine Formel (einige if-Then-Abfragen) heraus finden, ob der Touch (bei billigen Displays eher) innerhalb dieses Feld ist.

Dazu einige Tipps um das Leben zu erleichtern.
Nehme ein Blatt Papier. Mal darauf die Rechtecke auf und schreibe die Positionen dran. Dann gebe sie der Reihe Nach in die IF-THEN Abfrage ein.

Sehr oft kommt es vor, das man ein BILD in das Display läde und dann nur noch besagte Koordinaten abfragen muss.

Ich habe sogar ein Touch was man auf ein Objekt legen kann und dann die Werte abfragen kann.

Hier mal ein Link dazu.
https://www.digikey.de/en/maker/tutorials/2022/how-to-use-a-touchscreen-with-an-arduino

In der Mitte über den Bild mit den Gelben Display ist der Code den du brauchst.

Gruß

Pucki

Hallo,
ich habe mit Deinen Sketch mal kurz angesehen

hat eigentlich im loop nichts zu suchen

Ich denke Du fängst mal eine Nummer kleiner an und machst erst mal nichts anderes als die Buttons auf´s Display bekommen und dann abfragen ob einer gedrückt wird und welcher.

die Buttons bekommst Du ja anscheinend zu sehen, Wenn Du nun da drauf drückst musst Du abfragen ob der Touch innerhalb welches Buttons war. Damit kannst Du dann entscheiden was Du machst und z.B Deine Variable verändern. Damit das nicht rasend schnell geht würde ich das innerhalb einer millis() Abfrage z.B alle 100 ms machen.

bei mir sieht das so aus. ich habe 4 Buttons ganz unten. Es gibt eine Function readbtn() die liefert die Nummer des gedrückten Buttons 1-4 zurück.


// im loop das hier alle 100 ms bearbeiten 
 if (ts.touched()) {
    key = readbtn();
   
  }

 //------------ Seite auswälen

  switch (key) {
    case 1:
      page1();
      break;
    case 2:
      page2();
      break;
    case 3:
      page3();
      break;
    case 4:
      page4();
      break;
  }
}

ich mache damit jetzt nur eine Seitenumschaltung aber bei case 3 konnte ja auch stehen Sollwert++ und bei case 4 Sollwert--

und dann

byte readbtn() {
  static byte key ;
  TS_Point p = ts.getPoint();
  int x = map(p.x, TS_MINX, TS_MAXX, 0, 320); // x position 
  int y = map(p.y, TS_MINY, TS_MAXY, 0, 240); // y position

  Serial.print ("x "); Serial.println(x);
  Serial.print ("y "); Serial.println(y);

  if (y > 210 && y < 240) { // Bereich ganz unten 
    if (x > 0 && x < BUTON_WIDTH) key = 1;
    else if (x > 80 && x < 80 + BUTON_WIDTH) key = 2;
    else if (x > 160 && x < 160 + BUTON_WIDTH) key = 3;
    else if (x > 240 && x < 240 + BUTON_WIDTH) key = 4;
  }
  Serial.println(key);
  return (key);

Vielen Dank für eure Antworten. Leider hilft mir das nicht weiter. Irgendwie gibt es diese Funktionen nicht in den Bibliotheken, ich bekomme nur Fehlermeldungen.

Du brauchst für den Touch keine Funktion.

Ein Touch-Screen ist eine MATRIX.

Du musst nur den Analog-Wert von den 4 Pins die als Touch bezeichnet sind abfragen.

Fertig ist.

Siehe dir mal mein Beispiel an.

Wenn du mir sagst wie dein Teil heißt (oder selbst in Datenblatt schaust) siehst du wo die 4 Pins sind die du brauchst.

Wenn du es mit einer Libs machen willst.

Hier mal ein andere Link der dir das auf DEUTSCH erklärt.

Gruß

Pucki

Displays mit NV3029C sind meistens ohne Rückplatine mit Pins, nur Flachband, was für Display genau ist das Link reicht

Also das Display stecke ich direkt auf den Arduino. Die Testprogramme des Herstellers laufen. Mein kleiner Sketch auch. Vielleicht habe ich mich mit "Funktion" auch falsch ausgedrückt. Aber zum Beispiel das : if (ts.touched()) { key = readbtn(); , wie oben beschrieben, bringt schon eine Fehlermeldung. Schreibe ich z.B. if (ts.isTouching, habe ich keine Fehlermeldung. Wie gesagt bin ich absoluter Anfänger auf diesem Gebiet. Mein Ziel wäre es, da ich ja schon die vier Buttons habe, dass ich auf eines dieser drücke und ich eine Rückmeldung bekomme. Hier der Link zum Modul: http://www.lcdwiki.com/res/MAR2601/2.6inch_Arduino_UNO_Module_MAR2601_User_Manual_EN.pdf

OK. Gute Seite ;)

Mach folgendes :

Gehe auf 2.6inch Arduino Display - LCD wiki

Dort gibt es ein Download

Program Download

Downloaden / Auspacken

Dann auf 1-Demo -> Arduino -> Example -> Example_11_touch_pen

DAS Programm/Script sollte dir den Touch-screen erklären.

Wichtig:)

Das ist ein HAU-Screen. Nicht zu verwechseln mit den eleganten Touch-Teilen die in normale Handys eingebaut sind.
Hau-Screen deshalb weil die nur AUF DRUCK Reagieren. Falls du kein Stift hast : nehme ein Zahnstocher, haue ihn einige Male feste auf den Tisch(damit die Spitze stumpf wird). Dann kannst du die Stumpfe Spitze als TOUCH-PEN benutzen.

Wenn du Geld ausgeben willst. Gute Stifte sind die von Nintendo für die DS-Serie.

Ach ja. Vergiss was ich über die 4-Pins oben geschrieben habe. Dieses Display funktioniert anders. Das braucht expliziert ein Treiber.

In den Beispiel s.o. sind die passenden Treiber include

Gruß

Pucki

Danke pucki007, ich habe das alles schon durch. Bibliotheken installiert, Demos ablaufen lassen, alles kein Problem. Nur habe ich keine Ahnung, wie ich die Koordinaten abfrage um sie dann auszuwerten. Ein weiteres Beispiel, nebensächlich natürlich: Ich will einen Umlaut für "ä" schreiben.
Ich könnte die ganze Nacht damit verbringen, die richtige Bezeichnung zu finden, frage mich aber, wo sind die Definitionen? Ich habe bestimmt schon 20 Versuche gemacht, Sonderzeichen erhalten, welche ich noch nie gesehen habe, ein "ä" war aber nicht dabei, bin mir aber sicher, dass es das gibt.

Das blöde ist das bei LCD Wicki in der Schriftart keine Sonderzeichen eingebaut sind, und unterstützt nicht andere Schriften, habe vor ein paar J auch das Problem gehabt.
es gibt noch eine Lib für ILI9341 vom David Prentice ob die das kann weis nicht.

Habe nach geschaut, deren Font hat auch keine Sonderzeichen, das die aber Adafruit GFX nutzt könnte sein das man andere Fonts einbinden kann

Danke. das ist aber wie schon gesagt nebensächlich. Mir geht es nur darum, meinen Buttons eine Definition zuzuweisen und ich weiß nicht wie es geht, mit diesen Libraries. Aufgeben ist nicht mein Ziel, also werde ich weiter probieren, auch wenn ich nicht wirklich weiß, was ich da mache.

Ganz einfach, du lässt dir anzeigen mit SerialMonitor was Für Koordinaten diene Buttons haben, danach wertest du die aus. wie sind die Buttons aufgebaut Kreis, Rechteck ?

Führe mal das Beispiel unter

1_demo -> Demo_Arduino -> Install libraries -> TouchScreen -> examples ->touchscreendemoshield aus.

Das ist nicht so verspielt.

Hier der ganze Code.

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

Das Ergebnis sollte eine Koordinate sein. 
Lege nun die x-y Werte für O + U (sieh Zeichnung fest) und aufschreiben. 

o---------------- 
|                    |
|     button   |
|                    |
|--------------- u
 
Du braucht die Koordinate  von O  und u (Siehe Zeichnung für arme).

Wenn du beide hast, musst du nur noch im Script vergleichen ob ein TOUCH innerhalb dieser 2 xy Werte liegen.  

Wenn das der Fall ist, hast du den Button getroffen und kannst darauf reagieren.

Z ist der Wert der den Druck deines Stiftes wieder gibt. In wie weit das Sinnvoll ist, weiß ich allerdings nicht ;)

Ich bin aber nicht 100 % überzeugt das das läuft. 

Gruß

    Pucki

Danke dir, das probiere ich morgen. Schön, dass es solch gute Menschen wie dich und euch gibt.

Mit diesen beiden Zeilen aus deinem Sketch oben solltest du doch die x und y Position auslesen können

Setze doch mal zwei serielle Ausgaben dahinter, so wie das in meinem Beispiel ja auch gemacht ist , damit du etwas sehen kannst.

Die Funktion readbtn() habe doch selbst geschrieben , sie soll doch nur zeigen wie man das auswerten kann. Natürlich musst du eventuell anpassen wie der Aufruf (Methode) in deiner verwendeten lib geht. Das kannst ja aber sicher einem Beispiel entnehmen das mit deiner lib ausgeliefert wird.

Er muss erst mall die Koordinaten im Serial anzeigen lassen, p.x und p.y entsprechen nicht den werten x, y auf dem Display wenn Er das hat dann ist der Rest kein Problem.
Bei SPI Displays ist das kein Problem man Kalibriert den Touch, danach x.p ist gleich X

Hallo

@pucki007
p.x und p.y werden die Rohdaten sein , die werden wenig mit den Koordinaten des Monitors zu tun haben. Man sollte das erst noch map() en

Gruß Heinz

Muss man aber nicht :wink:
Ich habe zwei 3,95 8Bit TFT für Mega und beide zeigen was anderes