Mit Touch zurück zum Anfang des Programms.

Moin!

Ich habe folgendes Problem. Ich habe eine grafische Oberfläche mit Touchfunktion erstellt. Über diese Touchoberfläche lassen sich verschiedene digitale Pins ein und wieder aus schalten. Jetzt wollte ich eine Art Info-Fenster erstellen, dass sich über die Touchoberfläche aufrufen lässt. Das funktioniert auch alles soweit, nur komme ich aus dem neuen Fenster nicht mehr zurück zum "Hauptfenster".
Ich habe die Oberfläche des Hauptfenster in die Funktion ui() geschrieben. Aber egal, ob ich mit der if-Anweisung unten die loop(), die setup() oder die ui() aufrufe. Es flackert einmal der Bildschirm und sonst passiert nichts. Ideen?

Grüße

void info() {

  //Erstellen der Oberfäche des Info-Fensters
  tft.fillScreen(BLACK);
  tft.setTextColor(GREEN);
  tft.setTextSize(3);
  tft.setCursor(10, 10);
  tft.print("Version:");
  tft.setCursor(10, 60);
  tft.print("IP-Adresse:");
  tft.setTextColor(BLUE);
  tft.setTextSize(2);
  tft.setCursor(10, 40);
  tft.print("0.1 Beta");
  tft.setCursor(10, 85);
  tft.print("192.168.178.222");

  tft.fillRect(30, 190, 180, 50, BLUE);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  tft.setCursor(80, 205);
  tft.print("zurueck");

  //Touch-Oberfläche
  
  TSPoint p = ts.getPoint();

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {

    // scale from 0->1023 to tft.width
    p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
    p.y = map(p.y, TS_MINY, TS_MAXY, 320, 0);

    if (p.y > 190 && p.y < 240 && p.x > 30 && p.x < 210) {
      loop();
    }
  }
}

Rufe loop() niemals per Hand auf! Die loop() Funktion läuft ständig selbst durch. Wenn du die gleiche Funktion nochmal aufrufst hast du eine Rekursion wodurch sofort der Speicher voll läuft.

Was du willst in eine Art Zustandsmaschine die verwaltet in welchem Menü du dich befindest. Enums sind da z.B. eine Option wenn man richtige Namen will. Aber es geht auch ein Integer 0, 1, 2, etc.

Außerdem muss du das Zeichnen des Menüs und die Abfrage der Buttons trennen. Das Zeichnen darf nur beim Umschalten einmal erfolgen und dann fragt man ständig die Buttons ab. Also wenn man ein Menü wechselt ändert man die Zustands-variable und zeichnet in deren Abhängigkeit das entsprechende Untermenü. Und in loop() fragt man je nach Zustand dann andere Buttons ab.

z.B. so ähnlich:

enum menus { MAIN, INFO };
int currentMenu = MAIN;

void setup()
{
   drawMenu();
}

void loop()
{
   checkButtons();
}

void drawMenu()
{
   switch(currentMenu)
   {
       case MAIN:
         ....
         break;

      .....
   }
}

void checkButtons()
{
    //1.) abfragen ob Knopf gedrückt wurde

    //2.) Wenn zwischen Menüs gewechselt wird currentMenu ändern und drawMenu() aufrufen
}

pauli1910:

void info() {

...

if (p.y > 190 && p.y < 240 && p.x > 30 && p.x < 210) {
     loop();
...

Der Fehler besteht – soweit ich das überblicke – darin, dass Du loop() erneut aufrufst. Schreib' statt dessen

void info() {

...

    if (p.y > 190 && p.y < 240 && p.x > 30 && p.x < 210) {
      return();
...

Es ist aber auch Blödsinn ständig das Menü zu zeichnen. Das muss man nur einmal machen wenn man das Menü wechselt.
Wenn man Elemente hat die sich ändern (z.B. eine Temperaturanzeige) muss man auch nicht immer den ganzen Bildschirm zeichnen. Die statischen Elemente (Text, Buttons, etc.) werden einmal gemacht und nur der Variable Teil je nach dem wie oft man aktualisieren will.

Deshalb wie gesagt Menüaufbau und Button Auswertung in getrennte Funktionen

Danke erstmal für die Antworten.

das loop() war nur ein Platzhalter, bei dem ich bereits wusste, dass es falsch ist. Ich dachte, dies sei klar.

Das getrennte Zeichnen der Oberfläche und das Erstellen des Touchmenüs habe ich im "Hauptmenü" auch so durchgeführt.

return(); geht nicht

Versuche mal return;, also ohne Klammern.

agmue:
Versuche mal return;, also ohne Klammern.

kein Fehler beim Kompilieren, aber das gleiche Ergebnis. Das Bild flackert einmal und ich bin immer noch im Info-Fenster.

pauli1910:
Das getrennte Zeichnen der Oberfläche und das Erstellen des Touchmenüs habe ich im "Hauptmenü" auch so durchgeführt.

Bei info() sieht es aber nicht aus. Wenn man das richtig macht dann braucht man eben keine Sprünge und keine returns. Wenn kein Knopf gedrückt wird, wird halt nichts gemacht und die Funktion beendet sich von selbst.

Serenifly:
Rufe loop() niemals per Hand auf! Die loop() Funktion läuft ständig selbst durch. Wenn du die gleiche Funktion nochmal aufrufst hast du eine Rekursion wodurch sofort der Speicher voll läuft.

Was du willst in eine Art Zustandsmaschine die verwaltet in welchem Menü du dich befindest. Enums sind da z.B. eine Option wenn man richtige Namen will. Aber es geht auch ein Integer 0, 1, 2, etc.

Außerdem muss du das Zeichnen des Menüs und die Abfrage der Buttons trennen. Das Zeichnen darf nur beim Umschalten einmal erfolgen und dann fragt man ständig die Buttons ab. Also wenn man ein Menü wechselt ändert man die Zustands-variable und zeichnet in deren Abhängigkeit das entsprechende Untermenü. Und in loop() fragt man je nach Zustand dann andere Buttons ab.

z.B. so ähnlich:

enum menus { MAIN, INFO };

int currentMenu = MAIN;

void setup()
{
  drawMenu();
}

void loop()
{
  checkButtons();
}

void drawMenu()
{
  switch(currentMenu)
  {
      case MAIN:
        ....
        break;

.....
  }
}

void checkButtons()
{
    //1.) abfragen ob Knopf gedrückt wurde

//2.) Wenn zwischen Menüs gewechselt wird currentMenu ändern und drawMenu() aufrufen
}

Ich hab ehrlich gesagt etwas gebraucht um zu verstehen, wie du das meinst. Aber jetzt läuft es :slight_smile:

Ich habe mir dazu eine Variable "int bildschirm" erstellt, die jetzt je nach aufgerufener Seite den Wert ändert. Diese frage ich vor den Touch-Funktionen einfach per if ab.