Netzteil-Display mit Nextion-HMI #3

Hinterlasse einen Kommentar

16.07.2017 von plaintron

Wie angekündigt gehe ich heute näher auf die Zeigerdarstellung auf dem Nextion-Display ein.

Zunächst gibt es noch ein paar Optimierungen, um den Code zu beschleunigen und den Arduino zu entlasten. Auf dem Display-Modul steht immerhin ein leistungsstarker STM32 mit 48MHz zur Verfügung, der dem ATmega so viel Arbeit wie möglich abnehmen soll. Außerdem sollte die Kommunikation zwischen Arduino und Display so gering wie möglich gehalten werden.

Erste Verbesserung: Der Zeiger wird nur neu geschrieben, wenn sich die Eingangsspannung auch tatsächlich geändert hat. Dazu verwende ich zwei Integer-Variablen, input und last_input. In der loop wird alle 25ms eine Messung durchgeführt und die Zeiger-Routinen nur aufgerufen, wenn es dort Neuigkeiten gibt. Der aktuelle Wert wird dann wieder in last_input gespeichert und bei der nächsten Runde zum Vergleich verwendet.

void loop() {
  input = analogRead(A1);
  if(input != last_input){ 
    last_input = input; 
    set_meters(); 
  }
  delay(25);
}

Die Funktion set_meters ist auch neu dazugekommen und soll sich um Zeiger und Digitalanzeigen kümmern.

void set_meters(){ 
 a = ((float)input-512.0) * deg;
 volt = (int)((float)input * 2.93); 
 x = len * sin(a); 
 y = len * cos(a); 
 set_vars(); 
}

Nun sollen möglichst viele Berechnungen auf dem STM32 stattfinden. Dort gibt es aber nur eingeschränkte Programmiermöglichkeiten. Also lasse ich die Trigonometrie im Arduino erledigen und berechne den Rest der notwendigen Werte im Display. Dort läuft eine Schleife, die ständig alle notwendigen Werte ermittelt und an den entsprechenden Stellen der Anzeige Werte darstellt.

Nur die berechneten Werte für x und y und ein Spannungswert werden an das Display übertragen. Dort lege ich die entsprechenden Variablen an. Zur komfortablen Übertragung habe ich eine Funktion nx() hinzugefügt, die sich um die Kommunikation kümmert.

void nx(int len){ 
 Serial1.write(cmd, len); 
 Serial1.write(0xff);
 Serial1.write(0xff);
 Serial1.write(0xff);
}

Die übertragenen Variablen sind x, y und volt (0-3000).

void set_vars(){
 nx(sprintf(cmd, "x.val=%d", x)); 
 nx(sprintf(cmd, "y.val=%d", y)); 
 nx(sprintf(cmd, "volt.val=%d", volt)); 
}

Auf dem Display werden also nur x, y und volt gesetzt und der Rest dort berechnet. Zu beachten ist bei der Programmierung im Nextion-Editor, dass Integer-Variablen immer mit angehängtem „.val“ und Textvariablen mit „.txt“ angesprochen werden. Das ist etwas ungewohnt, habe ich festgestellt. Der Compiler mahnt das aber sofort an, wenn es vergessen wurde.

Das war es an Code auf dem Arduino. Nun schauen wir uns an, was im Nextion-Editor an Skript notwendig ist.

Hier habe ich zunächst einige Variablen angelegt. Die Koordinaten x und y sowie volt habe ich bereits erläutert. Davon gibt es jeweils eine Kopie, auf der gearbeitet wird, während die Originale vom Arduino beschrieben werden. Das ist notwendig, damit die Schleife des Displays nicht während der Berechnungen neue Werte untergeschoben bekommt. Das wären also xc, yc und last_volt. Auch hier passiert wieder nur etwas, wenn es Änderungen gab. Der Wert volt wird bei jedem Schleifendurchgang mit last_volt verglichen.

Schleifen heißen bei Nextion „timer“ und können nicht schneller als 50ms laufen. Das war mir zu wenig, deshalb habe ich mit einem Trick für mehr Speed gesorgt. Die meisten Display-Elemente haben Events für push und release. Also habe ich ein unsichtbares Element auf den Screen gelegt („m0“) und mein Skript in beide Events kopiert. Der Timer klickt nun alle 50ms dieses Element an und lässt es wieder los:

click m0,1
click m0,0

Diese Verdoppelung macht einen sichtbaren Unterschied. Bei einer Wiederholrate von 50ms ist noch ein leichtes Flimmern an Zeiger und Zahlen zu erkennen, mit dem Event-Trick nicht.

Der Skriptcode im Event von m0 sieht nun so aus:

if(volt.val!=last_volt.val)
{
 picq left.val,top.val,width.val,height.val,0
 d0.val=volt.val/1000*10
 d1.val=volt.val/100*10
 d2.val=volt.val/10*10
 p0.pic=volt.val/1000+6
 p1.pic=volt.val/100-d0.val+6
 p2.pic=17
 p3.pic=volt.val/10-d1.val+6
 p4.pic=volt.val-d2.val+6
 doevents
 x0.val=94*x.val/y.val+159
 xc.val=x.val+159
 yc.val=230-y.val
 width.val=x0.val-xc.val
 if(width.val<0)
 {
 width.val*=-1
 }
 width.val+=4
 height.val=y0.val-yc.val+4
 top.val=yc.val-3
 left.val=xc.val-2
 if(x0.val<xc.val)
 {
 left.val=x0.val-2
 }
 line xc.val,yc.val,x0.val+2,y0.val,35921
 line xc.val,yc.val,x0.val-2,y0.val,35921
 line xc.val,yc.val,x0.val,y0.val,0
 last_volt.val=volt.val
}

Sobald sich der Spannungswert ändert, wird ein Rechteck mit dem Hintergrundbild gemalt (picq), um den alten Zeiger zu löschen. Nun berechne ich die einzelnen Dezimalstellen der digitalen Spannungsanzeige. Hier könnte ich das Text-Element von Nextion verwenden. Das ist aber recht langsam und führt bei Bewegung des Zeigers zu Flackern. Deshalb habe ich 10 Ziffernbilder hochgeladen, die entsprechend des Spannungswertes angezeigt werden. Auch der Dezimalpunkt muss erneuert werden, denn er könnte ja gelöscht worden sein. Dieser Vorgang scheint wesentlich schneller abzulaufen als die Bildberechnung eines Strings, denn das Flackern ist fast nicht mehr sichtbar.

Nachdem die Zahlenbilder gewählt wurden, muss „doevents“ aufgerufen werden, damit diese auch tatsächlich auf dem Screen erscheinen. Anderenfalls würde dieser Vorgang erst am Ende des Makros stattfinden und den Zeiger überschreiben.

Nun werden die Koordinaten des Zeigers berechnet und die Werte für die nächste Löschung gespeichert. Anschließend werden drei Linien auf den Schirm geschrieben, die einen Zeiger mit weichen Kanten und leichter Verjüngung zur Spitze hin bilden. Das geht alles enorm schnell und der Arduino hat kaum noch Arbeit damit.

Und so sieht das Ergebnis nun aus. Der Zeiger läuft absolut flüssig und super schnell.

Die nächsten Artikel widmen sich dann den weiteren Pages meiner Display-Anwendung.

Links:

 

 

 

Advertisements

Kommentieren

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

Blogverzeichnis - Bloggerei.de
%d Bloggern gefällt das: