(Version 0.40)
Der Nextion-Editor ist eine komfortable und kostenlose Umgebung, mit der Sie Ihr "Human Machine Interface" (HMI) erstellen und testen können.
Auf die einzelnen Bereiche innerhalb des Editors werde ich bei den folgenden Beispielen eingehen. Wir werden jetzt ein neues Projekt anlegen und klicken dazu auf "New". Es öffnet sich ein File-Dialog, in dem wir das Verzeichnis und den Namen für das Projekt festlegen.
Danach öffnet sich ein weiterer Dialog:
Hier können wir zunächst das Modell auswählen und ob es sich um ein Standard- oder Enhanced-Modell handelt (Intelligent scheint eine 3. Variante zu werden).
Auf der 2. Seite dieses Dialogs steht dann zur Auswahl in welcher Ausrichtung das Display betrachtet wird und welche Zeichencodierung wir nutzen wollen. ISO-8859-1 steht für westeuropäische Zeichen und ist im Grunde immer die richtige Wahl. Falls Sie allerdings auch noch das -Symbol benötigen, wäre hier ISO-8859-15 die Alternative.
Im Anschluss öffnet sich das eigentliche Bearbeitungsfenster, bei dem ich mal zur Abwechslung oben rechts einen anderen Farbstyle gewählt habe.
Bis auf die üblichen Bereiche für Symbol- und Menüleisten, teilt sich der Editor maßgeblich in sieben Einzelfenster auf:
Im Menüpunkt settings können Sie jederzeit die Einstellung bezüglich der verwendeten Hardware und der Ausrichtung ändern. Das ist ein großer Vorteil, denn Sie müssen nicht für jedes Display ein neues Projekt anlegen.
Bevor wir daran gehen, die einzelnen Komponenten zu platzieren, schauen wir uns die leere Seite (page) genauer an. Oben rechts im Bereich G sind alle Seiten aufgelistet. Momentan ist das nur eine, die standardmäßig den Namen "page0" und die ID=0 bekommt.
Mit den kleinen Symbolen (von links nach rechts) können wir die folgenden Aktionen durchführen:
Mit einem Doppelklick auf den Seitennamen können Sie den Eintrag ändern. Sie müssen diese Änderung unbedingt mit der Return-Taste abschließen, sonst ist sie unwirksam. Ich wähle den Namen "start" für die erste Seite. Die ID können wir nicht verändern.
Überlegen Sie bei jedem Design, wie Sie Ihre Anwendung sinnvoll in mehrere Seiten aufteilen. Das hat zum einen natürlich etwas mit dem zur Verfügung stehenden Platz zu tun, zum anderen kann es aber durchaus sinnvoll sein, mehrere Seiten zu wählen, selbst wenn ausreichend Platz auf einer Seite wäre. So ist es immer eine gute Idee, die Konfiguration (z. B. Messauflösung, Kanalanzahl) und den eigentlichen Betrieb (Darstellung der Messwerte) zu trennen. Sie können natürlich später beliebig Seiten hinzufügen oder Komponenten auf eine andere Seite kopieren. Dazu können Sie die Menüpunkte Copy, Cut und nutzen oder auch das bekannte Ctrl-C, Ctrl-V und Ctrl-X .
In diesem Fenster können wir die Eigenschaften von Seiten oder Komponenten festlegen. Ich werde darauf hier nicht näher eingehen, weil die Eigenschaften im nächsten Kapitel Komponenten detailliert beschrieben werden. Hier geht es nur um die Bedienung des Editors.
Es gibt dort statische Attribute (schwarz), die Sie lediglich zur Entwurfszeit festlegen aber im Programm nicht ändern können. Daneben finden Sie auch grüne Einträge, damit sind dynamische Attribute gekennzeichnet, die Sie programmtechnisch ändern können.
Einige Eigenschaftswerte können Sie direkt eingeben, bei anderen müssen Sie auf das Eingabefeld klicken und es öffnet sich ein Dialog. Das ist z. B. bei Farben, Bildern oder Zeichensätzen der Fall.
Events (Ereignisse) sind das Kernelement zum definierten Ausführen von bestimmten Programmsegmenten. Ein "typisches" Computerprogramm läuft an einer bestimmten Stelle los und arbeitet sich dann Schritt für Schritt durch den Code. Es kann springen, in Schleifen laufen, verzweigen ... nur eins kann es nicht: stehen bleiben. Auch wenn es den Anschein hat oder wenn es Funktionen wie "Delays" gibt, die uns das vorgaukeln, irgendwas tut ein Mikrocontroller immer, sobald er mit Strom versorgt wird.
Nachdem die Initialisierungen durchlaufen sind, erreicht das Controllerprogramm die eigentliche Bearbeitungsschleife. Das Programm läuft im Kreis und fragt ständig bestimmte Zustände ab. Bezogen auf einen einzigen Mikrocontroller gibt es weder eine Parallelvearbeitung noch wirkliche softwaremäßige Events. Das einzige echte Event ist ein Hardware-Interrupt. Wird dieser ausgelöst, springt das Programm sofort an eine bestimmte Adresse und führt den Programmcode dort aus. In unserem Fall sind die sogenannten Events nichts anderes als das Setzen von bestimmten Variablen, die vom Betriebssystem ständig abgefragt werden. Dieses Wissen ist sehr wichtig, um die Wirkungsweise richtig zu begreifen.
Ein Nextion-Programm beginnt ebenfalls an einer bestimmte Stelle und wartet dann in einer Schleife. Als erstes wird abgefragt, ob eine Seite neu aufgerufen wurde, ist das der Fall wird das preinitialize
-Event ausgelöst. Nachdem die Seite komplett erstellt wurde, also alle Komponenten gezeichnet sind erfolgt das postinialize
-Event.
Wenn wir eine Seite neu aufrufen oder eine Komponente anklicken, sie wieder loslassen oder sie verändern, werden entsprechende Events ausgelöst. Trotzdem tut der Nextion erst einmal nichts wirklich sinnvolles. Das stimmt nicht ganz, denn selbst ohne den geringsten User-Code werden bestimmte Funktionen ausgeführt, so wird die Farbe beim Anklicken eines Tasters oder Schalters geändert. Aber von einer HMI-Funktionalität können wir dabei noch nicht sprechen.
Im Grunde ist es eine Kommunikation zwischen dem Betriebssystem des Nextions und dem Anwendungsprogramm. Der Nextion sagt: Jemand hat die Taste "ID=1" gedrückt und das Anwendungsprogramm sagt: "Gut, dann schreibe eine 22 über die serielle Schnittstelle".
Die Meldung des Betriebssystems ist das "Event", das darauf reagierende Anwendungsprogramm der "Event-Handler".
Wenn Sie also etwas generell machen wollen, dann schreiben Sie einen Event-Handler für das pre- oder postinitialize-Event. Doch welche Events gibt es noch?
Eine Übersicht über alle Kommandos finden Sie hier. Klicken Sie dort auf einen Befehl erhalten Sie eine detaillierte Beschreibung über Aufbau und Funktion.
Wenn Sie nicht extra Code schreiben möchten, reicht es für viele Fälle auch aus, beim entsprechenden "Touch-Press-" oder "Touch-Release-Event" ein Häkchen beim Send Component ID zu setzen. Dann erhalten Sie Daten über die Seite, die Komponente und über die Art des Events. Genauere Informationen dazu finden Sie im Kapitel Rückgabeformate und Fehlercodes.
Ressourcen sind Elemente, die im Speicher abgelegt werden und von mehreren Komponenten genutzt werden können. Ein Zeichensatz oder Bilder sind Ressourcen. Da der Nextion nicht wissen kann, mit welchem Zeichensatz oder auch Zeichensätzen Sie arbeiten möchten, müssen Sie zu Beginn Ihrer Arbeit Zeichensätze festlegen. Diese werden in einem ganz bestimmten Format im Flash gespeichert und müssen deshalb zunächst einmal erzeugt werden. Das ist logisch, denn ein Embedded System wie der Nextion kann natürlich nicht die Vielfalt an Zeichensätzen vorrätig halten, wie z. B. ein PC.
Das Erzeugen ist aber ganz simpel, denn dafür gibt es ein eigenes Werkzeug, das Sie unter Tools finden und das "Font Generator" heißt:
Im folgenden Dialog wählen wir in dem Auswahlfeld in der Mitte zunächst eine geeignete Schriftart aus (hier Arial). Dabei werden alle auf dem System registrierten Schriften berücksichtigt. In dem kleinen schwarzen Kästchen mit roter Schrift wird ein "x" in der Vorschau angezeigt. Das ist nicht gerade sehr aussagekräftig, aber der Sinn wird deutlicher, wenn wir eine andere Größe im Auswahlfeld "Height" wählen:
Wenn wir den Zeichensatz erzeugen, wird aus dem Windows-Font ein interner Nextion-Zeichensatz erzeugt und im Flash abgespeichert. Dafür ist ein Kompressionsverfahren notwendig, das wir im Feld "Compression-Mode" auswählen können. Voreingestellt ist mode 0. Ich habe die anderen Verfahren ausprobiert und es treten fast immer irgendwelche kleinen Fehler auf, deshalb übernehmen wir auch den empfohlenen Algorithmus.
Falls wir den Zeichensatz fett haben möchten, können wir noch das Kästchen Bold ankreuzen. Ansonsten vergeben wir unter Font Name einen sinnvollen Namen unter dem der Zeichensatz im Editor angezeigt wird, z. B. Standard für alle normalen Anzeigetexte. Am besten speichern Sie ihn unter dem tatsächlichen Namen + der Größe (Beispiel: arial24). Persönlich finde ich das am sinnvollsten.
Klicken Sie jetzt auf Generate Font, so öffnet sich ein Datei-Dialog und Sie können den Ort angeben, an dem Sie den Zeichensatz auf Ihrer Festplatte speichern wollen und auch noch einmal einen Namen. Um nicht durcheinander zu kommen, würde ich den gleichen Namen wählen wie im Editor. Das Abspeichern ist sinnvoll, wenn Sie bei späteren Projekten den gleichen Zeichensatz nutzen, dann können Sie ihn direkt laden und müssen ihn nicht erst erzeugen. Die Dateiendung ist .zi
Es erscheint eine Erfolgsmeldung, dass der Zeichensatz erzeugt wurde und auch eine Angabe, wie groß der Speicherverbrauch dafür ist.
Nachdem wir den Dialog geschlossen haben, passiert zunächst nichts. Hier wäre eine entsprechende Meldung über das weitere Vorgehen sinnvoll. Man muss einfach wissen, das wir jetzt noch weitere Zeichensätze erzeugen könnten oder aber einfach den Dialog schließen müssen und das nicht ganz konform mit einem Klick auf das Schließen-Kreuz im Systemmenü oben rechts.
Jetzt erhalten wir wieder eine Meldung und zwar die Frage, ob wir den Zeichensatz hinzuügen möchten. Das wollen wird und klicken auf "Yes".
Wenn sie jetzt im Editor-Bereich "C" (Picture/Fonts) auf Fonts klicken, finden Sie dort die Einträge für den oder die Zeichensätze.
Der Zeichensatz hat die id=0, der Name ist arial24, die Größe: 12x24 Pixel, es wurden 224 Zeichen erzeugt, die einen Speicher von 8071 byte belegen.
Sie können in diesem Fenster wieder über die Symbole (oben von links nach rechts):
In der gleichen Art und Weise, wie Sie Zeichensätze von der Festplatte laden, können Sie dies auch mit Bildern tun. Alle Bilder, die Sie innerhalb eines Projektes benötigen, werden in den Picture-Bereich geladen. Klicken Sie dazu im Editor-Sektor "C" auf den Reiter "Picture". Die Symbole sind mittlerweile bekannt. Wir können Bilder hinzufügen, löschen, in der Reihenfolge verschieben etc. Nutzen können Sie alle bekannten Formate wie jpg, tif, gif, png, bmp. Diese Formate habe ich getestet, andere sollten aber auch funktionieren. Im schlimmsten Fall müssten Sie ein Bild konvertieren. Bei gif-Animationen wird allerdings nur der 1. Frame angezeigt und nicht die komplette Animation.
Wichtig: Erstellen Sie die Bilder vorher in der Größe, in der Sie sie benötigen, eine Skalierung ist im Nextion-Editor selbst nicht möglich. Ich habe einmal zur Anschauung 2 Bilder hochgeladen:
Im Editor wird auf die Bilder nur über ihre ID zugegriffen, deshalb finden wir keine Bildnamen. Immer, wenn wir später bei einer Komponente auf die Eigenschaft pic, pic1, pic2 klicken, erscheint die Auflistung aller Bilder und wir können sie daraus auswählen. Der Inhalt lässt sich aber später auch per Code ändern. Hilfreich ist auch die Angabe der Größe. Die Doppelskala habe ich für die Anzeige von 2 Analogwerten gewählt. Für den tatsächlichen Einsatz müssten allerdings die Zeiger weg retuschiert werden. Außerdem ignorieren Sie bitte die Skaleneinteilung auf die es hier im Beispiel auch nicht ankommen soll. Für eine reale Anwedung würde man sich entweder eine entsprechende Zeichnung anfertigen oder ein konkretes Instrument suchen, das genau passt.
Jetzt können wir mit dem Platzieren der Komponenten beginnen. Dabei werde ich nur das prinzipielle Vorgehen erklären und nicht auf alle Komponenten einzeln eingehen. Die sind ausführlich im nächsten Kapitel Komponenten beschrieben.
Durch Klicken auf eine Komponente wird sie an der linken oberen Ecke des Bildschirms platziert. Danach können Sie sie anfassen und verschieben oder Sie geben in den Eigenschaften bei x, y entsprechende Werte ein. Auch die Größe können Sie dort über w, h ändern. Die Erklärung der allgemeinen Eigenschaften finden Sie ebenfalls zu Beginn des Kapitels über die einzelnen Komponenten.
Eine häufige Aufgabe ist das Platzieren mehrere gleichartiger Komponenten. Dazu gibt es in ausgereiften Entwicklungsumgebungen sehr komplexe Tools, mit denen Sie gleiche Abstände oder eine Anzeige der Abstände direkt in Pixeln erkennen können. Sie müssen aber bedenken, dass der Nextion-Editor noch sehr jung ist und deshalb für diese Aufgaben (in der aktuellen Version) nur einige wenige Hilfen dafür bietet. Zur Not hilft halt nur: rechnen und Koordinaten manuell eingeben.
Die Hilfsleiste für eine Platzierung finden Sie ganz oben links:
Die Bedeutung der einzelnen Symbole von links nach rechts sind:
An kleinen Beispielen wollen wir uns jetzt anschauen, wie wir Leben in ein Nextion-HMI bringen. Dazu lade ich zunächst als Hintergrundbild der 1. Seite die doppelte Anzeige und werde dann 2 Slider hinzufügen, mit denen ich die Anzeige ansteuere. Die Schritte:
Da die Gauge-Komponente nur ein "crop image" (Bildausschnitt) als Hintergrund erlebt müssen Sie zunächt ein vollformatiges Bild erstellen. Das Vorgehen ist auch noch einmal konkret bei der Gauge-Komponente beschrieben.
Die Seite sieht nun folgendermaßen aus:
Würde sich der Zeiger jetzt drehen, dann wäre zum einen der Drehpunkt nicht ganz in der Mitte der Skala und zum anderen wäre er zu lang. Also verkleinern wir die Gauge-Komponente etwas und verschieben sie außerdem ein wenig nach unten. Außerdem möchte ich den Zeiger etwas dicker haben wid=4 und die Farbe (pco) des 2. Zeigers ändere ich auf rot.
So ganz toll ist das noch nicht, denn durch das Verkleinern der Gauge-Elemente ist auch der Bildausschnitt kleiner geworden. Eigentlich würde ich das Bild gern ganz sehen und nur die Gauge-Elemente verkleinern. Um das zu erreichen, muss das Bild außerdem noch als Hintergrund für die Seite gewählt werden. Keine Angst, das kostet keinen zusätzlichen Speicher, denn intern wird das Bild nur einmal benötigt.
Ändern wir also die sta-Eigenschaft von page0 auf "image", klicken dann wieder doppelt auf die pic-Eigenschaft und wählen wir das Bild auch hier aus. Jetzt haben wir genau das Ergebnis, das uns vorschwebte:
Den linken Zeiger wollen wir über einen Slider einstellen, der rechte soll an ein Numberfeld gekoppelt werden. Es geht hier weniger um den Sinn dieser Anordnung, sondern mehr um die Funktionsweise.
Im Rohzustand sieht unsere Oberfläche jetzt so aus:
Zumindest den Slider werde ich optisch etwas aufwerten, in dem ich sowohl für den Hintergrund (sta) wie auch für den Vordergrund (psta) kleine Grafiken wähle, die ich natürlich vorher in die Picture-Galerie eingefügen muss. Danach sieht der Slider so aus:
Der Wert des Sliders soll jetzt auf der Skala angezeigt werden. Ein Gauge kann die Werte von 0 bis 360 (Grad) annehmen, also sollten wir auch den Slider darauf beschränken. Dafür nutzen wir die Eigenschaften minval und maxval. Das optimale Event, um die Daten zwischen Slider und Gauge zu synchroniseren, ist der Moment, in dem die Stellung des Schiebereglers verändert wird. Das wäre das "Touch Move Event". Wir klicken den Slider an und wählen dann im Event-Fenster den Reiter des Ereignisses. Dort gehen wir den entsprechenden Befehl ein:
Um den zuvor eingegebenen Code testen zu können, wählen wir eine der hilfreichsten Funktionen des Nextion-Editors auf: den Debugger. Er ist außerordentlich leistungsfähig und spart uns das permanente Herunterladen des Codes in den Flash-Speicher. Auch wenn die Zyklusfestigkeit recht hoch ist, hat er halt nur eine begrenzte Lebensdauer.
Schauen wir aber zunächst, ob das kleine Programm fehlerfrei übersetzt werden kann. Das können wir mit einem Klick auf Compile oben in der Menüleiste. Mit dieser Funktion erzeugen wir im "Build-Ordner" eine "tft"-Datei. Das ist eine Binärdatei, die wir direkt auf eine SD-Karte schreiben können. Stecken wir diese anschließend ins Nextion-Device, wird das Programm in den Speicher geladen und beim nächsten Einschalten gestartet.
Nach dem Compilieren erhalten wir im Output-Fenster die folgende Meldung:
"Compile Succesful" hört sich immer gut an und so lange Sie keinen roten Text sehen, ist alles glatt gelaufen. Das sollte bei einem derart umfangreichen Programm natürlich auch kein Wunder sein. Aber kleine Fehler schleichen sich immer mal schnell ein.
Nun rufen wir den Debugger auf:
Meine Beschreibung beginne ich oben links mit dem Menüpunkt Operation:
Hier können Sie unterschiedliche Funktionen wählen, z. B. das Programm in den Nextion laden, die Echtzeituhr (nur Enhanced-Version) justieren etc. Die Einträge sind einigermaßen selbsterklärend.
Unter Send command to:
können Sie festlegen, ob Sie mit dem Simulator, dem Nextion-Device oder beiden Einheiten kommunizieren. So lange keine Hardware angeschlossen ist, werden auch keine weiteren Angaben erforderlich. Möchten Sie allerdings mit dem Device selbst interagieren, müssen Sie auch noch den seriellen Port wählen, bzw. suchen lassen und auf Connect drücken:
Das wichtigste Fenster befindet sich unten links und trägt den Namen Instruction Input Area. Hier werden also alle Befehl eingegeben:
Dabei können Sie aber wählen, ob die Eingabe über die Tastatur erfolgt oder von einem Host-Controller. Ist Letzteres der Fall, müssen Sie wieder angeben über welche Schnittstelle der Host-Controller am PC angeschlossen ist. Für eine erste Simulation ist Keyboard Input die richtige Wahl.
In den den beiden Fenstern in der Mitte und rechts werden die Ausgaben angezeigt. In der Mitte meldet sich der Simulator:
Im rechten Fenster erscheinen die Informationen, die vom Host-Controller (so verhanden) über die serielle Schnittstelle an den PC gesendet werden.
Durch diese Anordnung ist eine sehr schöne Trennung der Kommunikation möglich, denn gerade hier liegt oft die Ursache für einen Fehler.
Ebenfalls sehr nützlich zum Testen der Waveform-Komponente ist der im Debugger integrierte Waveform-Generator ganz unten rechts. Rufen Sie ihn auf, erschient antstelle des Input-Fensters ein Menü zum Konfigurieren eines kleinen Wertegenerators:
Sie können die Komponenten-ID wählen, den Kanal oder auch mehrere, den Wertebereich und das Intervall, in dem die Daten liegen. Auch eine Zufallsfunktion "Random" ist möglich.
So viel zur Beschreibung. Jetzt wollen wir aber unsere kleine Anwendung testen. Da die val-Eigenschaft des Sliders direkt mit der val-Eigenschaft des Zeigers verbunden ist, sind zunächst keine Eingaben in der Instruction Input Area nötig. Wir bewegen einfach den Slider und der Zeiger dreht sich entsprechend mit. Das hat also schon einmal funktioniert. Testen wir einmal was passiert, wenn wir Wert des Sliders über einen Befehl ändern. Dazu tippe ich h0.val=180
im Eingabefenster und sende das Kommando mit Return ab:
Der Schieberegler springt zwar in die Mitte, der Zeiger bleibt aber stehen. Das ist auch logisch, denn es wurde ja kein "Touch-Move-Event" ausgelöst. Es besteht also kein klassisches Binding der beiden Eigenschaften. Auf der gleichen Art und Weise können Sie jetzt auch den Zeiger z. B. über z0.val=100
bewegen. Die Befehle bleiben im Fenster stehen bis Sie sie explizit löschen und Sie können sie auch alle zusammen aufrufen, indem den entsprechenden Eintrag Run all commands anklicken.
Würden Sie sich bei der Eingabe vertippen oder eine falsche Syntax verwenden, erscheint eine Fehlermeldung vom Simulator, die wie folgt aussieht:
Die Meldung 0x1a 0xff 0xff 0xff
ist ein Fehlercode, deren Bedeutung Sie im Kapitel "Rückgabeformate und Fehlercodes" an dieser Stelle finden.
Damit wären wir eigentlich am Ende unserer Tour durch die Funktionen des Editors und des Debuggers aber wir haben den 2. Zeiger und die Number-Komponente noch nicht genutzt.
Der 2. Zeiger sollte geändert werden, wenn sich der Wert der Number-Komponente ändert. Schreibt also der Host einen neuen Wert in n0.val
so soll ihm der Zeiger folgen. Das ist jetzt nicht wirklich sinnvoll, weil sich die Frage stellt, warum man nicht gleich die Zeiger-Komponente anspricht bzw. beide Werte ändert, aber diese Konstellation bietet sich an, um eine Problematik aufzuzeigen.
Es stellt sich nämlich die Frage, wo Sie den entsprechenden Code platzieren würden. Es gibt zwar auch für die Number-Komponente das Touch-Press- und Touch-Release-Event, die sind hier aber alles andere als sinnvoll. Es wäre also ein Ereignis in der Form eines "onChange"-Events erforderlich. Das können wir allerdings nur künstlich erzeugen, indem wir z. B. einen Timer nutzen.
Wir klicken dazu in der Komponentenliste auf "Timer". Es handelt sich um eine nicht sichtbare Komponente und diese erscheinen unter dem eigentlich Hauptfenster (kleine grünes Quadrat "tm0" in der Mitte).
Bei einem Timer können wir über die Eigenschaft tim eine Zeit in Millisekunden angeben (s. auch Timer). Der Timer zählt kontinuierlich vom tim-Wert auf Null und löst bei jedem Nulldurchgang ein Timer-Event aus. Ich wähhle jetzt einen Timer-Wert von 500 ms und gebe beim Timer-Event den Code z1.val=n0.val
ein.
Jetzt starten wir wieder den Debugger und geben den Befehl n0.val=100
ein. Die Zahl wird in der Number-Komponente angezeigt und sofort darauf springt der Zeiger auf den gleichen Wert.