[MicroPython] Display reagiert zu langsam

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo zusammen,

ich benötige mal wieder euere Hilfe.

Ich habe dieses 7" Display an einen ESP32 angeschlossen und dazu noch einen Potentiometer.
Ich will die Stellung des Potis grafisch darstellen und seine Stellung in Prozent auf dem Display ausgeben. Grafisch sieht das so aus. Nur dass da nicht 5 s steht, sondern je nach dem 0 - 100% und der dicke Strich und der ausgemalte Kreis verändern dann entsprechende die Position(ich nenne das im folgenden mal "Regler").

Da ich ein Hintergrundbild habe, habe ich für die Darstellung des Reglers 25 transparente Bilder erstellt. Das sieht zwar super aus, bedeutet aber auch, dass bei einer Änderung des Reglers nicht einach das aktuelle Bild über das vorherige legen kann. Ich muss bei jeder Regleränderung dafür sorgen, dass alle anderen Bilder ausgebelndet sind und nur das aktuelle eingeblendet wird.
Das funktioniert mit meinem Test-Code aus, aber zu langsam.
Wenn ich am Poti drehe, ändert sich die Prozentanzeige verzögerungsfrei, aber der Regler sieht bei der Änderung aus, als würde er "blinken". Also man erkennt, dass aus- und wieder einblenden.

Meine Frage wäre, kann ich da am Code noch was verbessern, ist das ein Hardwareproblem oder könnte man allgemein anders vorgehen um das Problem zu vermeiden?
Als Workaround habe ich mir überlegt, dass ich den dünnen Strich des Reglers als zusätzliches Bild "unter" die anderen lege und das immer eingeblendet lasse. Aber bevor ich das versuche, würde mich erst interessieren, ob ich da bis jetzt was falsch gemacht habe.

Zur Ansteuerung des Displays habe ich folgenden Code im Internet gefunden:

Code: Alles auswählen

from machine import UART
from os import uname
import time

class Nextion:
    WRITE_ONLY = 0
    WRITE_AND_READ = 1
    DECODE = 1
    RAW = 0
    def __init__(self, tx_pin, rx_pin, baudrate):
        self.uart = UART(1, baudrate, tx=tx_pin, rx=rx_pin)
        self.uart.init(baudrate, bits=8, parity=None, stop=1)
    def cmd(self, cmd, flags=WRITE_AND_READ):
        end_cmd=b'\xFF\xFF\xFF'
        self.uart.write(cmd)
        self.uart.write(end_cmd)
        if(flags == 1):
            time.sleep_ms(100)
            return self.uart.read()
    def sleep(self, state):
        self.cmd("sleep=" + str(state))
    def page(self, page):
        self.cmd("page {}".format(page))
    def reset(self):
        self.cmd("rest")
    def brightness(self, brightness):
        self.cmd("dim=" + str(brightness))
    def read(self, flags=0):
        if(flags == 0):
            return self.uart.read()
        else:
            output = self.uart.read()
            if(not output is None):
                #output.replace("\xFF\xFF\xFF", "")
                output = bytearray(str(output)).decode("ascii")
                return output
            else:
                return None

Und mein Test-Code sieht so aus:

Code: Alles auswählen

from machine import Pin, ADC
from time import sleep
from Nextion import Nextion

TX_PIN = 16
RX_PIN = 17


def initial_display(display):
    for picture in range(1, 26):
        display.cmd("vis speed{},0".format(picture), flags=0)


