|
[ Home ] [ Seitenende ]
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Micropython mit ESP32, Teil 1 In der Lektion „Micropython
mit ESP32“, Teil
5 „Das Display”
geht es um die Bedienung, das Aufspielen des OLED-Treibers
in Form des „Micropython“-Programms „ssd1306.py“, (Zum Vergrößern bitte
auf das Bild klicken!) die Inbetriebnahme mittels des kleinen „Micropython“-Programms „oled.py“ und die
Programmierung des kleinen OLED‑Displays mit einer fünfzeiligen Textanzeige (siehe „Micropython“-Programms „oled_demo.py“): (Zum Vergrößern bitte
auf das Bild klicken!) Bei dem Sourcecode (= Quelltext) im
obenstehenden Bild mit der fünfzeiligen Textanzeige (inkl. Rechteckrahmen
„Micropython“) fällt sofort auf, dass jede im kleinen OLED-Display
anzuzeigende Textzeile einzeln bezüglich Zeile „line“
und Spalte „pos“ positioniert und textlich
programmiert wird. Hinzu kommt noch, dass zur späteren Darstellung einer
jeden einzelnen Textzeile die Funktion
„text_line()“ zwecks Auffüllens des
Pixelspeichers bemüht wird. Denn wie im YouTube-Video erklärt, erfolgt ja die Ausgabe/Anzeige
auf das Display erst mit dem Aufruf des Statements
„oled.show()“. Okay, bei dem obenstehenden „Micropython“-Programms „oled_demo.py“ geht
es ja nur darum, zu zeigen, wie sich auch Text auf dem kleinen OLED-Display
darstellen lässt. Aber nichts desto trotz, möchte ich auf Dauer, d.h. beim
Programmieren weiterer „Micropython“-Programme
nicht jede Fehlermeldung, nicht jeden Bedienungshinweis usw. einzeln
programmieren müssen. Deshalb machen wir uns an die Arbeit und „pimpen“ (= veredeln) das kleine Programm etwas. Mit dem
Ziel, dass wir später nur einen einzigen Textstring programmieren, der dann
automatisch auf die fünf Textzeilen umgebrochen und auf dem Display angezeigt
wird. Jede Schrift bzw. jeder Text
in Form von zusammengesetzen Buchstaben und/oder Ziffern hat eine bestimmte
Größe (= Schriftgrad bei Microsoft Word, Schriftgröße bei Writer von
LibreOffice). Aber um welche Schriftgröße handelt es bei dem kleinen
OLED-Display vom „HELTEC WiFi kit
32“ nebst dem „ssd1306“-Display-Treiber? Finden wir es heraus! Wie man im obenstehenden Bild im roten Kasten
sehen kann, verfügt das Display über die Pixel-/Bildpunktgröße von 128 x 64 Pixel. Und zwar horizontal 128 Pixel und vertikal 64 Pixel. Mit einer Buchstabenbreite
von 8 Pixel/Buchstabe lassen
sich also pro Textzeile 128 Pixel / 8 Pixel / Buchstabe = 16 Buchstabe(n) je Textzeile horizontal
darstellen! Mit einer Buchstabenhöhe
von 14 Pixel/Textzeile
lassen sich vertikal 64 Pixel / 14 Pixel / ?
Textzeile = 4,571 Textzeilen ≈ 5 Textzeilen vertikal darstellen! Aber stimmt das wirklich? 5
Textzeilen vertikal, wo es doch nur ganze und eben nicht ≈ 4,6
„krumme“ Textzeilen gibt, oder? Was stimmt da nicht? Was wir also als Ergebnis
brauchen, ist ein ganzzahliger Quotient (= Bruch, Verhältnis) wie z.B.
60 vertikale Pixel / 12 vertikale Pixel / Textzeile = 5 Textzeilen vertikal! Da wir es bei dem
OLED-Display aber vertikal mit insgesamt 64 Pixel zu tun haben, verbleibt bei
60 vertikalen Pixel mit 5 vertikalen Textzeilen ein Rest von = 4 vertikalen Pixeln! Weil es aber zwischen den n =
5 vertikalen Textzeilen zwecks besserer Lesbarkeit jeweils noch = ( n - 1) einpixelige Leerzeilen
gibt, haben wir es mit ( n – 1 ) = ( 5 – 1 ) = 4 vertikalen, einpixeligen Leerzeilen zu tun. Für die Probe folgt
dementsprechend: 5 Textzeilen * 12
Pixel/Textzeile + 4 Leerzeilen * 1 Pixel/Leerzeile = 60 Pixel (= 5 Textzeilen) + 4 Pixel (= 4 einpixelige
Leerzeilen) = 64 Pixel in der
Vertikalen! Hier noch einmal die
Zusammenfassung: · 16 Buchstaben
je Textzeile à 8 Pixel Buchstabenbreite · 5
Textzeilen mit je 16 Buchstaben à 12 Pixel Buchstabenhöhe · 4
Leerzeilen à 1 Pixel pro Leerzeile als Abstandszeile Wenn wir jetzt nochmals einen
Blick auf das „Micropython“-Programms „oled_demo.py“ werfen, dann fallen in der Funktion „text_line()“ zwei
scheinbare Ungereimtheiten auf (siehe rote Kreise): (Zum Vergrößern bitte
auf das Bild klicken!) Bei dem Statement
„x = 10 * pos“ könnte z.B. meinen,
dass es sich bei dem Wert „10“ um die Buchstabenbreite handelt,
obwohl das rechnerisch bezüglich der Pixelzahl von 128 Pixel in horizontaler Richtung nicht stimmten
kann: 16 Buchstaben * 10 Pixel Buchstabenbreite = 160 Pixel insgesamt für
jede Textzeile! In Wirklichkeit haben die 16 Buchstaben je
Textzeile aber nur eine Buchstabenbreite von 8 Pixel/Buchstabe, was zusammen 16 * 8
= 128 Pixel in horizontaler
Richtung
ergibt! Bei dem Statement
„y = line
* 11“
könnte z.B. meinen, dass es sich bei dem Wert
„11“ um die Zeilenhöhe
handelt (= Buchstabenhöhe + einzeilige Leerzeile), obwohl das
rechnerisch bezüglich der Pixelzahl von 64 Pixel in vertikaler Richtung nicht stimmten
kann: 5 Textzeilen * 11 Pixel Zeilenhöhe = 55 Pixel insgesamt! Was also hat es mit diesen Angaben für die x-
und y-Richtung zu tun, wozu werden diese gebraucht? Wenn man sich das weiter
entwickelte „Micropython“-Programm „oled_demo-01-01.py“ anschaut, dann wird deutlich, wofür die beiden x- und y-Angaben nützlich sind: (Zum Vergrößern bitte
auf das Bild klicken!) Diesbezüglich haben die beiden „offset“-Angaben folgende Bewandnis: · Das Statement „x_offset = 10“ führt zu einer Verschiebung aller Textzeilen in horizontaler
Richtung nach rechts! · Das Statement „y_offset = 11“ führt zu einer Verschiebung aller Textzeilen in vertikaler Richtung mit
der Folge einer Stauchung der
Textzeilen für Werte <
11 an den oberen Rand des Displays und zu einer Dehnung für Werte > 11 an den unteren
Rand des Displays. Die beiden „offset“-Werte auf null zu setzen, macht
mathematisch wenig Sinn, da die Multiplikation mit dem „pos“-
oder „line“-Wert das Ergebnis null liefert. Wenn man, wie im „Micropython“-Programm „oled_demo-01-02.py“ zu sehen, den „offset“-Wert für das Statement „y_offset = 0“ auf null setzt, dann
werden alle anzuzeigenden Textzeilen in der ersten Zeile mit dem Zeilen-Index
0 übereinander angezeigt, sodass man einzelne Textstrings nicht
mehr lesen kann: (Zum Vergrößern bitte
auf das Bild klicken!) Wenn man aber, wie im „Micropython“-Programm „oled_demo-01-03.py“ gezeigt, die einzeln übereinander angezeigten Textstrings
so zur Anzeige bringen, dass man diese in Ruhe lesen kann, dann muss man
zwischen der Anzeige zweier Textstrings eine entsprechende Pause einlegen, bevor
der nächste Textstring angezeigt wird: (Zum Vergrößern bitte
auf das Bild klicken!) Während also das Statement „oled.fill(0)“ dafür sorgt, dass der Bildspeicher auf null gesetzt, d.h. gelöscht wird, sorgt das
nächste Statement „text_line("Hallo!
Ich bin",3,8)“ mittels des Funktionsaufrufs „text_line(text, line, pos = 0)“ dafür, dass der
Bildspeicher mit neuem Content (= Inhalt) gefüllt wird, wenn das
entsprechende Statement „oled.text(text,x,y)“ aufgerufen wird! Dabei wird der Bildspeicher aber erst ausgelesen
und auf dem Display angezeigt, wenn das Statement
„oled.show()“ aufgerufen wird. Demzufolge gibt es zwischen dem Befüllen des
Bildspeichers mit neuem Content und dem Auslesen und Anzeigen des
Bildspeichers auf dem Display eine strenge „Arbeitsteilung“ im Sinne der
einzuhaltenden Reihenfolge (= Algorithmus)
Wenn man sich den Sourcecode vom „Micropython“-Programm „oled_demo-01-03.py“ anschaut, dann sieht man, dass sich die vier im
obenstehenden Kasten befindlichen Statements insgesamt fünfmal
wiederholen und sich nur hinsichtlich der anzuzeigenden Textstrings wie z.B. beim Statement
„text_line("Hallo!
Ich bin",3,8)“
unterscheiden: (Zum Vergrößern bitte
auf das Bild klicken!) Immer dann, wenn sich Dinge mehrfach
wiederholen und sich praktisch nur in einem Detail, hier also der
anzuzeigende Textstring, voneinander unterscheiden, bietet es sich an, eine „while“- oder „for“-Schleife zu programmieren
(siehe „Micropython“-Programm „oled_demo-01-04.py“: (Zum Vergrößern bitte
auf das Bild klicken!) Wie man im obenstehenden Ausschnitt des
Quellkodes sieht, ändert sich in der „while“-Schleife nur der Inhalt des jeweiligen Textstrings im Statement „text_line(text_Str[i],3,8)“,
während alles andere unverändert bleibt. Und, da sich der anzuzeigende Inhalt
im Textstrings mit jeder Ausgabe/Anzeige auf dem Display ändert bzw. ändern
soll, müssen wir für die Textanzeige und die Textstrings noch eine entsprechende „Anzeige“-Liste namens „text_Str[ ]“ in Form einer
einfachen, d.h. eindimensionalen, einspaltigen Tabelle programmieren. Da wir später auch noch die
anzuzeigenden Inhalte dynamisch ändern/verändern wollen, kommt ein Tabelle in
Form eines Arrays zum
Einsatz. Und zwar vom Typ „list“, d.h. umgangssprachlich „Liste“ im Sinne
einer Aufstellung, Aufzählung oder einer Spalte einer Tabelle: (Zum Vergrößern bitte
auf das Bild klicken!)
Da sich mit dem mehrzeiligen, 5 x 16 großen OLED-Display nicht nur fünf Textzeilen zu je 16 Buchstaben und/oder Ziffern darstellen lässt, sondern z.B. auch Linien,
Dreiecke, Rechtecke usw. darstellen lassen, kann man die Aufmerksamkeit des
Anwenders oder Bedieners, die unser kleines Programm „bedienen“, auch dadurch
erhöhen, indem man z.B. eine Textzeile
mit einem Rahmen umhüllt und das
Ganze dann auch noch blinken lässt: (Zum Vergrößern bitte
auf das Bild klicken!) Wie man im obenstehenden Quellkode sieht, wird
beim Programmieren des blinkenden Rahmens
um den Textstring „Micropython“ (= letzte Anzeigezeile auf dem
Display) herum diesmal eine entsprechende „for“-Schleife verwendet. Dabei hat
man es im Schleifenkopf bei der Schleifenbedingung „range(0, 9, 1)“ insgesamt mit drei
Parametern zu tun. Der erste Parameter
„0“ legt den Startwert des Schleifenzählers n = 0 fest mit dem die
Schleife beginnen soll. Beim zweiten Parameter „9“ handelt es sich um
den Endwert des Schleifenzählers n, d.h. genau
genommen um die Abbruchbedingung! Aufgrund des
Schleifenzählerbereichs, engl. „range“, von [ 0 … 9 ] könnte man meinen, dass die Schleife = n + 1 =
9 + 1 = 10 mal durchlaufen wird. Da
aber die Schleifendurchläufe beim Erreichen des Schleifenzählers
n = 9 abgebrochen werden, haben wir es nur mit = n + 1 = 8 + 1 = 9 Schleifendurchläufen zu tun (siehe Video)! Der dritte Parameter „1“ legt fest, um welche Schrittweite, hier +1 nach oben, gezählt werden soll, sodass sich
im vorliegenden Fall der Schleifenzähler
stets um einen Schritt, d.h. n += 1, von einem Schleifendurchlauf zum nächsten erhöht. Wie man ferner im obenstehenden Quellkode
sieht, wird ganz zum Schluss des Programms noch das OLED-Display mittels des Statements „pin16.off()“ ausgeschaltet. - Es soll ja im richtigen Leben auch Menschen
mit einem weniger guten Kurzzeitgedächtnis geben oder auch Menschen, die
sich, aus welchen Gründen auch immer, nicht so richtig konzentrieren können,
weil sie eventuell zu hippelig, d.h. nervös sind (=
Schilddrüsen-Überfunktion oder zu viele Energy Drinks zu sich genommen). Neben dem mehr oder weniger gut ausgeprägten
Kurzzeitgedächtnis gibt es bei den Menschen aber auch solche mit
unterschiedlicher Lernauffassung. So müssen z.B. die Bastler und Praktiker
die Dinge oftmals selbst anfassen oder von allen Seiten betrachten, um Dinge
besser „begreifen“ zu können, während die Theoretiker bzw. weniger praktisch
Begabten lieber einen Blick in die Bedienungs-/Aufbauanleitung werfen, ohne
die sie sich stets unsicher fühlen. Manche Lerntypen müssen Dinge hören, um sie
besser zu verstehen. Da die Dinge bis jetzt noch nicht alle reden können, ich
denke da an die Sprachausgabe z.B. der Kaffeemaschine, des Kühlschranks oder
der Waschmaschine im Zeitalter des IoT, helfen sich
die akustischen Lerntypen auf ihre Weise, indem sie die Dinge laut
besprechen, d.h. vor sich hersagen, um was es geht. Erst wenn die Dinge
akustisch wahrnehmbar sind und das Gehör beteiligt ist, fangen sie an, Dinge
und Zusammenhänge (= Logik) besser zu verstehen und zu verinnerlichen. Sei es wie es ist, während es die einen kurz
und knackig mögen (= einzeilige Textanzeige evtl. mit Laufschriftanzeige),
mögen es die anderen dafür umso geschwätziger (= mehrzeilige
Textanzeige ohne Laufschrift). Beim nächsten „Micropython“-Programm „oled_demo-01-05.py“ geht es deshalb darum, eine fünfzeilige
Textstring-Anzeige auf das OLED-Display zu bringen, die sich übrigens (Text-)
Zeile für (Text-) Zeile von oben nach unten aufbaut: (Zum Vergrößern bitte
auf das Bild klicken!) Dabei hilft uns das obengenannte Programm
dabei, ein noch besseres Verständnis von der Arbeits- und Funktionsweise beim
Programmieren einer Display-Anzeige zu bekommen: (Zum Vergrößern bitte
auf das Bild klicken!) Die Bildschirmanzeige auf dem Desktop-PC hat dann folgendes, selbsterklärendes Aussehen
(siehe „Micropython“-Programm „oled_demo-01-05.py“: (Zum Vergrößern bitte
auf das Bild klicken!) Als nächstes soll ein Anzeige-Programm für das
OLED-Display programmiert werden, mit sich die nachfolgende Display-Anzeige
anzeigen lässt: (Zum Vergrößern bitte
auf das Bild klicken!) Um das „Micropython“-Programm „oled_demo-01-06.py“ mit den richtigen Werten für die xy-Koordinaten
(= 128 x 64 Pixel) im Bereich der x-Achse mit [ 0 …
127 ] = 128 Pixel und im Bereich der y-Achse mit [ 0 … 63 ] = 64 Pixel
programmieren zu können, müssen wir zuvor noch entsprechende Überlegungen
anstellen, wie groß der Platzbedarf in x- und y-Richtung in Form der Pixel
tatsächlich ist. Unschwer zu erkennen ist im obenstehenden
Bild, dass fünf Zeilen Text mit einem entsprechendem
Rahm außen herum für die Displayanzeige programmiert werden sollen. Bei
genauerem Hinsehen erkennt man auch, dass sich die Rahm um den Text herum
berühren, aber nicht überlappen! Deshalb ist die Linienstärke, dort wo
sich die Rahmen berühren, doppelt so dick wie bei der äußeren
Umrandung aller Rahmen. Für das gesamte Display und dessen Pixelgröße
folgt für den Pixelverbrauch in vertikaler Richtung, d.h. von oben nach
unten: 2 * 1 Pixel * 4 Zeilen = 2 Pixel * 4 Zeilen = 8 Zeilen insgesamt,
sodass für den äußeren Gesamtrahmen nur noch 64 Pixel – 8 Pixel = 56 Pixel
übrig bleiben. Von den 56 verbleibenden Pixel müssen dann
noch 2 äußere Rahmenlinien oben und unten der Linienstärke 1 Pixel
subtrahiert werden: 56 Pixel - 2 Pixel = 54 Pixel, sodass pro Textzeile jetzt
nur noch = 54 Pixel / 5 Zeilen = 10,8 Pixel/Zeile = abgerundet 10 Pixel/Textzeile für den Innenrahmen
übrig bleiben!
Dadurch aber, dass sich die 5 Rahmen im Inneren berühren, aber eben
nicht überlappen, werden wie berechnet 4 Pixel bzgl. der Gesamtpixelzahl von
64 Pixel verschenkt, verschlechtert sich die Auflösung der Darstellung, weil
wir 4 Pixel für die Doppel-Innenrahmen + 1
Rundungspixel = 5 Pixel insgesamt verschenken, die sich für die max. mögliche
Rahmenhöhe selbst nicht nutzen lassen, sodass sich die Lesbarkeit entsprechend verschlechtert (siehe
Bild oben)! Wenn wir also keinen Platz, d.h. keine Pixel
bei der Darstellung der Rahmen verschwenden wollen, dann müssen wir dafür
sorgen, dass sich die 5 Pixel-Rahmen um die Schrift herum eben Erwarten nicht
berühren, sondern überlappen: (Zum Vergrößern bitte
auf das Bild klicken!) Sehr deutlich sieht man das im „Micropython“-Programm „oled_demo-01-07.py“ (siehe Bild oben). Und zwar wenn man das Programm startet
und sich in der zweiten Textzeile der Rahmen um den Text legt, sieht
man sehr deutlich, dass sich der Rahmen mit seiner Oberkante über die untere
Linie des darüber befindlichen Rahmens der ersten Textzeile legt,
sodass die sich überlappenden Rahmen nur noch eine Linienstärke von einem
Pixel (bisher waren es zwei Pixel) ausmachen, man also insgesamt bei fünf
Textzeilen insgesamt vier Pixel hinzugewinnt! Für das gesamte Display und dessen Pixelgröße
folgt nun für den Pixelverbrauch in vertikaler Richtung, d.h. von oben nach
unten: 1 Pixel * 4 Zeilen = 4 Zeilen (vormals 8 Pixel), sodass für den äußeren
Gesamtrahmen jetzt wieder 64 Pixel - 4 Pixel = 60 Pixel
übrig bleiben. Von den jetzt noch 60 verbleibenden Pixel
müssen dann noch 2 äußere Rahmenlinien oben und unten der Linienstärke 1
Pixel subtrahiert werden: 60 Pixel - 2 Pixel = 58 Pixel, sodass pro Textzeile
jetzt wieder = 58 Pixel / 5 Zeilen = 11,6 Pixel/Zeile = abgerundet 11 Pixel/Textzeile für den Innenrahmen
übrig sind!
Dadurch aber, dass sich jetzt die 5 Rahmen im Inneren überlappen,
werden wie berechnet 4 Pixel hinzugewonnen, sodass sich die Auflösung der
Darstellung entsprechend verbessert, weil wir jetzt 4 * 1 Pixel für den einfachen,
und nicht mehr doppelten Innenrahmen, hinzugewonnen haben! Die dadurch
verbesserte Lesbarkeit im Rahmeninneren lässt sich sogar gut erkennen!
Vergleichen Sie z.B. in der letzten, d.h. fünften Textzeile „Micropython“ die beiden Buchstaben „py“, deren Unterlängen
nun nicht mehr die untere Umrandung berühren! - Abschließend bleibt noch die Frage zu klären,
ob sich der sogenannte „y_offset“, d.h. ob sich das Dehnen, Auseinanderziehen
oder Zusammenstauchen von Textzeilen auch auf die Rahmen auswirkt. Kurz und
knapp, probieren wir es im „Micropython“-Programm „oled_demo-01-08.py“ einfach aus, indem wir den „y_offset“-Wert z.B. im Intervall von
[ 8 … 16 ] entsprechend abändern. – Als nächstes geht es darum, dass wir die
fünfzeilige OLED-Anzeige noch attraktiver
gestalten, indem wir einen optisch ansprechenden Effekt einbauen, z.B. so wie
wir es von den noch mechanischen Anzeigetafeln bei den
Ankünften oder Abflügen vom Flughafen her kennen. Mich hat dabei immer
fasziniert, wenn neue Flugankünfte angekündigt wurden und dabei alle
Anzeigefelder und -zeilen der ganzen Tafel auf einmal
durchgeblättert wurden und das mechanische Geräusch beim Umblättern der
einzelnen Buchstabenblätter nicht zu überhören war. Man nennt diese
inzwischen veralteten, aber an Flughäfen noch immer zu sehenden Anzeigetafeln
übrigens „Faltblattanzeige“.
Ähnlich einer solchen Faltblattanzeige
programmieren wir die Textstring-Umrandung unseres OLED-Displays,
indem wir zum Schluss der Textanzeige den einzelnen Rahmen ein- bis zweimal
komplett von oben nach unten „durchrattern“ lassen, um dann am Ende auf einer
Textzeile stehen zu bleiben, die uns besonders wichtig ist und die wir
deswegen besonders hervorheben wollen (siehe Video): (Zum Vergrößern bitte
auf das Bild klicken!) Im obenstehenden Bild ist der Sourcecode zu
sehen, nachdem der fünfzeilige Text bereits komplett angezeigt wurde und nun die
einzelnen Textumrandungen in Form eines Rahmes zeilenweise von oben nach
unten durchscrollen, um dann bei der siebten Zeile beim Statement „if stop > 7“ zu stoppen. Was bedeutet es aber, wenn es keine sieben
anzuzeigenden Textzeilen gibt, sondern nur vier? Da es sich bei der „while“-Schleife wegen der Bedingung „True“ um eine Endlosschleife handelt, wird diese fortwährend durchlaufen bis
die Abbruchbedingung im Statement „if stop >
7“
erfüllt ist, das Programm dann wegen des Statements
„break“ einfach abbricht bzw.
beendet wird, die Displayanzeige wegen des auskommentierten Statements „pin16.off()“ aber eingeschaltet bleibt. Da die Endlosschleife mit dem anzuzeigenden
Text und den Textumrandungen fortwährend durchlaufen wird, muss der Textzeilenzähler „zeile“ nach Erreichen der vierten,
anzuzeigenden Textzeile wieder auf Anfang, d.h. den Wert 1 gesetzt werden. Wenn man nun aber erreichen will, dass die
Textumrandung bei der dritten Textzeile stehen bleibt, dann muss man
gemäß dem Statement „if stop > 7“ die Textzeilen wie folgt berechnen: 7
Textzeilen - 4 bereits angezeigte Textzeilen = 3 verbleibende Textzeilen als
Rest nach dem ersten Bilddurchlauf, sodass die Textumrandung die dritte Textzeile „Kit ESP32,“ umschließt. Praktisch bedeutet die Abbruchbedingung im Statement „if stop >
7“,
dass man das Durchnummerieren der Textzeilen fortwährend weiter laufen bzw.
durchrechnen lässt, so als ob es keinen Bildwechsel gäbe. Mit der
Folge dass die Textanzeige mit je vier anzuzeigenden Textzeilen quasi
1 ½ Bilddurchläufe bzw. Bildwechsel erfährt. Bei einer Abbruchbedingung mit dem Statement „if stop >
11“
bekämen wir z.B. 11 Textzeilen / (
4 Textzeilen/Bild ) = 2,75 Bildwechsel, d.h. zwei
vollständige Bildwechsel und eine 2/3 Bildanzeige mit der Textumrandung bei
der Textzeile = 11 Textzeilen / ( 4 Textzeilen/Bild ) = 2 * 4 Textzeilen
+ 3 restliche Textzeilen = 2 Volltextbilder + 3 restliche Textzeilen, sodass
die Textumrandung den Schriftzug „Kit ESP32,“ umranden würde. Wenn man das Ganze ausprobiert, dann stellt
man aber erstaunt fest, dass nicht der Schriftzug der dritten
Textzeile angezeigt wird, sondern nur der Schriftzug „ein HELTEC WiFi“ der zweiten Textzeile! Der Grund dafür ist ganz
einfach der, dass die Bedingung im Statement
„if
stop > 11“ für den Wert = 11 bis dato noch nicht
erfüllt wurde, sondern erst noch erfüllt werden muss, nämlich beim nächsten
Schleifendurchlauf. Wenn dann aber die Abbruchbedingung erfüllt wird, bricht
das Programm sofort ab, sodass die rechnerisch dritte Textzeile nicht
mehr angezeigt werden kann. Demzufolge werden bis zur Erfüllung der
Abbruchbedingung nur 10
Textzeilen
angezeigt, sodass folgt: 10 Textzeilen / ( 4 Textzeilen/Bild ) = 2 * 4 Textzeilen + 2 restliche Textzeilen = 2
Volltextbilder + 2 restliche Textzeilen, sodass die Textumrandung mit dem Schriftzug
„ein HELTEC WiFi“ der zweiten Textzeile angezeigt wird. - Aber so wie es aussieht, liegt der logische
Denkfehler bei der Berechnung darin begründet, dass die anzuzeigenden Textzeilen
in der Texttabelle „text_Str“ vom Typ „list“
eben nicht bei „1“ beginnen, sondern bei „0“, während hingegen der Zeilenzähler „zeile“ bei „1“ beginnt. Im Zweifelsfall geht „Probieren“ über
„Studieren“, lassen sich die Dinge ja mit dem kleinen Mikrorechner und dem „Micropython“-Programm „oled_demo-01-09.py“ praktisch ausprobieren! – Dass man, wie nachfolgend im Sourcecode von
Bild „01_17“ gezeigt, bei
der Textanzeige im
OLED-Display mittels des Statements „if stop > 7:“ auswählen kann, dass
die Textanzeige mit dem Textstring „Kit ESP32,“ mittels Rahmen umrandet werden soll, ist zwar sehr
interessant, aber programmiertechnisch zu umständlich, da man den Wert „7“
zwecks Änderung im Quellkode erst mal finden muss. Aber wenn man es dann früher oder später auch
noch mit einem sehr umfangreichen Programm mit vielen Programmzeilen zu tun
hat, dann ist das Motto „Wer sucht, der findet!“ nicht wirklich hilfreich,
weil man sich erst wieder in das Programm einlesen muss und der Zeitaufwand
für das Einlesen und die Suche unverhältnismäßig zu groß ist. Viel praktischer und ergonomischer wäre es,
wenn man dem anzuzeigenden Textstring
auch gleich noch das Attribut “1“ stellvertretend für „Umranden“ mit auf den Weg geben könnte! Das aber
wiederum bedeutet, dass wir es bei kleinen Datenbank vom Typ „list“ mit einer zweidimensionalen Tabelle,
die nicht nur aus Tabellenzeilen, sondern jetzt auch aus zwei Tabellenspalten
besteht, zu tun haben:
Während dabei das Deklarieren mit dem Statement
„text_Str
= list()“
und das anschließende Initialisieren
mit dem Statement „text_Str = [ … ]“ eine der leichteren
Übungen ist, müssen wir uns an das Handling, d.h. den Umgang mit einer zweispaltigen
Tabelle erst noch schrittweise herantasten! Zu diesem Zweck wird das
bisherige „Micropython“-Programm „oled_demo-01-09.py“ erst mal abgespeckt und quasi bis auf die Dinge, die mit
der Tabelle zu tun haben, entkernt: (Zum Vergrößern bitte
auf das Bild klicken!) Der im obenstehenden Bild gezeigt Sourcecode
lässt sich natürlich auch im „Micropython“-Programm „oled_demo-01-10.py“ selbst ausprobieren. An dieser Stelle noch ein Tipp: Kopieren Sie
sich die (Hyper-) Link-Adresse in
die (Windows‑) Zwischenablage, indem Sie den Mauszeiger auf den blau markierten Link „oled_demo-01-10.py“ positionieren, mit der rechten Maustaste klicken und im Kontextmenü auf <Adresse des Links kopieren> klicken, sodass der
Link in die Zwischenablage kopiert wird. Wechseln Sie anschließend in das
Programm mit der „Thonny“-Entwicklungsumgebung für das Programmieren
mit Micropython und Python. Klicken Sie in der „Thonny“-Menüleiste auf <File>, <Open>,
fügen Sie den Link aus der
(Windows-) Zwischenablage wieder
mittels der Tastenfolge <Strg>,
<V> ein in die Eingabezeile
<Dateiname> und
bestätigen Sie die „Eingabe“ mit der Taste
<Return/Enter>,
sodass das „Micropython“-Programm „oled_demo-01-10.py“ aus dem Hinternet vom Webserver heruntergeladen
und in der „Thonny“-Entwicklungsumgebung
angezeigt wird! Nachfolgend also der
maßgebliche Ausschnitt vom Quellkode zur zweispaltigen Tabelle (siehe „Micropython“-Programm „oled_demo-01-11.py“): (Zum Vergrößern bitte
auf das Bild klicken!) Kennen Sie den Unterschied zwischen der analogen
Welt und der digitalen? In der analogen Welt gibt es z.B. abends im Sommer
oftmals einen wunderschönen Sonnenuntergang bei dem die Sonne kurz vor dem
Verschwinden noch als rot glühender Feuerball zu sehen ist, obwohl sie
eigentlich schon seit knapp sechs Minuten hinter dem Horizont verschwunden
ist, weil eben das Licht wegen der großen Entfernung zwischen Sonne und Erde
trotz der Lichtgeschwindigkeit
von rund c = 300 000 km/s so lange braucht, bis es die Erde erreicht. Wäre
die Sonne digital, gäbe es keinen Sonnenuntergang, weil sich beim
Sonnenuntergang von jetzt auf gleich ausschalten würde. In der Digitaltechnik
und Informatik wird das Einschalten mit einer „1“ (auf manchen Elektro-/Elektronikgeräten
mit „I“ symbolisiert) und das Ausschalten mit einer „0“. Das Umschalten von „0“ auf „1“ bzw. der
Schaltzustand „0“ (= „aus“) oder „1“ (= „ein“) lässt sich mit zwei
Transistoren als sogenannte „bistabile Kippstufe“
oder „RS-Flipflop“ realisieren, die dabei in der Lage sind jeweils einen der
beiden Schaltzustände zu speichern. Und zwar solange bis die Batterie leer
ist oder der Strom ausfällt. In der Digitaltechnik und Informatik bezeichnet
man den gespeicherten Schaltzustand als 1 Bit. Dabei ergeben 8 Bit = 1 Byte
und 1024 Bits = 1 Kilobyte (KByte). Wenn Sie jemanden beleidigen wollen, ohne eine
Strafanzeige zu riskieren, dann sagen Sie zu Ihrem Gegenüber: „Du dummer
45054!“ Informatiker, die im Informatikunterricht gut aufgepasst haben,
wissen, dass sich die dezimalen Zahl 45054 ins hexadezimale Zahlensystem zur
Basis 16 umrechnen lässt und dann den hexadezimalen Wert „AFFE16“
ergibt. Eine einstellige, hexadezimale Zahl erstreckt sich über den
Zahlenbereich [0…F]. Bei hexadezimalen Zahl rechnet man also dezimal von
[0…9]10 und dann weiter mit den Buchstaben, die aber hexadezimale
Zahlen sind wie z.B. [A, B, C, D, E und F]16, wobei F16
= 1510 entspricht! Starten Sie den (Windows-) Taschenrechner,
schalten Sie ihn im Menü um auf „wissenschaftlich“ ( </>
), tasten Sie die hexadezimale (= engl. „HEX“) Zahl AFFE ein, und lassen Sie
sich diese dezimal (= engl. „DEC“) anzeigen! Jetzt sind Sie soweit sensibilisiert, dass Sie
den Unterschied der ansonsten
identischen „Micropython“-Programme „oled_demo-01-11.py“ und „oled_demo-01-12.py“ herausfinden können. Aber können Sie den Unterschied auch
erklären? Versuchen Sie es, indem Sie beide Programme der Reihe nach im Mikrorechner „HELTEC WiFi kit 32“ mit dem ESP32-Prozessor laufen lassen. Noch deutlicher, aufschlussreicher und erfolgsversprechender wird die Detektivarbeit, wenn man
sich die beiden „Micropython“-Programme „oled_demo-01-13.py“ und „oled_demo-01-14.py“ anschaut und diese ausprobiert. Dann stellt man nämlich
fest, dass der Programmaufruf des Programms „oled_demo-01-13.py“ zu einer Fehlermeldung in der Programmzeile 47
mit dem Statement „oled.text(text_Str[2][1],zeile,spalte)“ führt. Was aber
passiert in dem Statement? Tritt der Fehler im Statement auf? Ist das
Statement selbst der Fehler oder liegt der Fehler ganz wo anders? Mit dem Statement
„oled.text(text_Str[2][1],zeile,spalte)“ soll bewirkt werden,
dass der Text bzw. Textstring „text_Str[2][1]“auf
dem OLED-Display angezeigt wird. Dabei fällt auf, dass es sich bei dem
Textstring nicht um einen einzelnen Textstring handelt, sondern dass
sich dieser aus den beiden Teilen „[2][1]“ zusammensetzt. Wenn man sich dazu den Quellkode des Programms
„oled_demo-01-13.py“ anschaut, dann stellt man fest, dass es sich bei dem Textstring „text_Str[2][1]“
um zwei Datenfelder des zweiten Datensatzes „["Kit ESP32,", 1]“ der kleinen Datenbank
in Form einer 5 x 2 Matrix großen Tabelle handelt, die sich aus 5 Zeilen und
2 Spalten zusammensetzt. Weiter fällt auf, dass es sich beim ersten
Datenfeld mit dem Content
"Kit
ESP32," um einen alphanumerischen Content
in Form eines Textstrings handelt, während es beim zweiten Datenfeld
um einen numerischen Content in Form der Zahl = 1 geht. Dazu muss man wissen, dass sich in einer
Datenbank in Form einer Tabelle vom Typ „list“ nicht nur gemischte Contents (= Dateninhalte) unterbringen lassen, sondern
z.B. auch Funktions-/Methodenaufrufe (siehe dazu auch im Tutorial „Micropython,
Teil 1“). Im Vergleich zum „Micropython“-Programme „oled_demo-01-14.py“ fällt auf, dass man bei diesem keine Fehlermeldung
angezeigt bekommt, dass sich dieses fehlerfrei ausführen lässt. Im
weiteren Vergleich dazu fällt auf, dass es auch bei diesem Programm einen Textstring „text_Str[2][1]“
mit zwei Datenfeldern im zweiten Datensatzes „["Kit ESP32,", "1"]“
gibt. Allerdings, und das scheint wesentlich zu
sein(!), handelt es sich bei dem zweiten Datenfeld mit dem Content "1" um einen alphanumerischen Content,
d.h. um die Ziffer 1 und nicht wie im „Micropython“-Programme „oled_demo-01-13.py“ um die Zahl
1 !!!
Es bleibt weiterhin spannend, wenn wir der
Frage nachgehen, wie der dritte Datensatz, erstes Datenfeld mit
dem Content „Kit ESP32,“ mittels des Statements
„oled.text(text_Str[2][0],zeile,spalte)“ an das OLED-Display
übertragen wird. Doch zunächst bleiben wir bei dem inzwischen umbenannten
Funktionsaufruf „text_zeile(text_Str[2][0],zeile,spalte)“ im Programm „oled_demo-01-15.py“ (Zum Vergrößern bitte
auf das Bild klicken!) und lassen uns zwecks besseren Verständnisses
sowohl im Hauptprogramm als auch
in der Funktion „text_zeile()“ hilfsweise die
unterschiedlichen Typen von
Klassen
wie folgt anzeigen: (Zum Vergrößern bitte
auf das Bild klicken!) Dass es sich bei dem Statement „oled.text()“ um eine Funktion bzw. ein Modul der
importierten Klasse „SSD1306_I2C“ handelt, lässt sich leicht
nachvollziehen; dass der Funktionsaufruf
„text(text,x,y)“ selbst vom Typ „str“ ist, schon weniger!
Das Programm
„oled_demo-01-16.py“ ähnelt dem Programm
„oled_demo-01-15.py“ nur mit dem Unterschied, dass beim Ersteren jetzt das Statement „oled.text(text_Str[2][0],zeile,spalte)“ direkt, d.h. ohne die Funktion „text_zeile(text, zeile,
spalte : int())“ an das OLED-Display übertragen wird: (Zum Vergrößern bitte
auf das Bild klicken!) Jetzt steht endgültig fest, dass die Funktion „text_zeile(text, zeile,
spalte : int())“ tatsächlich nur der
„Bequemlichkeit“ dient bzw. in dieser nur der sogenannte Offset der „x“- und „y“-Koordinaten umgesetzt wird. Dabei
lässt sich die Darstellung der Textzeilen in „y“-Richtung, d.h. auf dem
OLED-Display von oben nach unten, entsprechend stauchen oder dehnen!
- Aber bei dem Programm „oled_demo-01-16.py“ kommt der Offset nicht zum Einsatz, da die dazugehörige Funktion „text_zeile(text, zeile,
spalte : int())“ nicht
verwendet wird (siehe Bild oben). – So, jetzt sind wir an einem Punkt angekommen,
wo wir alles analysiert und ausführlich untersucht haben, was sich
untersuchen lässt. Und das Verblüffende dabei ist, dass das eigentliche Problem
bzw. die Fragestellung, ob es ein funktionelles Zusammenwirken zwischen der zeilenorientierten
Textdarstellung auf dem OLED-Display und der grafischen
Darstellung der Umrandung mittels eines Rechtecks, das sich wiederum aus
einzelnen Pixeln zusammensetzt, nicht gelöst bzw.
beantwortet wurde, eben weil es zwischen der grafischen Darstellung
wie bei der rechteckigen Umrandung und der zeilenorientierten Textdarstellung
keinen Zusammenhang gibt: die Pixeldarstellung wie beim Zeichnen eines
Rechtecks als Umrandung hat mit der zeilenorientierten Textdarstellung
überhaupt nichts tun! Beide, d.h. Text und Grafik haben nichts miteinander zu
tun! Die einzige Gemeinsamkeit zwischen Text und Grafik ist die, dass sich
beide das gleiche Koordinatensystem teilen. Im Nachhinein erscheint das einfach nur
logisch zu sein. Und, wer als erfahrener Programmierer oder Mathematiker
schon öfters Grafiken programmieren musste, weiß das eben! Wenn man aber in ein- und demselben Programm
sowohl Text als auch Grafik quasi synchron programmieren und
ein an sich simpler Rahmen einen Textstring umranden soll, dann wünscht man
sich eben, dass sich die Rahmengröße ganz einfach von der Text- bzw.
Schriftgröße ableitet. Aber wenn man eben nicht weiß, mit welcher
Schriftgröße man es bei Darstellung von Text zu tun hat und anfangs auch
nicht weiß, ob sich die Schriftgröße verändern, d.h. skalieren lässt oder
nicht, dann ist man mangels entsprechender Erfahrung als „digitaler
Schriftsetzer“ oder grafischer Layouter schnell überfordert oder eben anfangs
ziemlich ratlos. Aber das hat sich ja jetzt geklärt, sodass wir unser
kombiniertes Programm „oled_demo-01-17.py“ mit Text- und Grafikanwendung endlich fertigstellen
können: (Zum Vergrößern bitte
auf das Bild klicken!) Werfen wir abschließend noch kurz einen Blick
auf das „if“-Statement im obenstehenden
Quellkode (siehe roter Kasten ganz oben): · if text_Str[zeile-1][1] == "1": Bei einfachen „if“-Abfage ohne „else“, d.h. „Nur wenn die Bedingung xy“
erfüllt ist, wird der nachfolgende Programmkode ausgeführt, ansonsten (= „else“) passiert nichts! In der „if“-Abfage wird das Statement „text_Str[zeile-1][1]“, konkret die zweidimensionale Tabelle „text_Str[zeile-1][1]“ mit den zwei Parametern „[zeile-1]“ und „[1]“ quasi für „Zeile“ und
„Spalte“, aufgerufen und bezüglich der Inhalte, engl. „contents“,
abgefragt. Dabei wird mit dem ersten Parameter konkret die „zeile-1“ = 1 - 1 = 0 aus der Tabelle „text_Str“ ausgelesen. Man höre und staune: Die Tabelle „text_Str“ beginnt in der rauen Wirklichkeit der
Programmierung tatsächlich beim Index „0“, aber das wussten wir ja eigentlich schon.
Aber gerade deswegen, weil die Textzeilen
stets bei „1“ beginnen und nicht bei „0“ und gleichzeitig die Grafikpixel für die Umrandung stets
bei „0“ für die x- und y-Achse, gab es anfangs, auch und gerade mit dem „y-Offset“ für das Stauchen und
Dehnen der Textzeilen entsprechende Verständnisschwierigkeiten! Mit dem zweiten Parametern „[1]“, der übrigens immer auf „1“ stehen muss, weil es sich um
die zweite Spalte der Tabelle „text_Str“ handelt, wird dann
ausgelesen, ob der in der Tabelle zugewiesene Wert auf „0“ oder „1“ steht.
Dabei steht „0“ für „false“, d.h. falsch, nicht
zutreffend und „1“ für „true“, d.h. richtig,
zutreffend. Im Programm
„oled_demo-01-18.py“ ersetzen wir die in der Tabelle „text_Str“ enthaltenen („Wahrheits“-)
Werte „0“ durch „False“ und „1“ durch „True“, da die booleschen
Wahrheitswerte aussagekräftiger sind und die Verwechselungsgefahr verringern.
Außerdem werden die Display-Anzeigen für Text und Textumrandung in eigene
Funktionen wie folgt ausgelagert: (Zum Vergrößern bitte
auf das Bild klicken!) Da wir in den obenstehenden Funktionen mit globalen
Variablen aus dem Hauptprogramm arbeiten
und zwar deswegen, weil wir diese zuvor mittels des Statements „from ssd1306 import SSD1306_I2C“ durch Importieren verfügbar gemacht haben, müssen wir
diese nicht explizit über den Funktionskopf
der beiden Funktionen „anzeigen_Textzeile()“ und „anzeigen_Textrahmen()“ einlesen! Demzufolge
haben die beiden Funktionen nur die Funktion, das Hauptprogramm kompakter und
übersichtlicher zu machen. (Zum Vergrößern bitte
auf das Bild klicken!) Wie man im obenstehenden Quellkode des Hauptprogramms sieht, wird die Tabelle „text_Str“ im ·
Statement if text_Str[zeile-1][1] == "True" Zeile für Zeile abgefragt, ob der zweite
Parameter vom Typ „bool“ den Wert „True“ hat, und falls dies
der Fall ist, dann wird die entsprechende Textzeile abschließend mit einem Rahmen umrandet und der Anzeigevorgang mittels des Statements
„break“ abgebrochen, da der Anzeigevorgang vollständig umgesetzt
wurde (siehe Programm „oled_demo-01-18.py“). – „Faltblattanzeige“
jetzt mit „exec“-Programmausführung Beim Programm
„oled_demo-01-19.py“ wurden der Quellkode für das Anzeigen der Textzeilen
sowie der Textumrandungen in die Funktionen
„anzeigen_Textzeile()“ und „anzeigen_Textumrandung()“ ausgelagert. Da den
Funktionen im Funktionskopf keine Parameter mit auf den Weg gegeben und auch
keine Werte mittels „return“ zurückgegeben werden
gibt es mit der Auslagerung keinerlei Probleme. Darüber hinaus wurde noch die
Funktion „arbeite_mit_oled()“ neu in das Programm
aufgenommen. Dabei handelt es sich um das kleine OLED-Programm
oled.py mit dem man sich ein „Hallo“, ein leeres
und ein gefülltes Reckteck auf dem OLED-Display
anzeigen lassen kann. Im Programm selbst wird das kleine OLED-Programm „oled.py“ automatisch
aufgerufen und zwar nachdem der Text
„Kit
ESP32,“
im Display angezeigt wurde: (Zum Vergrößern bitte
auf das Bild klicken!) Wie man im obenstehenden Quellkode sieht,
lässt sich mit dem Statement „exec("text_auf_OLED_Display.arbeite_mit_oled()")“ die Funktion „arbeite_mit_oled()“
aufrufen und ausführen. Anschließend springt das Programm an die Stelle im
Quellkode zurück, von es ursprünglich aufgerufen und gestartet wurde. - Das Programm „oled_demo-01-20.py“ ist eine Weiterentwicklung des
vorhergehenden Programms mit dem Unterschied, dass das Statement „break“ (= Abbruch des laufenden
Programms) entfernt wurde, so dass die „Endlosschleife“ mit dem Statement „while True“ weiter
ausgeführt wird! Darüber hinaus gibt es in der Endlosschleife noch die neu
hinzugefügte Statements „text_Str[2][1] = False“ und „text_Str[3][1] = True“, sodass das extern aufgerufene Programm „text_auf_OLED_Display.arbeite_mit_oled()“ nun nicht mehr
ausgeführt wird und der „Cursor“ mit dem Textstring-Anzeigerahmen als Nächstes
die Anzeige „programmiert in“ anzeigt. Dabei
erneuert sich die fünfzeilige Anzeige im OLED-Display fortlaufend alle fünf
Sekunden! Damit wird demonstriert, dass sich die Anzeige
im OLED-Display inhaltlich, d.h.
bezüglich der anzuzeigenden Textstrings
„text_Str[?][?]“, während des laufenden
Betriebs jederzeit ändern lässt: (Zum Vergrößern bitte
auf das Bild klicken!) Da die „Endlosschleife“ mit dem Statement „while True“ nun endlos
ausgeführt wird, lässt sich das Programm „oled_demo-01-20.py“ im Moment nur durch Unterbrechung der Stromzufuhr des
kleinen „HELTEC WiFi kit
32“-Mikrorechners oder durch Mausklick auf den Button „Rotes Stop!“-Schild in
der Menüleiste der „Thonny“-Entwicklungsumgebung
beenden! – Jetzt wissen wir und schätzen
es, dass sich über die fünfzeilige OLED-Displayanzeige
nicht nur Contents wie z.B. Textstrings komfortabel
und effektvoll darstellen lassen, sondern dass sich jetzt auch Anwendungen, wie z.B. das kleine
Grafik-Testprogramm „oled.py“, mittels des „exec()“-Statements starten und ausführen lassen
(siehe im Bild oben). Der Nachteil dabei ist aber noch der, dass das
automatische, d.h. das Menü gesteuerte Starten und Ausführen eines anderen
Programms wie z.B. die Funktion „arbeite_mit_oled()“ noch
manuell veranlasst bzw. extra programmiert werden musse
(siehe im Bild oben). Aber genau das lässt mit geringem Programmieraufwand
problemlos verbessern. Allerdings muss man dazu einen kleinen Trick anwenden
bzw. wissen, wie man mit einer dreidimensionalen Tabelle umgeht, wie sich
diese handhaben lässt. Doch zunächst erweitern wie die zweidimensionale
Tabelle wie folgt zu einer dreidimensionalen: (Zum Vergrößern bitte
auf das Bild klicken!) Aber handelt es sich bei der
oben im Bild stehenden fünfzeiligen Tabelle wirklich um eine dreidimensionale
Tabelle? Dies ist natürlich eine rhetorische Frage, die einem die Antwort
quasi in den Mund legt: nein. Was aber ist der Grund dafür, dass es sich
nicht wirklich um eine dreidimensionale Tabelle handelt? Im Bereich der grafischen
Datenverarbeitung bzw. der Programmierung von Grafiken, aber auch der
Abbildung/Darstellungen von Gleichungen zweiten ( f(x)
= x2 ) und dritten Grades ( f(x) = x3 ) wie z.B. bei
der Kurvendiskussion, haben wir es mit zwei Dimensionen, d.h. mit x- und
y-Koordinaten und bei drei Dimensionen mit x-, y- und z-Koordinaten zu tun. Lässt man z.B. eine zweidimensionale
Hyperbel der Funktion y = f(x) = x2 um die y-Achse rotieren, dann
entsteht ein dreidimensionales Gebilde ähnlich einem Sektglas in das man von
oben Sekt hineinfüllen kann. Würde man die rotierende Hyperbel nach oben
abschließen, d.h. auf das Sektglas einen Deckel auflegen, dann ließe sich das
(dreidimensionale) Volumen wegen der Form des Sektglases bzw. der Hyperbel
nur durch Integration (= Umkehrung der Differentiation) berechnen. Für die
grafische Darstellung bräuchte es dann eine echte dreidimensionale Tabelle im
Sinne einer dreidimensionalen Wertetabelle. Ob sich eine solche dann mit
einer Tabelle vom Typ „list“, wie oben im Bild zu sehen, programmieren lässt,
müsste noch geklärt, d.h. ausprobiert werden. Falls nicht, müssten wir in Python
ein externes Modul importieren, um tatsächlich zwei-, drei- und
vierdimensionale Arrays programmieren zu können. Apropos vierte Dimension.
Wissen Sie, was allgemein als vierte Dimension bezeichnet wird? Richtig, die
Zeit! Was wir bezüglich unserer „dreidimensionalen“
Tabelle (siehe im Bild oben) mit Sicherheit sagen können, ist, dass es sich
bei dieser um eine Tabelle mit
fünf Zeilen,
engl. „rows“, d.h. Reihen und drei Spalten, engl. „columns“,
d.h. Spalten, handelt. Ausgehend von einer
dreispaltigen Tabelle müsste also eine fünfspaltige Tabelle z.B. wie folgt aussehen:
*) Anmerkung: Bei den Parametern handelt es sich z.B. um Parameter, die der Funktion „arbeite_mit_oled(param_1, param_2)“ mit
auf den Weg gegeben werden können. Nehmen wir einmal an, wir
müssten den Parameter „param_1“ aus der Tabelle, d.h.
aus der dritten Zeile und vierten Spalte auslesen und den Wert im Programm
entsprechend verarbeiten bzw. programmieren. Wie müsste das dazugehörige „exec()“-Statement
aussehen? So vielleicht: param_1 = text_Str( [2][True][ ][3][ ] ) exec( text_Str( [2][True][ ][param_1][ ] ) ) param_1 = text_Str( [2][True][“”][3][“”]
) exec( text_Str( [2][True][“”][param_1][“”]
) ) param_1 = text_Str( [2][True],
[3], ) exec( text_Str( [2][True], [param_1], ) ) Vielleicht sollten wir aber
zunächst unsere fünfspaltige Tabelle doch etwas vereinfachen und diese
wie folgt auf drei Spalten reduzieren:
Wie müsste jetzt das
dazugehörige „exec()“-Statement
aussehen? So vielleicht: exec( text_Str( [2][True]["… arbeite_mit_oled()"] ) ) Oder so: exec( text_Str( [2][ "… arbeite_mit_oled()"]
) ) Oder eventuell so: exec( text_Str( [2][2] ) ) Oder wie wäre es damit: exec( text_Str[2][2] ) Kennen Sie den Unterschied
zwischen einem (Elektronik-) Bastler und einem Ingenieur der Elektotechnik/Elektronik? Der Bastler bastelt, indem er
z.B. Widerstände nicht zuvor berechnet, bevor er sie in einer
Schaltung verwendet, sondern tauscht sie einfach gegeneinander aus. Wenn dann
der Widerstand abraucht, dann war er zu klein. Aber es war eben nicht der
Widerstand mit seinem ohmschen Widerstandwert(!) zu klein, sondern die
zulässige (Wärme-) Verlustleistung des Widerstandes! Es gibt nämlich Widerstände
mit z.B. 1/8, 1/4 oder 1/2 Watt zulässiger Verlustleistung. Widerstände mit
einer größeren Verlustleistung von 1 bis 5 Watt sind dann wegen der
Hitzeentwicklung in einem Keramikgehäuse untergebracht und Widerstände mit
noch höherer Verlustleistung sind z.B. als gewickelte Spule auf einem
Porzellankörper aufgebracht. Der Ingenieur („Einem Ingenör ist nichts zu schwör!“, „Gestern wusste ich noch
nicht, wie ‚Ingenieur’ geschrieben wird, heute bin ich schon einer!“)
hingegen, bemüht erst seine grauen Zellen und versucht den Widerstand hinsichtlich
seines ohmschen Wertes und seiner Verlustleistung richtig zu
berechnen, bevor er diesen in die Schaltung einbaut und verlötet bzw.
verdrahtet (Widerstände können nämlich so heiß werden, dass das Lötzinn
schmilzt! Branntgefahr!). Und was macht der
Programmierer? Er wendet das Prinzip „Banane“ an: das Produkt reift beim
Kunden, wird also erst mit dem dritten oder vierten Update zuverlässig
funktionieren. Aber das kennt man ja z.B. von Microsoft Windows oder Google Android Betriebssystemen. Was also tun? Starten Sie
ganz einfach das Programm „oled_demo-01-21.py“, lassen Sie sich überraschen, und
schauen Sie sich den Sourcecode an: (Zum Vergrößern bitte
auf das Bild klicken!) Obwohl wir mit einer „dreidimensionalen“, pardon dreispaltigen(!)
Tabelle vom Typ „list“ - die Inhalte
lassen sich im laufenden Betrieb ändern! - arbeiten,
haben wir es bei dem Statement „exec(text_Str[2][2])“ nur mit zwei(!) Übergabeparametern „[2][2]“ zu tun! Wahnsinn! Da muss man erst
mal drauf kommen! Dabei legt der erste Parameter „[2]“ fest, welche Tabellenzeile
aus dem Indexbereich [ 0 … 4 ] im OLED-Display
angezeigt werden soll und der zweite Parameter „[2]“ (= 3. Tabellenspalte) aus dem Indexbereich [ 0 … 2 ] gibt
an, dass das „exec()“-Statement
nebst der Funktion „arbeite_mit_oled()“ aus
der Klasse „text_auf_OLED_Display“
ausgeführt werden soll:
Das „exec()“-Statement
nebst der Funktion „arbeite_mit_oled()“ aus
der Klasse „text_auf_OLED_Display“
selbst wird aber nur dann ausgeführt, wenn die „if“-Abfrage mit
dem Statement „if
text_Str[zeile-1][1] == True:“ den Wert „True“ hat! - Mit den beiden Statements text_Str[2][1] = False text_Str[3][1] = True innerhalb des Programmblocks
der “if”-Abfrage wird
demonstriert, dass sich die OLED-Displayanzeige während des Betriebs, d.h. im laufenden
Programm, jederzeit ändern lässt (siehe im obenstehenden Bild)! Damit haben wir es erstmals mit der Möglichkeit einer Ereignis
gesteuerten Programmierung zu tun. Vorausgesetzt natürlich, dass wir es bei der entsprechenden „while“-Schleife nach wie vor mit einer Endlosschleife zu tun haben und dies bei der
weiteren Programmierung nicht ändern! - Wir entwickeln das Programm „oled_demo-01-21.py“ weiter, indem wir die Funktion „text_zeile(text, zeile,
spalte : int())“ in die Klasse „text_auf_OLED_Display“
verschieben und dabei entsprechend anpassen: (Zum
Vergrößern bitte auf das Bild klicken!) Auch die Funktion „anzeigen_Textzeile()“ muss wie folgt
angepasst werden: (Zum
Vergrößern bitte auf das Bild klicken!) Jetzt sind alle Funktionen
„unter Dach und Fach“, d.h. innerhalb der Klasse „text_auf_OLED_Display“ vereint (siehe Programm „oled_demo-01-22.py“). Wie wir gleich sehen werden,
lassen sich die Funktionen der Klasse „text_auf_OLED_Display“
nicht nur vom Hauptprogramm aus
steuern, sondern auch direkt vom Programmblock der Klasse
aus. Und zwar ganz ohne irgendeinen Funktionsaufruf! Das funktioniert
tatsächlich, weil der „Python“-Interpreter vor
dem Programmstart alle Klassen nach darin enthaltenden Variablen, Funktionen
usw. durchsucht, nach Abhängigkeiten von
anderen Klassen, Funktionen usw. durchforstet, um diese später beim Interpretieren des Programmkodes und
dessen Ausführung in
der richtigen Reihenfolge zu berücksichtigen. Dabei wird dann auch der in
der jeweiligen Klasse vorhandene
Programmkode ohne Zutun von
außen gestartet und abgearbeitet (siehe Programm „oled_demo-01-23.py“): (Zum
Vergrößern bitte auf das Bild klicken!) Wenn es also darum geht, dass
wir systematisch, effizient und gut lesbar programmieren, dann sollte man den
Programmkode zur Ansteuerung des OLED-Displays
früher oder später vom Hauptprogramm
aus in den Programmblock der Klasse „text_auf_OLED_Display“
verschieben, sodass das Hauptprogramm
entrümpelt wird und im Endeffekt tatsächlich nur den zentralen,
übergeordneten Quellkode enthält, während gleichzeitig jede Klasse ihre eigene Programmierung bezüglich der Funktionen usw. erhält. Auf diese
Weise wird sichergestellt, dass sich innerhalb der Klasse stets nur der Quellkode
befindet, der mit der Klasse und deren Programmierung zu tun hat (siehe
obenstehendes Bild). Nur so vermeidet man, dass
sich im Hauptprogramm im Laufe der
Zeit teils unterschiedlicher „Spaghetti“-Programmkode
ansammelt, der mit verschiedenen Aufgaben,
Funktionen und deren Klassen zu tun hat, gleichzeitig aber
die Lesbarkeit und das Verständis über die Funktionsweise des Programms erschwert, weil man
sich im Hauptprogramm erst mal
durch das Dickicht und das Gestrüpp schlagen muss, um zu erkennen, worum es
beim Programm wirklich geht. Wer sich aber im Unterholz im Wald verirrt hat
und umher irrt, der darf sich nicht wundern, dass er den Wald vor lauter
Bäumen nicht sieht! Wie man anhand des Quellkodes
im obenstehenden Bild sieht, gibt es in der Klasse „text_auf_OLED_Display“ insgesamt vier
Funktiononen von
denen drei in den Funktionsköpfen mit
den Parametern „zeile, y_offset, oled“ und zwei
mit dem Parameter „time“ zu tun haben: (Zum
Vergrößern bitte auf das Bild klicken!) Wenn man also den Programmblock der Klasse „text_auf_OLED_Display“ vom
Hauptprogramm des Programms „oled_demo-01-22.py“ ans untere Ende der Klasse „text_auf_OLED_Display“ des Programm „oled_demo-01-23.py“ verschiebt (siehe grüner Kasten), (Zum Vergrößern
bitte auf das Bild klicken!) dann muss man zwangsläufig
die bisherigen Funktionsköpfe, wie
bereits weiter oben gezeigt, um die entsprechenden Parameter „zeile, y_offset, oled“ und „time“ erweitern, damit diese auf die globalen Variablen zugreifen können. Das gilt
dann auch insbesondere für die entsprechenden Aufrufe der Funktionen (siehe grüne Kästen): (Zum
Vergrößern bitte auf das Bild klicken!) Beim Anpassen des
Programmkodes vom Programm „oled_demo-01-22.py“ ans untere Ende der Klasse „text_auf_OLED_Display“ im Programm „oled_demo-01-23.py“ fällt auf, das der Präfix auf die Klasse „text_auf_OLED_Display“ entfällt, · · · da sich die entsprechenden Funktionsaufrufe wegen
der Verschiebung nun selbst in der zugehörigen Klasse „text_auf_OLED_Display“ befinden! Abschließend muss noch
beachtet werden, dass das Statement „y_offset = 10“
ebenfalls in die Klasse „text_auf_OLED_Display“
verschoben werden muss. - Wenn das Programm „oled_demo-01-23.py“ einwandfrei läuft und sich im Hauptprogramm keinerlei Programmkode mehr befindet, haben
wir es geschafft, können wir das Programm mit dem Programm „micro_python-hallo_3-2.py“
zwecks Verwaltung der Namensliste verheiraten,
d.h. zum Programm „oled_demo-01-24.py“ zusammenfügen! Neben den bereits
beschriebenen Änderungen am Programmkode muss im Programm
„oled_demo-01-24.py“ noch der Funktionskopf der Funktion
„arbeite_mit_oled()“ auf „arbeite_mit_oled(oled)“ geändert
werden! Dies betrifft dann auch den Funktionsaufruf
„arbeite_mit_oled(oled)“ in
der nachfolgenden OLED-Anzeigetabelle „text_Str“:
Ziel der Zusammenführung der
beiden Programme „oled_demo-01-23.py“ und „micro_python-hallo_3-2.py“
zum neuen Programm „oled_demo-01-24.py“ ist es nämlich, den später im OLED-Display anzuzeigenden Text der Tabellen-Variablen „text_Str“ vom Programm, d.h. der Klasse „verwalte_Namensliste“,
dynamisch generieren zu lassen:
Zu diesem Zweck wird dann die
Klasse „verwalte_Namensliste“ in Klasse „verwalte_Textanzeigeliste“
umbenannt und aus den Vornamen wird
dann Textanzeigezeile (siehe
Programm „oled_demo-01-25.py“). - Wird demnächst fortgesetzt … … deshalb diese Webseite als Lesezeichen/Favorit abspeichern! |
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
[ Home ] [ Seitenanfang ] |
|