2. Bildschirm Touch geht nicht

Hallo Leute, ich bin ganz neu hier, und brauche dringend eure Hilfe.
Es geht darum, ich habe einen Arduino Mega auf einem Elegoo Board. Außerdem habe ich zwei 4“ TFT Displays mit Touchfunktion: (amazon link zum Display) https://amzn.eu/d/00GzBOz8

Ich möchte gerne, dass die Displays zwar das selbe anzeigen, aber auch über beide Touchscreens bedienbar sind. Also, wenn zum Beispiel am ersten Display etwas gedrückt wird, dass es dann auf beiden Displays aktualisiert wird.

Beziehungsweise im weiteren dann auch die Displays zwei verschiedene Sachen anzeigen aber soweit bin ich noch nicht.

Hier mein Code, das Problem ist, dass zwar beide Displays richtig anzeigen, aber nur ein Touch geht und ich komm einfach nicht auf den Fehler. Ich habe auch ein paar serielle Ausgaben hinzugefügt, damit ich sehe, ob der zweite Touchscreen überhaupt erkannt wird, aber das tut er nicht, Nur der erste.

Danke beste Grüße

#include <Adafruit_GFX.h>
#include <Adafruit_ST7796S_kbv.h>
#include <XPT2046_Touchscreen.h>
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans18pt7b.h>
#include <Fonts/FreeSans24pt7b.h>
#include <Arduino.h>

// Pins für das erste Display (Hardware-SPI)
#define TFT_CS1 10
#define TFT_RST1 8
#define TFT_DC1 9

// Pins für das zweite Display (Hardware-SPI)
#define TFT_CS2 11
#define TFT_RST2 7
#define TFT_DC2 6

// Pins für den ersten Touchscreen (Hardware-SPI)
#define TOUCH_CS1 4
#define TOUCH_IRQ1 2

// Pins für den zweiten Touchscreen (Hardware-SPI)
#define TOUCH_CS2 5
#define TOUCH_IRQ2 3

Adafruit_ST7796S_kbv tft1 = Adafruit_ST7796S_kbv(TFT_CS1, TFT_DC1, TFT_RST1);
XPT2046_Touchscreen ts1(TOUCH_CS1, TOUCH_IRQ1);

Adafruit_ST7796S_kbv tft2 = Adafruit_ST7796S_kbv(TFT_CS2, TFT_DC2, TFT_RST2);
XPT2046_Touchscreen ts2(TOUCH_CS2, TOUCH_IRQ2);

int rectWidth = 200;
int rectHeight = 100;
int rectX;
int rectY;
bool initialScreen = true;
bool gameScreen = false;
unsigned long gameStartTime;
int gameTime = 30;  // Zeit für das Spiel in Sekunden
int hits = 0;

void drawInitialButton() {
  tft1.fillScreen(ST7796S_BLACK);  // Bildschirm löschen
  tft1.fillRect(rectX, rectY, rectWidth, rectHeight, ST7796S_RED);
  tft1.setFont(&FreeSans18pt7b);
  int16_t x1, y1;
  uint16_t w, h;
  tft1.getTextBounds("Test starten", 0, 0, &x1, &y1, &w, &h);
  int16_t textX = rectX + (rectWidth - w) / 2;
  int16_t textY = rectY + (rectHeight + h) / 2;
  tft1.setCursor(textX, textY);
  tft1.setTextColor(ST7796S_BLUE);
  tft1.print("Test starten");

  tft2.fillScreen(ST7796S_BLACK);  // Bildschirm löschen
  tft2.fillRect(rectX, rectY, rectWidth, rectHeight, ST7796S_RED);
  tft2.setFont(&FreeSans18pt7b);
  tft2.setCursor(textX, textY);
  tft2.setTextColor(ST7796S_BLUE);
  tft2.print("Test starten");
}