def translate_to_percent(value):
    return 100 - (100 * value // 4095)


def translate_to_picture_number(value):
    return 25 * value // 100


def clear_display(display, number):
    display.cmd("vis speed{},0".format(number), flags=0)


def update_display(display, number):
    display.cmd('percent.txt="{}"'.format(number), flags=0)
    display.cmd("vis speed{},1".format(translate_to_picture_number(number), flags=0))


def main():
    potentiometer = ADC(Pin(39))
    potentiometer.atten(potentiometer.ATTN_11DB)
    display = Nextion(TX_PIN, RX_PIN, 9600)
    display.brightness(100)
    initial_display(display)
    sleep(0.1)
    percent = translate_to_percent(potentiometer.read())
    update_display(display, percent)
    old_percent = percent
    while True:
        percent = translate_to_percent(potentiometer.read())
        if not old_percent == percent:
            clear_display(display, translate_to_picture_number(old_percent))
            update_display(display, percent)
            old_percent = percent
        sleep(0.01)


if __name__ == "__main__":
    main()

Wenn ich das 'sleep' aus der Dauerschleife entferne, ändert das am Blink-Verhalten nichts, aber die angezeigten Werte schwanken immer ganz leicht.
Die verwendete Nextion-Befehle sind hier auf der Nextion Seite zu finden.

Vielen Dank vorab.

Viele Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Die Dokumentation von ``vis`` warnt davor ja explizit: „can cause ripping and flickering“.

Kann man mehr als ein command auf einmal senden? Dann würde ich das mal versuchen, damit zwischen verstecken des einen Bildes und Anzeigen des anderen keine Pause durch die serielle Kommunikation entsteht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo und danke für deine Antwort.

Ich habe leider keine andere Möglichkeit wie 'vis' gefunden.

Mehrere Kommandos auf einmal senden habe ich so versucht:
In der Nextion.py habe ich die 'cmd'-Funkion so abgeändert:

Code: Alles auswählen

    def cmd(self, *commands, flags=WRITE_AND_READ):
        end_cmd=b'\xFF\xFF\xFF'
        for command in commands:
            self.uart.write(command)
        self.uart.write(end_cmd)
        if(flags == 1):
            time.sleep_ms(100)
            return self.uart.read()[(code]

und in der 'main.py' rufe ich dass dann so auf:
[code]def update_display(display, number, old_number):
    display.cmd('percent.txt="{}"'.format(number), flags=0)
    display.cmd(
        "vis speed{},0".format(translate_to_picture_number(old_number)),
        "vis speed{},1".format(translate_to_picture_number(number)),
        flags=0,
    )
Die Anzeige des Prozenwerts funktioniert noch, aber jetzt wird kein Regler mehr angezeigt. Hast du das Vorgehen so gemeint? Zwei Kommandos und erst dann die Zeichen, dass das Kommandoende erkennt wird.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich bezweifele, dass du da mit Programmierung viel erreichst. Dafuer ist das Nextion-System nicht gemacht. Wenn du sowas willst, ist ein Pi Zero + Kivy oder so die Antwort.
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

danke für deine Antwort.
Hm das wäre schade, dass soll das Display für die Drehschweißmaschine werden und da würde mir ein Pi nicht so gefallen.
Das Nextion habe ich gewählt, weil ich da die ganzen Bilder drauf speichern kann und dass dann etwas entkoppelt vom ESP ist. Dass das so "langsam" ist habe ich nicht gewusst, bzw. darüber habe ich mir gar keinen Kopf gemacht.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst im Zweifel da noch so einiges erreichen, indem du deinen Ansatz ueberdenkst. Also eben eine andere Visualisierung waehlst. Aber nur weil du das vis-Kommando anders schickst, macht das Display das nicht ploetzlich schneller.
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Okay, dann überlege ich mal, ob mir noch etwas anderes, schönes einfällt.
Sonst muss ich halt so damit leben. An sich gefällt mir der Aufbau gerade richtig gut.

Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Die Kommandos müssen ja irgendwie getrennt werden und wenn man die nicht per serieller Schnittstelle schickt, dann schreibt man ja Programme wie man das üblicherweise macht: eine Anweisung pro Zeile. Also hätte ich versucht ob man da mit einem "\n" oder "\r\n" zwischen den Kommandos mehr als eines auf einmal übertragen kann. __deets__ schreibt ja, dass dadurch das Display nicht schneller wird, aber eventuell bringt das was weil in der Doku steht, dass die Kommandos ausgeführt werden sobald die drei 0xff-Bytes eintreffen. Das heisst wenn man zwei ``vis``-Kommandos einzeln schickt wird erst das erste übertragen, dann ausgeführt, und dann das zweite übertragen, dann ausgeführt. Man könnte also die Zeit für die serielle Übertragung zwischen der Ausführung der beiden Kommandos damit beseitigen. Also wenn das geht, mehr als ein Kommando pro Übertragung zu schicken.

Ansonsten habe ich da auch so Sachen wie "element_id.pic=…" gesehen wo man anscheinend mindestens mal eine numerische ID von einem Bild zuweisen kann.

Dann ist noch die Frage wie variabel der Hintergrund ist, also ob Du passend zum Hintergrund nicht-transparente Bilder verwenden kannst. Pre-composed sozusagen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für die Idee.
Ich habe dann als Kommando sowas:

Code: Alles auswählen

command = "vis speed{},0\r\nvis speed{},1".format(translate_to_picture_number(old_number), translate_to_picture_number(number))
abgeschickt, aber da passiert leider nichts. Auch ein einzelnes '\n' , Komma, Semikolon, Leerzeichen, ein oder zwei &, ein oder zwei | haben nichts bewirkt. Ich habe da zusätzlich einfach mal mit den Zeichen ausprobiert. Von & und | habe ich auch nichts erwartet, die sind laut Doku ja schon anderweitig reserviert.
Ansonsten habe ich da auch so Sachen wie "element_id.pic=…" gesehen wo man anscheinend mindestens mal eine numerische ID von einem Bild zuweisen kann.
Wo hast du das gesehen, in der von mir verlinkten Doku? Wenn ich die Seite nach "element" durchsuche, erhalte ich kein Treffer.
Dann ist noch die Frage wie variabel der Hintergrund ist, also ob Du passend zum Hintergrund nicht-transparente Bilder verwenden kannst. Pre-composed sozusagen.
Das habe ich mir auch schon als Alternative überlegt. Der Hintergrund ist fix. Da müsste ich nur dafür sorgen, dass der Text, also der Prozentwert, auch immer wieder "über" dem Bild liegt.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13107
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Auf dieser Seite https://nextion.tech/editor_guide/ nach „the picture component“ gesucht, da steht in dem Absatz ``p0.pic=3``. An anderer Stelle im Netz habe ich das in Code gesehen wo der Wert dynamisch berechnet wird, kann aber nicht mehr sagen wo. Aber die Attribute von den Komponenten sollten ja eigentlich änderbar sein.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Dennis89
User
Beiträge: 1155
Registriert: Freitag 11. Dezember 2020, 15:13

Im Nextion-Editor habe ich einen Art "Speicher". Wenn ich Bilder auf meinem Display anzeigen will, dann müssen die in diesem Speicher sein. Dort wird jedem Bild eine ID zugewiesen.
Jetzt kann ich im Editor entweder die gewünschten Bilder an die gewünschte Position schieben, den Name und die Größe ändern und so wird es dann auf dem Display angezeigt.
Ich kann das aber auch sein lassen und die Bilder aus dem Speicher mit Code positionieren:

Code: Alles auswählen

pic 10,10,1
Zeigt mir ID 1 an der Position x=10, y=10 an.

Dann ist dass da und ich habe nach meinem Verständnis wieder den gleichen Ausgangszustand und muss sie wieder ein- und ausblenden.

Möglich dass ich aber auch nicht verstehe auf was du hinaus willst.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Ohne jetzt im Detail die Hardware zu kennen:
Was ist, wenn du versuchst DoubleBuffering zu imitieren? Wenn du das neue Bild erst anzeigen lässt (an der Position des alten Bildes) und dann erst das alte Bild entfernst?
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

@sparrow: nextion displays funktionieren so nicht. Das sind „smarte“ Displays, die man mit einem Editor grafisch gestaltet, und veränderliche Werte oder auch Ansichten einfach per uart umschaltet. Einen derartig tiefen Eingriff hat man da gar nicht.
Antworten