Anhang B - LVGL-Fonts selbst erstellen

Aus Micropython
Zur Navigation springen Zur Suche springen

Binäre LVGL-Fonts auf dem M5Stack Tab5[Bearbeiten | Quelltext bearbeiten]

Überblick[Bearbeiten | Quelltext bearbeiten]

Auf dem M5Stack Tab5 können eigene TrueType-Fonts (TTF) als binäre LVGL-Fonts verwendet werden.

UIFlow2 erzeugt für eingebundene Fonts eine BIN-Datei und lädt diese auf das Dateisystem des Tab5. Die Datei kann anschließend mit

lv.binfont_create()

geladen und einem LVGL-Widget als Font zugewiesen werden.

Bei den bisherigen Versuchen mit UIFlow2 V2.5.3 und der zugehörigen MicroPython-/LVGL-Firmware zeigte sich allerdings ein noch nicht vollständig geklärtes Verhalten beim manuellen Erzeugen und Übertragen solcher BIN-Dateien.

Beispiel: DSEG7Classic-Regular[Bearbeiten | Quelltext bearbeiten]

Für die Anzeige von Messwerten wurde der 7-Segment-Font

DSEG7Classic-Regular.ttf

verwendet.

In UIFlow2 wurde daraus ein Font mit einer Größe von 70 Pixeln erzeugt.

Die von UIFlow2 auf dem Tab5 angelegte Datei befand sich unter:

/flash/res/font/DSEG7Classic-Regular-70px.bin

Aus LVGL heraus wird die Datei über das von M5Stack eingerichtete Laufwerk S: angesprochen:

S:/flash/res/font/DSEG7Classic-Regular-70px.bin

Initialisierung[Bearbeiten | Quelltext bearbeiten]

Vor dem Laden eines binären Fonts muss die M5Stack-/LVGL-Umgebung initialisiert sein.

Beispiel:

import M5
from M5 import *
import m5ui
import lvgl as lv

M5.begin()
Widgets.setRotation(3)
m5ui.init()

font = lv.binfont_create(
    "S:/flash/res/font/DSEG7Classic-Regular-70px.bin"
)

print(font)

Bei erfolgreichem Laden wird beispielsweise ausgegeben:

struct lv_font_t

Wichtig:

Ein Aufruf von

lv.binfont_create()

vor der Initialisierung durch

m5ui.init()

funktionierte beim Tab5 nicht zuverlässig. Insbesondere war der von M5Stack verwendete LVGL-Dateisystemzugriff über S: vorher nicht vollständig verfügbar.

Verwendung des Fonts[Bearbeiten | Quelltext bearbeiten]

Der geladene Font kann beispielsweise einem M5UI-Label übergeben werden:

label = m5ui.M5Label(
    "21.23456",
    x=23,
    y=150,
    text_c=0x000000,
    bg_c=0xffffff,
    bg_opa=0,
    font=font,
    parent=page
)

Es empfiehlt sich, die Referenz auf den geladenen Font während der gesamten Lebensdauer der Widgets zu erhalten.

Beispiel:

DSEG7Classic_Regular_70px = None

def setup():
    global DSEG7Classic_Regular_70px

    DSEG7Classic_Regular_70px = lv.binfont_create(
        "S:/flash/res/font/DSEG7Classic-Regular-70px.bin"
    )

Dadurch bleibt die Python-Referenz auf das Fontobjekt erhalten.

Erzeugen des BIN-Fonts unter Windows[Bearbeiten | Quelltext bearbeiten]

Zur Konvertierung wurde lv_font_conv verwendet.

Voraussetzungen:

  • Node.js
  • npm
  • lv_font_conv

Installation von lv_font_conv:

npm.cmd install -g lv_font_conv

Die Installation kann überprüft werden mit:

lv_font_conv.cmd --help

Ermitteltes UIFlow2-Format[Bearbeiten | Quelltext bearbeiten]

