Nextion
Nextion | |
---|---|
Zweck / Funktion | |
Anbindung von Nextion Touch Displays | |
Allgemein | |
Typ | Gerätemodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | Bastelecke |
Modulname | 42_Nextion.pm |
Ersteller | viegener |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
Das FHEM Modul Nextion dient zur Einbindung der kostengünstigen, mit serieller Schnittstelle ausgestatteten Displays, die von der Firma Fa. Itead in verschiedenen Größen angeboten werden.
Modelle
Es gibt zwei Grundmodelle (basic und enhanced), wobei die enhanced-Modelle Zugriff auf GPIOs erlauben. Beide Modelle sind in Größen von 2,4 Zoll bis zu 7 Zoll erhältlich.
Inbetriebnahme
Stromversorgung
Die Nextion-Displays benötigen eine stabile 5V Spannungsversorgung. Zudem befindet sich auf dem Display ein 3.3V-Ausgang, der aber maximal 100 mA liefert und daher nicht für die Anbindung leistungsintensiver Geräte (dazu gehört schon der ESP8266) genutzt werden kann. Ausgeliefert werden die Displays mit einem vierkabligen Anschluss, der die Spannungsversorgung (5V und GND) sowie die serielle Schnittstelle (Rx und Tx) liefert.
Serielle Schnittstelle und Flashing
Um die Displays anzuschließen, muss daher die serielle Schnittstelle physisch mit der vorhandenen Infrastruktur gekoppelt werden. Dabei bietet es sich an, die Displays ins eigene WLAN-Netz einzubinden (auch eine direkte USB-Verbindung ist denkbar). Die Einbindung ins WLAN kann beispielsweise mit den ESP8266-Modulen vorgenommen werden, da diese auch über eine serielle Schnittstelle verfügen und zudem leicht für das eigene WLAN vorbereitet werden können. Eine möglichst einfache Anbindung scheint dann gegeben, wenn man einen Wemos D1 Mini verwendet.
In diesem Forenthema wird intensiv diskutiert, ob die serielle Schnittstelle mit einem Spannungsteiler oder direkt an den ESP angeschlossen werden kann. Da die Produkte aus Fernost oft massive Abweichungen von den Standards besitzen können, sollte hier nachgemessen werden. Ist ein Spannungsteiler nötig, kann man sich etwa an diesem Schaltplan orientieren. Der oben genannte Wemos Mini besitzt einen Micro-USB Anschluss, der die 5V Stromversorgung für das Display liefert; mehrere User berichteten, dass sie das Display direkt (also ohne Spannungsteiler) an den Wemos anschließen konnten.
Das Nextion-Modul verlangt (anscheinend) eine Baudrate von 115200. Dieses muss in einem HMI-File, der das Display bespielt, vorab eingestellt werden. Dazu verwendet man auf der ersten Seite (page 0) die post-initialization den Befehl baud=115200
.
Die Firmware für die serielle Verbindung auf dem ESP8266 kann zum Beispiel ESPEasy oder ESPlink sein.
ESPLink
Flasht man den Chip mit ESPLink, so lautet der Befehl bei Verwendung von esptool.py
esptool.py --port /dev/tty.<USB Port eintragen> write_flash -fm qio -ff 80m 0x00000 boot_v1.7.bin 0x01000 user1.bin 0x3fc000 esp_init_data_default.bin 0x3fe000 blank.bin
In ESPLink muss man dann den WLAN-Zugang eintragen, danach funktioniert die Verbindung zur seriellen Schnittstelle sofort (normal UART einstellen, nicht swapped).
ESPEasy
Flasht man den Chip mit ESPEasy, so lautet der flash-Befehl
./esptool.py --port /dev/tty.<USB Port eintragen> --baud 115200 write_flash -u -fm dio -fs 1MB 0x00000 ESP_Easy_mega-20181220_normal_ESP8266_1024.bin
(evtl lautet der Dateiname der Firmwaredatei inzwischen anders). In ESPEasy muss man auf der advanced-Seite die serielle Schnittstelle aktivieren, die Baudzahl einstellen (115200) und dann bei den Geräten ("devices") unter Communication-Seriell Server die entsprechenden Daten für den Port (23) sowie 8 Datenbits, non-parity und 1 stopbit einstellen, mehr hierzu in dem Beitrag im Forum
Programmierung
Es gibt zwei Möglichkeiten, die Displays zu programmieren. Einmal bietet Itead mit dem Nextion Software Editor eine Windows-basierte Software an, mit der man auf dem Display verschiedene Stilelemente (Buttons, Labels, Pages etc.) platzieren kann. Dabei ist zu beachten, dass eventuelle Schriftarten zuerst erstellt und ebenfalls geladen werden müssen. Ein Video für eine solche Installation findet man etwa hier oder hier. Ebenso findet sich eine sehr gute Einführung in die Programmierung auf folgender Webseite von Böcker. Nachdem die Software kompiliert wurde, muss sie hochgeladen werden. Das kann entweder durch eine micro-SD-Karte geschehen, die man in das Display steckt. Oder man verwendet die serielle Schnittstelle, mit der man die Firmware hochlädt (upload-Button im Editor).
Die zweite Möglichkeit betrifft die Einbindung in FHEM, siehe dazu unten.
Einbindung in FHEM
Programmierung mit Modul
Eine andere Möglichkeit besteht darin, mit Hilfe der seriellen Schnittstelle das Modul 42_Nextion.pm zu verwenden. Dieses Modul ist bereits in der Standardinstallation von FHEM enthalten. Man legt dazu ein device an
defmod <myNextion> Nextion <hostname/ip>:23@115200
und folgt der Darstellung aus der Commandref. Die Baudrate sollte der Portnummer mit @ anhängt werden. Sie sollte ebenfalls im Display mit dem Befehl baud=115200 (unter Postinitialize event auf page 0) eingegeben werden (siehe oben).
Darstellung zur Laufzeit
Im Gerät angelegte Elemente (wie hier zum Beispiel Texte) spricht man dann zum Beispiel so an
set <myNextion> cmd t0.txt=\"test\";
oder auch
set <myNextion> cmd t0.txt="test";
Handelt es sich um Zahlen, dann
set <myNextion> cmd t1.txt=12345;
Ebenso kann man dargestellte Bilder während der Laufzeit austauschen, unsichtbar oder sichtbar machen. Weitere Befehle finden sich sowohl auf der Itead-Webseite oder dem oben angegebenen Link: so kann man beispielsweise das Display dimmen oder bestimmte Seiten auswählen.
Hat man mehrere Seiten erstellt und wechselt zwischen diesen Seiten, setzt Nextion die Werte auf die ursprünglichen Größen zurück (irritierenderweise wird dieses Zurücksetzen als "Refresh" bezeichnet - obwohl gerade kein refresh stattfindet). Will man, dass auf der Seite 0 auch nach einem Seitenwechsel wieder bestimmte Werte angezeigt werden, muss man im Modul das folgende Attribut setzen (hier wird Setmagic verwendet, wir lesen das Attribut temperature des devices Messgeraet aus und weisen es dem Text-Inhalt der Komponente temp auf Seite 0 zu):
attr <myNextion> initPage0 temp.txt="[Messgeraet:temperature]";
Damit diese Zuweisung funktioniert, müssen zu Beginn aber im Event einer jeder einzelnen Seite bei "Preinitialize Event" der Eintrag "bkcmd=3" und bei "Postinitialize Event" der Befehl "sendme" eingetragen sein (damit die aufgerufene Seitenzahl dem Modul mitgeteilt wird).
Eine etwas aufwendiger zu gestaltende Idee besteht darin, Icons aus einem Wetterdevice (zum Beispiel Proplanta) auf das Nextion-Display zu übertragen. Dazu fügt man in initPage0 neben den bisher bestehenden Zuweisungen folgendes hinzu
wetter.pic={(WeatherToNextion(ReadingsVal(<WetterDeviceName>,"fc1_code",100)))};
wobei das Device <WetterDeviceName> ein Reading mit fc1_code enthält. Dieses Reading enthält dann Informationen, welches Icon zu einem bestimmten Vorhersagezeitpunkt aufgerufen werden soll. Die Perl-Funktion WeatherToNextion wandelt dann diesen Reading-Wert in die entsprechende ID des anzuzeigenden Bildes um; dabei müssen vorab alle später anzuzeigenden Bilder in den Editor geladen werden. Beispielhaft könnte die Funktion so aussehen
sub WeatherToNextion($) { my ( $val ) = @_; return 20 if ( $val == 2 ); return 21 if ( $val == 3 ); return 21 if ( $val == 4 ); return 22 if ( $val == 5 ); return 23 if ( $val == 6 ); return 24 if ( $val == 7 ); return 25 if ( $val == 8 ); return 25 if ( $val == 9 ); usw.... return 48; }
Bei der Verwendung von Perl-Code muss SetMagic verwendet werden, d.h. der Code ist einzuklammern in {( Code )}.
Wakeup
Es besteht die Möglichkeit, das Display automatisch nach einer gewissen Anzahl von Sekunden auszuschalten (thsp=10). Beachten Sie, dass das Display nur dann nach einer Berührung wieder aufwacht, wenn vorher die Variable thup=1 gesetzt wurde. Es bietet sich an, beide Variablen bereits im Nextion-Editor zu definieren.
Dieser sleep-Modus setzt das Gerät auf die ursprünglichen Werte zurück, auch scheint zwischendurch ein Senden an das Display nicht möglich (obwohl in den Dokumentationen etwas anderes behauptet wird). Der Sleep-Modus scheint dem arduino zu ähneln, bei dem der Stromverbrauch nur noch auf das notwendigste gedrosselt wird.
Will man zwischendurch nur das Display ausschalten, bietet es sich dagegen an, mit dem internen dim-Befehl zu arbeiten. Beispielsweise schaltet dim=0
den Bildschirm aus; hier muss man einen internen Timer hinzufügen. Hier sind also zwei Angaben notwendig: Einmal bei einem Timer und ein weiteres Mal bei dem Objekt, das den Bildschirm aufwecken soll:
- Dazu definiert man einen timer (beispielsweise tm0). Ein solcher Timer zählt von der angegeben Anzahl (tm0.timer) die Anzahl der Millisekunden nach unten und fängt dann wieder erneut an herunterzuzählen. Immer dann, wenn er den Wert 0 erreicht, führt er das timer-Event aus (dieses Objekt würde man besser als "repeater" bezeichnen). Fügt man in die Definition dieses Events den Befehl tm0.en=0 sowie dim=0 ein, so wird der Timer nach einem einmaligen Herunterzählen ausgeschaltet; ebenso schaltet sich der Bildschirm aus.
- Wenn nun an dem Objekt, das den Bildschirm aufwachen lassen soll, die Befehle dim=85 und tm0.en=1 eingefügt werden, wird durch Drücken des Objektes der Bildschirm erhellt und der Timer aktiviert. Dieser Timer zählt dann einmal nach unten und schaltet sich selbst aus.
Da sich die Objekte auf dem Display unter Umständen gegenseitig überlagern, muss vermutlich bei jedem am Bildschirm sichtbaren Objekt dieser Code eingegeben werden,
Buttons auslesen
Die Buttons auf dem Display können ausgelesen werden (anscheinend darf dazu eine Seite/page nicht ihre Component ID senden, siehe oben). Man macht dazu bei den Buttons oder Tastern einen Haken bei Send Component ID und kann dann mittels notify entsprechende Events abfangen. Typischerweise sieht ein notify so aus
defmod <myname> notify myNextion:received:.H65\(e\).H01.H04.H01 {}
:
Anscheinend sind die Elemente am Ende wie folgt zu lesen. H65 steht für Touch Event (siehe dazu auch Böckers Übersicht). Die erste 01 steht anscheinend für page1, der der Button entnommen wurde. 04 bezeichnet die id des Buttons (nicht den objname, sondern id - rechts unter Attribute im Nextion-Editor zu erkennen). Die zweite 01 steht für das Event Niederdrücken, 00 steht für Loslassen.
Auch einen Fehler kann man abfangen, dies geschieht mit
defmode <myname> notify myNextion:received:.H00.H00.H00.H00.H00.H00.H00.H00.H00.H00.H00.* {}
:
Einfacher geht es direkt mit dem Nextion-Editor. Trägt man den folgenden Code eines Buttons in das "Touch Release Event" ein
print "button=" get button.val
so erscheint im Reading "rectext" des Moduls beim Drücken des Tasters "button=1" (bzw 0 bei einem dual-state Button). Man beachte, dass der print-Befehl alleine nicht notwendig in rectext einen Text liefert! Das liegt darin begründet, dass bei print keine Steuerungsbefehle gesendet werden (bei get dagegen schon), die vom Modul aber benötigt werden, um Rückmeldungen des Displays korrekt zu verarbeiten. Im Zweifel muss man den print-Befehl mit get 1
abschließen.
Taster entprellen?
Die Taster auf dem Display können mit Software-Mitteln etwas entprellt werden. Dazu wird bei Touch Release Event(2) folgender Code in zwei Zeilen untereinander eingegeben
delay=500
code_c
Der erste Befehl sorgt dafür, dass nach der Ausführung des Tastendrucks das Diplay für 500ms steht. Eigentlich soll der zweite Befehl die Codeelemente, die in diesen 500ms in den Puffer geschrieben werden, löschen. Das scheint aber nicht zu funktionieren. Auch die Verwendung von comp_stop
oder com_start
brachte keine anderen Ergebnisse. In jedem Fall wird ein weiterer möglicher Tastendruck, der innerhalb dieser 500ms erfolgt, dann erst nach 500ms weitergegeben.
Eventuell muss man also mit einem DOIF das Entprellen durchführen. Bei einem notify kann man das Attribut
attr <myNextion_notify> disabledAfterTrigger <Sekundenbruchteile>
verwenden. Dabei kann man Werte kleiner als 1 Sekunde verwenden, siehe auch diesen Forumsbeitrag.