nextion-Display und Mega2560 - Ein Beispiel

Hallo,

nachdem ein nextion Display bei mir schon eine geraume Zeit rumlag und ich jetzt endlich mal etwas Ruhe zum Spielen hatte, habe ich mich mal mit diesem beschäftigt. Was mich wirklich überall stört, ist das “Warum biste auch so blöd und machst das so.”, “Denk doch erst mal nach, bevor Du was machst.”, “Laien sollten davon die Finger lassen”, “Nimm doch ein 4D”. Jepp, alles extrem hilfreich. Ich beziehe mich hier nicht explizite auf dieses Forum, obwohl das leider auch hier immer wieder auftaucht - vor allem das sklavische Ablehnen bezüglich der nextion-Bibliothek. Jeder ist mal Anfänger gewesen. Darum muss man aber nicht als Depp behandelt werden. Vergessen die meisten nur zu gerne.

Ja, ich bin durch zahllose Foren getigert und habe wirklich hunderte von Beiträgen gelesen. Die wenigsten sind hilfreich für echte Anfänger. Am Ende habe ich es so gemacht wie immer: learning by doing. Das Böker Tutorial, auf das gerne sklavisch verwiesen wird, habe ich natürlich auch nachgearbeitet. Aber es hört eben für einen Newbie da auf, wo es eigentlich interessant wird. Über HTherm läuft alles prima. Will man dann aber den Arduino und das nextion nutzen, steht man plötzlich vor massiven Fragen. Trotzdem ein sehr hilfreiches Tutorial.

Ich versuche meist Postings nachzuvollziehen, was aufgrund der sehr merkwürdigen Antworten (Pädagogik: 6. Setzen) nicht gerade leicht fällt - vor allem wenn man im nextion-Forum Hilfe sucht und nur dummschwätzerische und beleidigende Antworten der beiden nextion-Forenbetreuer erhält, die anscheinend unter einem Gottkomplex leiden. Die Programmierer, mit welchen ich zu tun habe, würden für so etwas entlassen werden.

Aus diesem Grund will ich einfach mal für andere Laien meinen Einstiegstest veröffentlichen, in der Hoffnung anderen interessierten Laien das Leben etwas leichter zu machen. Was ich nicht möchte, ist Kommentare zu ernten, was man alles besser machen könnte und versucht das Beispiel zu verreißen. Ich weiß, dass ich gerade erst anfange. Es ist für mich ein Einstieg in die Materie gewesen. Ich sehe noch einiges Verbesserungspotential, gerade auch was den Speicher betrifft. Man könnte auch vieles im nextion durchführen. Wollte ich aber bewusst nicht. Es ist eben nur ein Testprojekt. Wer nur daran rummäkeln möchte, den bitte ich ein vergleichsweises, aber natürlich viel besseres, Demo einzustellen.

Ich habe einen Arduino Mega 2560, ein nextion 3,5" enhanced Display und ein 8-Port Relaisboard zum rumspielen genutzt. Es ging mir allein um das Prinzip des Verstehens des Datenaustausches zwischen Arduino und nextion und das Ausprobieren. Über das nextion schalte ich die einzelnen Relais, schalte alle" gleichzeitig" an, bzw. aus, oder lasse eine Testsequenz durchlaufen. Mehr nicht. Die Funktionen geben dem nextion auch ein Feedback, in dem die Buttonfarbe bei ausgeschaltetem Relais grau ist und bei eingeschalteten grün. Auch gibt es im Display ein kurzes Textfeedback, was alle 5s gelöscht wird. Sollte ich mal Fritzing verstehen und die Relais-Komponente finden, erstelle ich vielleicht auch einen Schaltplan zur Hilfe, falls es jemand benötigt.

Kleiner Tipp noch: wenn nur noch Müll am Arduino ankommt, einfach mal auf die Masseleitung zwischen der Stromversorgung des nextion und dem Arduino schauen. Ich habe ewig gebraucht, bis ich bemerkt habe, dass die Masseverbindung sich durch das in die Hand nehmen gelöst hatte :roll_eyes:

Im Anhang findet Ihr die INO- und die HMI-Datei - zum Rumspielen und Nachvollziehen.

Vielleicht hilft es ja jemanden.

Euer

Dali

P.S.
Ich habe bezüglich der sinnvolleren Verwendung von Speichertypen eine Kleinigkeit geändert. Danke für Deine Anmerkungen postmaster_ino.

Relais_test.zip (12.6 KB)

Und hier der Code im Klartext. Hatte vorher die 9000-Zeichen überschritten und musste dann die fünf Minuten Sperrzeit abwarten.

// Kein Fehlerabfangen.


#define nextion Serial2                               // Pin 16 und 17 bei MEGA 2560

const uint8_t relais[2][8] = {
  {10, 11, 12, 13, 3, 4, 5, 6}, // Zuordnung Nextion Objekt-ID zu Relais
  {53, 51, 49, 47, 45, 43, 41, 39} // Zuordnung Relais zu digitalen PINs
};
String relais_button_name[8] = {"r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"};
byte relais_aktiv[8];

const uint16_t ButtonColorEin = 1024; //grün
const uint16_t ButtonColorAus = 48631; // Hellgrau - LONG, da INT nur bis 32767 geht

byte SeitenID;
byte KomponentenID;
byte Eventtyp;
byte Event;
const byte NextEnd[3] = {255, 255, 255}; // Abschluss Nextion-Befehl

unsigned long StartzeitMilliSek;  // Timer-Startzeit
unsigned long AktuellMilliSek;
const unsigned long TimerPeriode = 3000;  // alle 3s

void setup() {
  Serial.begin(115200);
  nextion.begin(115200);
  StartzeitMilliSek = millis();  //Erste Startzeit festhalten
  String Starttext = "Arduino gestartet";
  Serial.println(Starttext);
  StatusText(Starttext);

  for (uint8_t i = 0; i < 8; i++) {
    pinMode(relais[1][i], OUTPUT); // Den digital PIN als Ausgangssignal setzen.
    RelaisSchalten(i, false);
  }
}

void loop() {
  nextionRead();
  if (Event == 101) {   //Touchevent
    RelaisSwitch();     // Schalten der Relais, entsprechtend der Objekt-ID des nextions
    Event = 0;          // Keine Event mehr vorhanden
  }
  delay(100);           // ohne das delay hier werden die Daten nicht sauber eingelesen. ?

  AktuellMilliSek = millis();  //Aktuelle Zeitstempel
  if (AktuellMilliSek - StartzeitMilliSek >= TimerPeriode)  //Timerzeit überschritten?
  {
    StatusText(" ");
    StartzeitMilliSek = AktuellMilliSek;  //Timer neu starten
  }
}

void StatusText(String Displaytext) {           // Text an den Arduino schicken
  nextion.print("main.tArduinoStatus.txt=\"");  // Statustextfeld
  nextion.print(Displaytext);                   // Anzuzeigender Text
  nextion.print('"');                           // Textfeld abschliessen
  nextion.write(NextEnd, 3);                    // nextion mitteilen, dass Übertragung beendet ist
}

void RelaisSwitch() { // Schalte Relais
  if (KomponentenID > 0) {
    uint8_t i;
    if (KomponentenID < 2) { // Alle an, ID = 1
      StatusText("Alle an");
      for (i = 0; i < 8; i++) {
        RelaisSchalten(i, true);
      }
    }
    else if (KomponentenID < 3) { // Alle aus, ID = 2
      StatusText("Alle aus");
      for (i = 0; i < 8; i++) {
        RelaisSchalten(i, false);
      }
    }
    else if (KomponentenID == 9) { // Testsequenz, ID = 9
      StatusText("Test-Sequenz");
      for (i = 0; i < 8; i++) {
        RelaisSchalten(i, false);
      }
      for (i = 0; i < 8; i++) {
        RelaisSchalten(i, true);
        delay(100);
      }
      for (i = 0; i < 8; i++) {
        RelaisSchalten(i, false);
        delay(100);
      }
      for (i = 0; i < 4; i++) {
        RelaisSchalten(i, true);
        RelaisSchalten(7 - i, true);
        delay(100);
      }
      for (i = 0; i < 4; i++) {
        RelaisSchalten(i, false);
        RelaisSchalten(7 - i, false);
        delay(100);
      }
      for (uint8_t x = 0; x < 3; x++) {
        for ( i = 0; i < 8; i++) {
          RelaisSchalten(i, true);
        }
        delay(100);
        for (i = 0; i < 8; i++) {
          RelaisSchalten(i, false);
        }
        delay(100);
      }
      for (i = 0; i <= 64; i++) // Eingangscache löschen
      { uint16_t tmp[64];
        tmp[i] = nextion.read();
      }
    }
    else {  // Relais entsprechend der Button-Eingabe schalten, ID = alles andere
      for ( i = 0; i < 8; i++) {
        if (relais[0][i] == KomponentenID ) {
          if (relais_aktiv[i]) {                            // Relais eingeschaltet
            StatusText("Relais " + String(i + 1) + " aus"); // Relaisstatus an nextion
            RelaisSchalten(i, false);                       // Relais Ausschalten
          }
          else {                                            // Relais ausgeschaltet
            StatusText("Relais " + String(i + 1) + " ein"); // Relaisstatus an nextion
            RelaisSchalten(i, true);                        // Relais Einschalten
          }
        }
      }
    }
    KomponentenID = -1; // Neue Eingabe abwarten
  }
}