Durch Vergleich mit der von UIFlow2 erzeugten BIN-Datei wurden für den getesteten Font folgende Einstellungen ermittelt:

  • Fontgröße: 70 px
  • Farbtiefe: 1 Bit pro Pixel
  • Format: LVGL BIN
  • keine Kompression
  • verwendete Zeichen: 0–9, Punkt und Minuszeichen

Der entsprechende Aufruf lautet:

lv_font_conv.cmd `
  --font "C:\Users\User\LVGL-Fonts\DSEG7Classic-Regular.ttf" `
  --size 70 `
  --bpp 1 `
  --format bin `
  --no-compress `
  --symbols "0123456789.-" `
  -o DSEG7Classic-Regular-70px.bin

Der erzeugte Font hatte eine Größe von:

3612 Byte

Vergleich mit der UIFlow2-Datei[Bearbeiten | Quelltext bearbeiten]

Die selbst erzeugte Datei wurde mit der von UIFlow2 erzeugten Datei verglichen.

Unter Windows wurde dazu SHA-256 verwendet:

Get-FileHash ".\DSEG7Classic-Regular-70px-1bpp.bin" -Algorithm SHA256

Get-FileHash ".\Von UIFlow2\DSEG7Classic-Regular-70px.bin" -Algorithm SHA256

Für beide Dateien wurde derselbe SHA-256-Wert ermittelt:

BD7AF692C3C2B022403977B914A73F68748035D9D1B6633F93B944C3C14743AE

Damit waren die beiden Dateien auf dem PC bytegenau identisch.

Vergleich auf dem Tab5[Bearbeiten | Quelltext bearbeiten]

Zusätzlich wurden die Dateien nach dem Übertragen auf den Tab5 mit MicroPython verglichen.

Beispiel:

file1 = "/flash/res/font/DSEG7Classic-Regular-70px.bin"
file2 = "/flash/res/font/testfont.bin"

with open(file1, "rb") as f1, open(file2, "rb") as f2:
    data1 = f1.read()
    data2 = f2.read()

print("Datei 1:", len(data1), "Bytes")
print("Datei 2:", len(data2), "Bytes")
print("Identisch:", data1 == data2)

Auch auf dem Tab5 wurden die Dateien als identisch erkannt.

Beobachtetes Problem[Bearbeiten | Quelltext bearbeiten]

Trotz der nachgewiesenen Bytegleichheit trat bei den Versuchen ein ungewöhnliches Verhalten auf.

Eine manuell erzeugte und übertragene BIN-Datei konnte zunächst mit

lv.binfont_create()

geladen werden. Beim anschließenden Darstellen der damit erzeugten Labels kam es jedoch zu einem nativen Absturz des ESP32-P4.

Typisch war:

  • Bildschirmhintergrund wurde dargestellt.
  • Widgets waren teilweise kurz sichtbar.
  • Anschließend trat ein Guru Meditation Error auf.
  • Gemeldet wurde unter anderem ein Load access fault.

Es handelte sich damit nicht um eine normale MicroPython-Exception, sondern um einen Absturz innerhalb der nativen Firmware bzw. LVGL-Laufzeit.

Der Fehler trat sowohl beim Start des Programms aus Thonny 5.0.0 als auch beim Start aus der UIFlow2-IDE auf.

Damit konnte Thonny als unmittelbare Ursache des Problems ausgeschlossen werden.

Verhalten der von UIFlow2 übertragenen Datei[Bearbeiten | Quelltext bearbeiten]

Wurde der Font von UIFlow2 selbst als Projektressource auf den Tab5 übertragen, funktionierte der Font.

Anschließend funktionierte das Programm mit dieser Datei auch beim Start aus Thonny.

Ein weiterer Versuch ergab:

  1. Die funktionierende UIFlow2-Fontdatei wurde vom Tab5 auf den PC kopiert.
  2. Die Datei auf dem Tab5 wurde umbenannt.
  3. Die zuvor auf den PC kopierte Datei wurde wieder auf den Tab5 übertragen.
  4. Der Font funktionierte weiterhin.

Auch eine Umbenennung, beispielsweise von

DSEG7Classic-Regular-70px.bin

in

__DSEG7Classic-Regular-70px.bin

hatte keinen negativen Einfluss.

Der Dateiname allein ist daher nicht die Ursache.

Derzeitiger Erkenntnisstand[Bearbeiten | Quelltext bearbeiten]

Folgende Punkte gelten aufgrund der bisherigen Versuche als gesichert:

  • Binäre LVGL-Fonts funktionieren grundsätzlich auf dem M5Stack Tab5.
  • Die Fonts können mit lv.binfont_create() geladen werden.
  • Für den Zugriff über S: muss die M5Stack-/LVGL-Umgebung zuvor initialisiert werden.
  • UIFlow2 erzeugte für den getesteten 70-px-Font eine unkomprimierte 1-bpp-BIN-Datei.
  • Diese Datei lässt sich mit lv_font_conv bytegenau reproduzieren.
  • Die Bytegleichheit wurde sowohl über SHA-256 auf dem PC als auch nach dem Übertragen auf dem Tab5 überprüft.
  • Der Programmstart über Thonny ist nicht grundsätzlich für den beobachteten Absturz verantwortlich.
  • Der Dateiname ist nicht für das unterschiedliche Verhalten verantwortlich.
  • Eine von UIFlow2 übertragene und funktionierende Datei kann auf den PC kopiert und anschließend wieder auf den Tab5 übertragen werden und funktioniert danach weiterhin.

Noch ungeklärt ist:

Warum führte die zunächst manuell erzeugte bzw. übertragene Datei trotz nachgewiesener Bytegleichheit zu einem nativen LVGL-/Firmware-Absturz, während die von UIFlow2 bereitgestellte Datei funktionierte?

Die bisherigen Ergebnisse erscheinen widersprüchlich. Daher sollte derzeit nicht behauptet werden, dass die Ursache im BIN-Format, im Dateisystem oder im Übertragungsprogramm liegt.

Praktische Empfehlung[Bearbeiten | Quelltext bearbeiten]

Bis die Ursache genauer untersucht wurde, sollte für produktive Programme auf dem Tab5 die von UIFlow2 erzeugte und übertragene Fontdatei verwendet werden.

Eine funktionierende Fontdatei kann anschließend gesichert und offenbar auch manuell wieder auf den Tab5 übertragen werden.

Für eigene Experimente kann das von UIFlow2 verwendete BIN-Format mit folgendem Schema reproduziert werden:

lv_font_conv.cmd `
  --font "FONTDATEI.ttf" `
  --size 70 `
  --bpp 1 `
  --format bin `
  --no-compress `
  --symbols "0123456789.-" `
  -o FONTDATEI-70px.bin

Die Größe und der Zeichensatz müssen für den jeweiligen Anwendungsfall angepasst werden.

Offene Untersuchung[Bearbeiten | Quelltext bearbeiten]

Für eine spätere Untersuchung sollten insbesondere folgende Punkte betrachtet werden:

  • genauer Übertragungsweg der Fontdateien auf den Tab5
  • Verhalten des LVGL-Dateisystemtreibers S:
  • Lebensdauer der durch lv.binfont_create() erzeugten Fontstrukturen
  • Verhalten des Binfont-Decoders der verwendeten LVGL-Version
  • Unterschiede zwischen UIFlow2-Ressourcenverwaltung und manuell übertragenen Dateien
  • Reproduzierbarkeit des Fehlers nach vollständigem Löschen und Neuerzeugen der Fontdatei

Da inzwischen eine funktionierende Lösung für die praktische Anwendung vorliegt, wurde die weitere Fehlersuche zunächst zurückgestellt.