void drawOverlay() {
  tft1.fillScreen(ST7796S_BLACK);
  tft2.fillScreen(ST7796S_BLACK);

  // Einzelspieler-Button
  int singlePlayerButtonX = 50;
  int singlePlayerButtonY = 100;
  tft1.fillRect(singlePlayerButtonX, singlePlayerButtonY, 150, 50, ST7796S_RED);
  tft1.setCursor(singlePlayerButtonX + 10, singlePlayerButtonY + 30);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.setFont(&FreeSans9pt7b);
  tft1.print("Einzelspieler");

  tft2.fillRect(singlePlayerButtonX, singlePlayerButtonY, 150, 50, ST7796S_RED);
  tft2.setCursor(singlePlayerButtonX + 10, singlePlayerButtonY + 30);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.setFont(&FreeSans9pt7b);
  tft2.print("Einzelspieler");

  // Mehrspieler-Button
  int multiPlayerButtonX = tft1.width() - 200;
  int multiPlayerButtonY = 100;
  tft1.fillRect(multiPlayerButtonX, multiPlayerButtonY, 150, 50, ST7796S_GREEN);
  tft1.setCursor(multiPlayerButtonX + 10, multiPlayerButtonY + 30);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.print("Mehrspieler");

  tft2.fillRect(multiPlayerButtonX, multiPlayerButtonY, 150, 50, ST7796S_GREEN);
  tft2.setCursor(multiPlayerButtonX + 10, multiPlayerButtonY + 30);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.print("Mehrspieler");

  // Beenden-Button
  int endButtonX = (tft1.width() - 100) / 2;
  int endButtonY = tft1.height() - 60;
  tft1.fillRect(endButtonX, endButtonY, 100, 50, ST7796S_BLUE);
  tft1.setCursor(endButtonX + 20, endButtonY + 30);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.print("Beenden");

  tft2.fillRect(endButtonX, endButtonY, 100, 50, ST7796S_BLUE);
  tft2.setCursor(endButtonX + 20, endButtonY + 30);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.print("Beenden");
}

void drawGameScreen(int timeLeft, int hits) {
  // Timer oben
  tft1.setFont(&FreeSans9pt7b);
  tft1.fillRect(20, 20, 100, 30, ST7796S_BLACK);  // Lösche alten Timer
  tft1.setCursor(20, 30);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.print("Timer: ");
  tft1.print(timeLeft);

  tft2.setFont(&FreeSans9pt7b);
  tft2.fillRect(20, 20, 100, 30, ST7796S_BLACK);  // Lösche alten Timer
  tft2.setCursor(20, 30);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.print("Timer: ");
  tft2.print(timeLeft);

  // Treffer in der Mitte
  tft1.fillRect((tft1.width() - 150) / 2, (tft1.height() / 2) - 20, 150, 40, ST7796S_BLACK);  // Lösche alten Treffertext
  tft1.setCursor((tft1.width() - 150) / 2, tft1.height() / 2);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.setFont(&FreeSans24pt7b);
  tft1.print("Treffer: ");
  tft1.print(hits);

  tft2.fillRect((tft2.width() - 150) / 2, (tft2.height() / 2) - 20, 150, 40, ST7796S_BLACK);  // Lösche alten Treffertext
  tft2.setCursor((tft2.width() - 150) / 2, tft2.height() / 2);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.setFont(&FreeSans24pt7b);
  tft2.print("Treffer: ");
  tft2.print(hits);
}

void drawStopButton() {
  // Stop-Button unten
  int stopButtonX = (tft1.width() - 100) / 2;
  int stopButtonY = tft1.height() - 60;
  tft1.fillRect(stopButtonX, stopButtonY, 100, 50, ST7796S_RED);
  tft1.setCursor(stopButtonX + 20, stopButtonY + 30);
  tft1.setTextColor(ST7796S_WHITE);
  tft1.setFont(&FreeSans9pt7b);
  tft1.print("Stop");

  tft2.fillRect(stopButtonX, stopButtonY, 100, 50, ST7796S_RED);
  tft2.setCursor(stopButtonX + 20, stopButtonY + 30);
  tft2.setTextColor(ST7796S_WHITE);
  tft2.setFont(&FreeSans9pt7b);
  tft2.print("Stop");
}