void RelaisSchalten(uint8_t Relaisnummer, boolean Einschalten) {  // Relais schalten und Buttonthintergrundfarbe abhängig vom Schaltzustand setzten
  nextion.print("main.");
  nextion.print(relais_button_name[Relaisnummer]);
  nextion.print(".bco=");
  if (Einschalten) {
    digitalWrite(relais[1][Relaisnummer], LOW);
    relais_aktiv[Relaisnummer] = true;
    nextion.print(ButtonColorEin);
  }
  else {
    digitalWrite(relais[1][Relaisnummer], HIGH);
    relais_aktiv[Relaisnummer] = false;
    nextion.print(ButtonColorAus);
  }
  nextion.write(NextEnd, 3);
}

void nextionRead() {  // Die Daten vom nextion Byteweise einlesen und Anzeigen was empfangen wurde
  uint16_t SerialDaten = nextion.available();
  byte SerialCacheByte[SerialDaten];
  if (SerialDaten > 0)
  {
    Serial.println("-");
    Serial.print("Gefundene Bytes = ");
    Serial.println(SerialDaten);
    for (uint16_t i = 0; i <= SerialDaten; i++)
    {
      SerialCacheByte[i] = nextion.read();
    }
    Event = SerialCacheByte[0];
    SeitenID = SerialCacheByte[1];
    KomponentenID = SerialCacheByte[2];
    Eventtyp = SerialCacheByte[3];
    Serial.print("Event: ");
    Serial.println(SerialCacheByte[0]);
    Serial.print("Seite: ");
    Serial.println(SerialCacheByte[1]);
    Serial.print("Komponente: ");
    Serial.println(SerialCacheByte[2]);
    Serial.print("Eventtyp: ");
    Serial.println(SerialCacheByte[3]);
    Serial.println("-");
    StartzeitMilliSek = AktuellMilliSek;  //Timer zum Löschen der Info am nextion neu starten
  }
}

Was erwartest Du von uns, wenn Du uns in jedem 2. Satz als "sklavisch" abqualifizierst?

Gruß Tommy

Hallo Tommy,

wie ich schon schrieb, war das eine allgemeine Feststellung und nicht speziell auf diesen Bereich des Forums oder dieses Forum bezogen. Ziehst Du Dir diesen Schuh an? Warum?

Und ich erwarte nichts.

Nö, ziehe ich mir nicht. Es sagt nur Einiges über Dich aus.

Gruß Tommy

  delay(100);           // ohne das delay hier werden die Daten nicht sauber eingelesen. ?

Mehr muss ich dazu nicht sagen.

Added:

Mit Serial auf 250000 Baud (und Serial1 als Verbindung zum Nextion) funktioniert der Sketch nicht.
Fragiles Timing und völlig naive Einlesemethode.

Außerdem gibt es noch einen Arrayüberlauf

Somewhere\NextionString\NextionString.ino: In function 'void RelaisSwitch()':

Somewhere\NextionString\NextionString.ino:114:18: warning: variable 'tmp' set but not used [-Wunused-but-set-variable]

       { uint16_t tmp[64];

                  ^

C:\Users\Sven\Documents\Arduino\FremdeBeispiele\NextionString\NextionString.ino:115:32: warning: iteration 64 invokes undefined behavior [-Waggressive-loop-optimizations]

         tmp[i] = nextion.read();

                                ^

C:\Users\Sven\Documents\Arduino\FremdeBeispiele\NextionString\NextionString.ino:113:21: note: containing loop

       for (i = 0; i <= 64; i++) // Eingangscache löschen

                     ^

mit Glück wird der aber wegoptimiert.

Die x Positionen der Buttons sind nicht gleich, die stehen wie Kraut und Rüben.