void startCountdown(int seconds) {
  for (int i = seconds; i > 0; i--) {
    tft1.fillScreen(ST7796S_BLACK);
    tft1.setFont(&FreeSans24pt7b);
    tft1.setCursor((tft1.width() - 50) / 2, (tft1.height() - 50) / 2);
    switch (i) {
      case 3:
        tft1.setTextColor(ST7796S_RED);
        break;
      case 2:
       tft1.setTextColor(ST7796S_YELLOW);
break;
case 1:
tft1.setTextColor(ST7796S_GREEN);
break;
}
tft1.print(i);
tft2.fillScreen(ST7796S_BLACK);
tft2.setFont(&FreeSans24pt7b);
tft2.setCursor((tft2.width() - 50) / 2, (tft2.height() - 50) / 2);
switch (i) {
  case 3:
    tft2.setTextColor(ST7796S_RED);
    break;
  case 2:
    tft2.setTextColor(ST7796S_YELLOW);
    break;
  case 1:
    tft2.setTextColor(ST7796S_GREEN);
    break;
}
tft2.print(i);

delay(1000);
}
// Zeige “Start” an
tft1.fillScreen(ST7796S_BLACK);
tft1.setFont(&FreeSans24pt7b);
tft1.setCursor((tft1.width() - 100) / 2, (tft1.height() - 50) / 2);
tft1.setTextColor(ST7796S_WHITE);
tft1.print("Start");

tft2.fillScreen(ST7796S_BLACK);
tft2.setFont(&FreeSans24pt7b);
tft2.setCursor((tft2.width() - 100) / 2, (tft2.height() - 50) / 2);
tft2.setTextColor(ST7796S_WHITE);
tft2.print("Start");

delay(1000);
// Bildschirm nach Countdown löschen
tft1.fillScreen(ST7796S_BLACK);
tft2.fillScreen(ST7796S_BLACK);
}

void handleTouch(XPT2046_Touchscreen &ts, Adafruit_ST7796S_kbv &tft, const char* displayName) {
if (ts.touched()) {
// Holen Sie sich die Touch-Informationen
TS_Point p = ts.getPoint();
// Anpassung der Bereichswerte basierend auf der Rohwert-Ausgabe
int mapX = map(p.x, 300, 3900, 0, 480);
int mapY = map(p.y, 300, 3900, 0, 320);

// Anpassung der Koordinaten für die doppelte Spiegelung
mapX = 480 - mapX;
mapY = 320 - mapY;

Serial.print(displayName);
Serial.print(" Touch detected! Mapped X = ");
Serial.print(mapX);
Serial.print(" Mapped Y = ");
Serial.println(mapY);

if (initialScreen) {
  // Überprüfen, ob der Touch innerhalb des Rechtecks liegt
  if (mapX >= rectX && mapX <= (rectX + rectWidth) && mapY >= rectY && mapY <= (rectY + rectHeight)) {
    // Zeichne das Overlay
    drawOverlay();

    // Setze initialScreen auf false
    initialScreen = false;
  }
} else if (gameScreen) {
  // Überprüfen, ob der Stop-Button gedrückt wird
  int stopButtonX = (tft.width() - 100) / 2;
  int stopButtonY = tft.height() - 60;

  if (mapX >= stopButtonX && mapX <= (stopButtonX + 100) && mapY >= stopButtonY && mapY <= (stopButtonY + 50)) {
    // Zeichne den initialen Button
    drawInitialButton();

    // Setze initialScreen auf true
    initialScreen = true;
    gameScreen = false;
  }
} else {
  // Überprüfen, ob einer der neuen Buttons gedrückt wird
  int singlePlayerButtonX = 50;
  int singlePlayerButtonY = 100;
  int multiPlayerButtonX = tft.width() - 200;
  int multiPlayerButtonY = 100;
  int endButtonX = (tft.width() - 100) / 2;
  int endButtonY = tft.height() - 60;

  if (mapX >= singlePlayerButtonX && mapX <= (singlePlayerButtonX + 150) && mapY >= singlePlayerButtonY && mapY <= (singlePlayerButtonY + 50)) {
    // 3-Sekunden Countdown starten
    startCountdown(3);

    // Zeichne das Spielinterface
    gameStartTime = millis();
    hits = 0;
    drawGameScreen(gameTime, hits);
    drawStopButton();

    // Setze gameScreen auf true
    gameScreen = true;
  }

  if (mapX >= multiPlayerButtonX && mapX <= (multiPlayerButtonX + 150) && mapY >= multiPlayerButtonY && mapY <= (multiPlayerButtonY + 50)) {
    // Aktion für Mehrspieler-Button
  }

  if (mapX >= endButtonX && mapX <= (endButtonX + 100) && mapY >= endButtonY && mapY <= (endButtonY + 50)) {
    // Zeichne den initialen Button
    drawInitialButton();

    // Setze initialScreen auf true
    initialScreen = true;
  }
}

// Warte, bis der Touchscreen losgelassen wird
while (ts.touched()) {
  delay(10);
}
}
}

void setup() {
Serial.begin(9600);

// Initialisiere das erste Display
tft1.begin();
tft1.setRotation(1);
tft1.fillScreen(ST7796S_BLACK);

// Initialisiere den ersten Touchscreen
if (!ts1.begin()) {
while (1);
}
ts1.setRotation(1);

// Initialisiere das zweite Display
tft2.begin();
tft2.setRotation(1);
tft2.fillScreen(ST7796S_BLACK);

// Initialisiere den zweiten Touchscreen
if (!ts2.begin()) {
while (1);
}
ts2.setRotation(1);

// Position des Buttons initialisieren
rectX = (tft1.width() - rectWidth) / 2;
rectY = (tft1.height() - rectHeight) / 2;

// Zeichne den initialen Button auf beiden Displays
drawInitialButton();
}

void loop() {
handleTouch(ts1, tft1, "Display 1");
handleTouch(ts2, tft2, "Display 2");

if (gameScreen) {
// Überprüfen, ob die Spielzeit abgelaufen ist
int timeLeft = gameTime - (millis() - gameStartTime) / 1000;
static int lastTimeLeft = -1;
if (timeLeft <= 0) {
  // Zeichne den initialen Button auf beiden Displays
  drawInitialButton();

  // Setze initialScreen auf true
  initialScreen = true;
  gameScreen = false;
} else if (timeLeft != lastTimeLeft) {
  // Aktualisiere das Spielinterface nur, wenn sich der Timer ändert
  drawGameScreen(timeLeft, hits);
  lastTimeLeft = timeLeft;
}
}
}

Es sind 3,3V Displays ist auch auf den Fotos zu sehen. Dir werdenit deinem Mega funktionieren wie lange steht in den Sternen.
Kann sein das der Touch IC schon austeigt.

Evtl. solltest du kleiner anfangen und dein Projekt auf eine minimale Funktion reduzieren. Dabei wirst du deinen Fehler sicher leichter finden.
Und der Hinweis von @fony ist unbedingt zu beachten, das geht mit SPI-Levelshiftern, z.B. ein CD4050.

Okay danke. Ja habe zuvor einen Spannungsteiler aufgebaut. Hab aber dann gelesen dass das Display doch mit 5V betrieben werden kann und an den Kommunikations Pins keine 3.3V benötigt werden.
Habe es schon probiert nur einzeln zu betreiben. Da gehen die Touch Funktionen.
Nur dann wenn ich versuche auf ein zweites Display zu erweitern geht irgendwas nicht. Glaube auf Seitens der Software, weil wie gesagt einzeln gehen die Displays.

Danke für die Hilfe soweit mal.

Wo hast du das gelesen ?
Die Treiber sind fast ausschließlich nur mit 3,3V zu nutzen. Die sind nicht 5Volt tolerant. Es sei denn, das Datenblatt sagt da explizit etwas anderes.

Und was sagen denn die seriellen Ausgaben in der Touchroutine ?

Edit:
Im Datenblatt deines Links steht genau das: Datenpins 3,3Volt.

1 Like

So weit habe nicht gescrollt .
Habe erst die Rückseite mir angeschaut, das reicht mir.
Habe noch kein 4" SPI Display gesehen für 5V.

Produktmerkmale:

  1. Unterstützt mehrere Ein-Chip-Mikrocontroller zum direkten Einbau, ohne dass eine Verdrahtung erforderlich ist
  2. Integrierter Spannungsstabilisierungs-IC, unterstützt 5V oder 3,3V Stromversorgung
  3. Onboard-Pegelumwandlungsschema, kompatibel mit 5V/3,3V IO-Pegeln, unterstützt verschiedene Mikrocontroller-IO-Verbindungen
  4. Integrierte SD-Karten-Erweiterungsschaltung,
  5. Reserve SPI FLASH-Wortbibliotheksschaltung zur einfachen Erweiterung von Anwendungen

4" SPI-Touchscreen-Anzeige:
Anzeigefarbe: RGB 65K Farbe
Bildschirmgröße: 4(Zoll)
Typ: TFT
Treiber IC: ST7796S
Auflösung: 480*320 (Pixel)
Modul-Schnittstelle: 4-Draht-SPI-Schnittstelle
Aktive Fläche (AA-Fläche): 83,52 X 55,68(mm)
Modul-PCB-Größe: 108,04 X 61,74(mm)
Betriebstemperatur: -20℃~60℃
Lagertemperatur: -30℃~70℃
VCC Versorgungsspannung: 3.3V~5V
Spannung der logischen IO-Ports: 3,3 V (TTL)
Leistungsaufnahme: TBD

Das ist das Problem. Da macht sich das Amazon und AZ-Müllmann auch einfach.
Entweder die geben keine Daten an oder falsche. Der Kunde wirds schon (kaputt) hin kriegen. Weil alles lesen ist immer ein Problem und manchmal funktioniert es ja auch.

Davon ist auf der Platine nichts zu sehen, es fehlt der nötige Wandlerchip.

Und das ist die wichtige und richtige Aussage.

Und das ist der Witz. Ich vermisse da einen Funkchip, der das drahtlos macht.
Soweit zur Dokumentation von Amazon.

Man sollte halt nur etwas kaufen, wenn man das Datenblatt geliefert bekommt / gefunden hat und es gelesen/verstanden hat.
Sonst produziert man schnell Elektronikschrott.

Gruß Tommy

1 Like

Genau, das kann man hier nicht oft genug schreiben / sagen.

Aber 5 Minuten später kommt der nächste, den es nicht interessiert.
Das heißt dann halt: Lehrgeld
Manche lernen nur durch Schmerzen.

Gruß Tommy

Evtl. sind die Schmerzen ja nicht stark genug.

Das Problem ist das --> "Wire SPI Kompatibel mit Arduino" was auch nicht falsch ist außer der Annahme das es gib noch anderen SPI Bus, damit ist der Händler aus dem Schneider,
nur kommt der Gedanke bei fast allen Anfänger "ist ja für Arduino also kaufe das für meinen Mega, Uno, Nano"
Erst hier im Forum werden denen die Augen aufgemacht, am schlimmsten sind die was meinen recht zu haben "dort steht doch Arduino".
Na ja wie schon Ihr habt geschrieben

Ich würde man versuchen die Libs auszutauschen.

Gerade die Adafruits-Libs setzen sehr gerne nach meiner Erfahrung viel voraus.

Versuch es mal mit der TFT_ESPI Libs.

Die benutze ich auch lieber. Ist auch etwas schneller in der Ausführung und nach meiner Erfahrung weniger Zickig.
Nachteil : Sie ist nur extern configurierbar. (Man muss einen Datei ändern).

Gruß

Pucki

Der TO nutzt ein Mega, TFT_eSPI kann nur bis D48 adressieren deshalb geht damit nicht. Mit Software SPI kann die Bibliothek nicht umgehen.
Komm bitte nicht mit " der TO könnte den ICSP header nutzen", das geht auch nich.

Im welschem Sinne ?
Gerade Adafruit sind die Anfängerfreundliche Bibliotheken, und sind deshalb so langsam den die mit fast jeder Konfiguration auskommen, funktionieren.
Wurdest alles lesen wüstest du das es ist ein 3,3V Display, und wie lange der direkt mit 5V wird funktionieren kann keiner sagen.
Dir sollte doch bekannt sein das manchmal schon bei 0,2V mehr wird der geist aus dem IC freigelassen.

Ist der einfachster Weg einmal genau durchlesen, die Kommentare beachten dann ist das beherrscht. Man muss nicht unbedingt die User_Setup.h nutzen, so gar auch nicht den Eintrag im User_Setups für sein Display anpassen, wenn jemand will ziemlich langen Sketch schreiben.

Genau im den Sinne das sie so einfach ist. Zauberwort : Hard / VOR -Codiert.

Weil grundsätzlich gilt. Ist etwas einfach dann ist es auch sehr eingeschränkt.

Der TO will 2 Displays anklemmen. Und das ist nicht Standart.

Adafruit hatte ich (mit ein Display) auch mal versucht. Die Beispiele haben erst dann funktioniert, als ich ALLE Pins des Displays bei der INI-Funktion übergeben habe.

Was das 5 Volt problem angeht. Was spricht dageben mal ca. 20 Cent auszugeben und sich 2 Level-Shifter zu kaufen und dazwischen zu schalten. Damit ist man IMMER auf der sicheren Seite. Egal ob das Display die 5 Volt ab kann oder nicht.

Gruß

Pucki

Hat er schon :wink:
Was geht nicht mit der TFT_eSPI ohne halb Bibliothek umzuschreiben.
Suche mall nach TFT_eSPI mit 2 Displays, mit Adafruit + eSPI geht
Nur Adafruit geht
LCD Wicki geht.