Vollgrafikanzeige mit Grafikbibliothek und Touchscreen
Ich habe hier plötzlich einen
Arduino
Uno mit ATmega328p sowie ein TFT-Display mit der Bezeichnung
2.8 ITDB02 Shield (Itead Studio) herumliegen.
Ungefähr das hier.
Was macht man damit?
Also Webseite besuchen, fürchterliche Datenblätter herunterladen
und Beispielprogramm austesten.
Immerhin ist da noch ein Touchscreen und ein
SD-Kartenleseschacht dran.
Der arme kleine Mikrocontroller! (Verwalte mal 32 Gigabyte mit 32 Kilobyte!)
Dafür gibt es jedoch vom Hersteller keinen Verweis auf Demo-Programme.
Es gibt auch keine. Bananen-Hardware? (Soll beim Anwender reifen.)
Das Display ist leider write-only angeschlossen,
damit ist Alpha-Transparenz nicht realisierbar.
Arduino-Kritik
Warum Arduino über drei Viertel der Weltbevölkerung
vom Programmieren ausschließt?
Gerade junge Leute, die Zielgruppe,
werden vom English-Only
eher abgeschreckt.
Da will man also ein kompliziertes Ding
in einer Fremdsprache mit blumigen Worten erklären.
Und behauptet, dass alles ganz einfach ist.
Das Bereitstellen von Unmengen von Beispielen
und magischen Bibliotheken zweifelhafter Qualität
hilft nicht, Kreativität zu fördern.
Computer denken nicht englisch, sondern in Zahlen.
Die sind sprachbarrierefrei.
Früher wusste jeder Programmierer, was ein Int21 ist.
Das musste man gar nicht übersetzen.
Heutzutage wird alles, aber auch alles, nur
in Englisch erklärt.
Mit unverständlichen Abkürzungen,
Schreibfehlern, die jedes Übersetzungsprogramm aushebeln,
und symbolischen Namen, die überflüssig sind.
Huh, da muss man auch noch eine fette Java-Programminstallation
über sich ergehen lassen.
Für jedes Betriebssystem extra, na klar.
Robuste Software sieht anders aus!
Mit Arduino hatte ich bis jetzt nichts zu tun.
Wie ich sogleich sah, das war auch gut so:
- Die Software ist riesengroß
aber ohne Debugger auch bloß ein Texteditor.
- Außer Syntaxhervorhebung bietet die Software nichts.
Kein IntelliSense, nicht mal ansatzweise.
Gerade Programmier-Anfänger sind auf Schreibunterstützung
und Kontexthilfe angewiesen.
- Kontextsensitive Hilfe ist nicht. Deutsch auch nicht.
Die paar deutschen Menüeinträge helfen da nicht drüberweg.
Eine deutsche Übersetzung des ATmega328-Datenblatts
liegt seit Mai 2016 vor: 5,5 MByte CHM statt 32 MByte PDF,
trotzdem ist alles drin!
- Funktionstasten sind lieblos verteilt, dafür gibts Vorbilder.
- Obwohl gcc-basiert ist alles völlig anders als beim
WinAVR:
100 % umlernen für das gleiche System.
Die Pinzuordnung ist ganz Arduino-typisch gelöst:
Mit langsamem Zugriff und hohem Speicherverbrauch.
Nämlich indirekt über Speicheradressen der Ports.
- Der Editor hat den lästigen Bug, dass man einzelne Tabs nicht
schließen kann.
Will man Ordnung machen, muss man ein neues Projekt erstellen.
Igitt!
(Wo auch immer er sich die Tabs merkt.)
- Wie man Compiler-Einstellungen vornimmt erschließt sich überhaupt
nicht. Etwa die Einstellungen des Optimierers
oder die Generierung von Listing-Dateien.
- Das schlimmste: Alle gefundenen Demo-Programme
passen nicht in den ATmega328p!
Lassen sich also gar nicht verwenden.
UTFT - ziemlich unbrauchbar
Die Demo-Programme basieren auf UTFT,
einer mickrigen Grafikbibliothek mit riesigem Speicherverbrauch.
Also erst mal alles nicht benötigte herausgeworfen und laufen gelassen:
Von dem was übrig bleibt sieht's schon mal ganz gut aus!
So wie's aussieht gibt's nichts besseres.
Daher habe ich als erstes ein WinAVR-Projekt draus gemacht
und den Arduino-Ramsch 'rausgeschmissen.
An einem Demo konnte ich die folgenden Features erkennen:
- Display-Drehung bei Initialisierung, nur 2 Richtungen
- Ausgabe von Text mit diktengleicher Schrift (ziemlich hässlich)
- Ausgabe von Bitmaps (nur Hi-Color) mit ganzzahliger Vergrößerung
- Linien, Rechtecke, Kreise, Rund-Rechtecke sowohl hohl als auch
ausgefüllt
- Angenehm schnelle Funktion
- Die Siebensegment-Schrift (nur 10 Ziffern) sieht hübsch aus,
aber hier wäre wohl eine Polygonausgabe angemessener
in Anbetracht der Speicherverschwendung
Implementiert aber ungesehen ist (weil Demo gekürzt werden musste):
- Frei rotierbarer Text
- Frei rotierbare Bitmaps
- Transparente Ausgabe von Text und Bitmaps
Anmerkung: Die Rund-Rechtecke sind mit festem Eckenradius.
Ellipsen gibt's nicht, die Display-Pixel müssen gefälligst 1:1 sein.
UTFT - noch einmal
Beim Blick auf das Disassemblerlisting
(die man mit der Arduino-Software auf Tod und Teufel
nicht zu Gesicht bekommt)
fand ich riesige Passagen identischen Kodes.
Was ist da los?
Also: Unfähiger Programmierer. (Fleißig aber unfähig.)
Sowas erwächst aus dem Arduino-System.
War kaum anders zu erwarten.
(Das gleiche Dilemma ist von VisualBasic bekannt.)
Ah, da findet sich eine memorysaver.h.
Mal alle Displays ausknipsen, die nicht gebraucht werden.
Wieso sind die per Default alle (~ 30) an?
Hm, komischer Verdacht:
Alles steckt in switch/case
statt in
#ifdef/#endif
-Konstrukten!
Wer kommt schon auf die Idee, an einen Mikrocontroller zwei
Displays dranzuhängen??
Wie man's richtig macht sieht man bei
V-USB:
Fähiger Programmierer.
Der nimmt auch keinen Arduino. Gut so.
Schade nur, auch hier kein Deutsch.
Also alle nicht benötigten Controller auch noch restlos
rausgeworfem, und die Code-Größe dampft auf erträgliche
20 Kilobyte ein.
Unter Verzicht auf Gleitkomma und damit der freien Rotation.
Würde sicherlich sowieso unleserlich aussehen, so ein schräger Font.
Im Prinzip habe ich's neu geschrieben, aber (klar!) unfertig und
mit folgenden Features:
- Auswahl dier Display-Eigenschaften per
#define
für minimale Code-Größe, aber auch nur 1 Display pro Controller
(sollte wirklich reichen)
- Display-Rotation in 4 Richtungen sowie gespiegelt wählbar
(wichtig für handgehaltene Geräte),
dabei werden die Spiegelungen bereits vom Controllerchip übernommen
Mögliche (ungespiegelte) Bildschirm-Ausrichtungen
- bitblt
(Bitmap-Transfer) in „8 Richtungen“
(X/Y-Tausch, X-Spiegelung, Y-Spiegelung)
für 1-Bit-Quelle (Flash-Speicher)
und 16-Bit-Quelle (
FILE*
, also universell)
mit Masken-Transparenz auch als Kernfunktion für die Schriftausgabe
Bitmaps können in alle Hauptrichtungen ausgegeben werden.
Es entscheidet orient[3]
sowie das Vorzeichen von w und h
- Rechteck-Clipping, auch für bitblts
(Das Display clippt zwar Pixelausgaben automatisch,
aber betrachtet nur 8 vertikale
und 9 horizontale Bits.)
Rechteck-Clipping in Aktion. Völlig außerhalb liegende Bitmaps und
Zeichen werden gar nicht erst ausgegeben
- Objekt-Variablen wie aktuelle Position und Nullpunkt
vereinfachen die Positionierung im Anwenderprogramm
und verringern die Code-Größe, da eine lange Übergabeparameterliste
vom avr-gcc nicht gut compiliert wird (liegt auch am Mikrocontroller).
- Proportionalschrift, speichersparend (bitweise hintereinander) abgelegt
und die Funktion
getTextExtent()
Das liefert die Funktion getTextExtent()
- Textausgabe in „8 Richtungen“ (siehe bitblt per orient[5:3])
und 4 Laufrichtungen (Escapements), was man so wahlfrei
nur für die Ausgabe von Chinesisch oder Arabisch braucht
Die vier Laufrichtungen der Schriftausgabe
- Punkte, Linien, Kreise, Rechtecke, hohl oder ausgefüllt wie bisher
nur eben mit Clipping
- Rund-Rechtecke mit Radiusvorgabe
als Basis für Kreise und Rechtecke (TODO)
- Linienausgabe wahlweise ohne (wie Windows)
oder mit (wie früher) Zielpunkt;
Rechteck-Ausgabe wahlweise inklusive (wie früher) oder exklusive
(wie Windows) der letzten Zeile und Spalte.
Die Windows-Variante hat rechentechnische Vorteile,
sonst hätte es Microsoft nicht so implementiert.
Das Demo enthält auch Kode für den Touchscreen, ganz simpel
zum Weiterschalten oder zum Pausieren.
Was fehlt und in eine abgeleitete Klasse gehört:
- Scrolling im Rechteckfenster (erfordert rücklesbares Display)
- 2D-Weltkoordinatensystem (Drehung, Scherung, Skalierung)
- Muster- und Gradientenfüllung
- Polygone und Polygonfüllung
- Linienbreite > 1 Pixel (das ist richtig schwierig!)
- Alpha-Transparenz (sofern das Display rücklesbar ist)
- Freie Rotation von Bitmaps und Ellipsen
- Kreisbögen und Splines
- Pfade und Pfad-Clipping
- Outline-Schriften
- In eine weitere Klasse:
OpenGL
für den 3D-Renderwahnsinn
- Speicher-Bitmap (wird u.a. für OpenGL benötigt)
Das alles ercheint nur sinnvoll für Mikrocontroller mit mindestens
16 Bit Verarbeitungsbreite und mindestens 64 KByte Flash-Speicher.
Der RAM-Verbrauch hält sich hingegen in Grenzen.
Hier ist Software
(Download).
Diese enthält eine make-basierte VisualStudio-2008-Projektdatei,
um den Quelltext mit IntelliSense bearbeiten zu können
und gleich in der Entwicklungsumgebung (IDE) übersetzen zu können.
Abgesehen dass diese IDE noch einiges fetter ist, nicht unter Linux läuft
und kein Deutsch kann, ist's auf Dauer trotzdem komfortabler.
Für die Filterung des gcc-Outputs wird
gccfilter
benötigt.
Die Datenblätter nochmal:
- DB0
- DB1
- DB2
- DB3
- GND
- IOVCC
- /CS
- RS
- WR
- RD
- NC
- X+
- Y+
- X-
- Y-
- A
- K1
- K2
- K3
- K4
- NC
- DB4
- DB8
- DB9
- DB10
- DB11
- DB12
- DB13
- DB14
- DB15
- RESET
- VCC
- IOVCC
- GND
- DB5
- DB6
- DB7
Rätselhaftes TFT
Für diesen Ebay-Artikel
(Suchworte TFT Arduino Uno R3)
ist weder Dokumentation noch ein Beispielprogramm aufzutreiben!
Alle UTFT-Displaytypen ausprobiert führte auch zu keiner Funktion.
Die Pinbeschriftung deutet weder auf den benutzten Controller hin,
noch ist klar wo und wie das Touchpanel angeschlossen ist.
Nur dass es 240 × 320 Pixel hat ist dokumentiert.
Bananen-Hardware also, oder gar ein Briefbeschwerer?
Also das Display gewaltsam von der Platine getrennt.
Auf der flexiblen Leiterplatte steht eine Bezeichnung:
FRD2803703.
Google fördert ein PDF mit der Anschlussbelegung der Flexleiterplatte
(siehe rechts) zu Tage, sowie den verwendeten TFT-Controllerchip:
ILI9341.
Keinen Schaltplan. Nicht mal einen unleserlichen.
Auf der Platine befindet sich ein Null-Ω-Widerstand mit der
Beschriftung R8 und R16.
Man hätte drauf kommen können, dass es sich dabei um die
Auswahl der Busbreite 8 bit oder 16 bit handelt.
Bestückt ist er als R8 auf 8 bit.
Da aber nirgends in der Doku zu entnehmen ist, wie
die IMx-Eingänge des ILI9341 beschaltet sind,
kam mir zunächst der Verdacht, dass man den Low-Teil ansteuern muss
und das Arduino-Shield, so wie's ist, gar nicht gehen kann.
Einige Experimente später kam schließlich raus, dass alles richtig
angeschlossen und verdrahtet ist.
Nur die UTFT-Bibliothek ist krankhaft konstruiert.
Die IM-Anschlüsse und Datenleitungen müssen wie folgt
beschaltet sein:
IM3 | IM2 | IM1 | IM0 | Modus | DB15:8 | DB7:0
|
---|
1 | 0 | 0 | 0
| 16-bit-Interface II | D17:10 | D8:1
|
1 | 8-bit-Interface II
|
Anschlussbelegung des Displays — nicht des Arduino-Shields
Immerhin unterstützt es das Rücklesen und damit Alpha-Blending
und Scrollen.
Der Pullup R1 auf der Unterseite wird nicht benötigt.
Die Touchpanel-Anschlüsse X+,X-,Y+,Y-
teilen sich die übrigen Datenleitungen wie folgt:
Elektrode | Signal | Arduino-Pin | ATmega328-Pin | ATmega328-Funktion | Ruhezustand | X messen | Y messen
|
---|
X- (links) | LCD_D7 | A1 | 24 | PC1 | ADC1 | Z | L | Z + messen
Y- (oben) | LCD_RS | ~6 | 10 | PD6 | - | L | Z | L
| X+ (rechts) | LCD_WR | 7 | 11 | PD7 | PCINT23 | Hi-Z + Interrupt | H | Z
| Y+ (unten) | LCD_D6 | A2 | 25 | PC2 | ADC2 | L | Z + messen | H
| |
Direkte Analogwertabfrage beim „TFT-Shield 2.8″ R3“
So, hier ist eine halbfertige aber
funktionierende Firmware
(Einsicht).
Dreh- und Angelpunkt ist eine "utft-config.h",
die ich mit der Arduino-Software leider ums Verderben willen
nicht in das Verzeichnis neben die .ino-Datei bekomme.
Touchscreen-Unterstützung fehlt auch noch.
2016: Andere TFT-Zuordnung
Siehe Datei Touchscreen.h.
Die TFT- und TouchScreen-Zuordnung ist immer noch etwas unglücklich gelöst
und erfordert das Herumspielen am
Makefile und der
utft-config.h.
Letzlich gibt es drei oder vier einigermaßen unabhängige Schräubchen zum Drehen:
- Display-Controller, Auflösung (für Kalender muss es 240×320 sein), Orientierung (hochkant und ungespiegelt)
- Portpin-Zuordnung zum Display-Controller, Bidirektionalität
- Portpin-Zuordnung zum Touchscreen
- falls vorhanden, Touchscreen-Controller (selten)
Elektrode | Signal | Arduino-Pin | ATmega328-Pin | ATmega328-Funktion
| Ruhezustand | X messen | Y messen
|
---|
X- (links) | LCD_D0 | 8 | 14 | PB0 | PCINT0 | Hi-Z + Interrupt | L | Z
|
Y- (oben) | LCD_RS | A3 | 26 | PC3 | ADC3 | L | Z + messen | L
|
X+ (rechts) | LCD_WR | A2 | 25 | PC2 | ADC2 | Z | H | Z + messen
Y+ (unten) | LCD_D6 | ~9 | 15 | PB1 | PCINT1 | L | Z | H
| |
Direkte Analogwertabfrage beim „2.4″TFT LCD SHIELD“
Firmwarestand von 2016 auf ILI9341.
Der Proportionalfont sieht fetzig aus
Seit August 2016 gibt es auch einen
Monatskalender
mit Editierfunktion.
Was man nicht sieht:
Vom Hauptbild geht es per Touch in drei Bereiche zu drei Unterprogrammen:
Touchscreen kalibrieren
|
Monatskalender | Uhr stellen
|
Die Klickbereiche sind hierbei
unkalibriert getrennt,
damit man überhaupt sinnvoll zum Kalibrier-Dialog kommt.
Zielgenauigkeit ist erst bei „Monatskalender“ und „Uhr stellen“ vonnöten.
Abfallkalender
Nach einigen Diskussionen mit den Besitzern solcher
Arduinos + TFT-Shields stellte sich doch noch eine
sinnvolle Anwendung heraus.
Natürlich nicht für Bewohner von Plattenbauten, wie ich,
sondern für Häuslebesitzer — ein Abfallkalender
oder kurz Müllkalender.
Dieser hängt in der Küche oder an der Hauseingangstür
und erinnert mit einer auffälligen Hintergrundfarbe daran,
die entsprechende Tonne an den Straßenrand zu stellen.
Von Vorteil ist der geringe Stromverbrauch von ca. 100 mA,
der sicherlich aus 80 % Hintergrundbeleuchtung besteht.
Die gleiche Lösung mit einem Raspberry wäre deutlich gefräßiger.
Die derzeitige Firmware zeigt die Aktion für den heutigen,
morgigen und übermorgigen Tag an, auch mehrere Aktionen pro Tag können
angezeigt werden.
Ein Großteil des Kodes kümmert sich um das Stellen der Uhr
mit dem Touchscreen.
Die UTFT-Bibliothek kommt nunmehr mit UTF-8 zurecht
und kann die Zeichenposition 0x80..0x9F im Windows-Zeichensatz CP1252
benutzen.
Für mehr als 256 Zeichen ist's aber erst mal nicht vorgesehen.
Zur perfekten Ablesbarkeit wurden zwei Proportionalschriften
mit 19 und 24 Pixeln Zellenhöhe und je 224 Zeichen eingebaut,
was trotzdem nur ca. 13 kByte Speicher verbraucht.
Das Konvertierungsprogramm für die
UB-PixelFontGenerator-Dateien
ist in awk geschrieben.
Die jetzige Implementierung ist mit einigen
Unvollständigkeiten verbunden:
- Da der Arduino keine batteriegepufferte Echtzeituhr hat,
wird zur Überbrückung von kurzen Stromausfällen die Zeit
jede Minute im EEPROM gerettet.
Aber nicht einfach so plump, sondern so ausgetüftelt,
dass jedes Bit von insgesamt 12 Bytes nur 1× pro Stunde
programmiert wird.
Atmel garantiert somit eine Lebensdauer von über 10 Jahren.
- Es ist kein Arduino-Projekt, sondern ein WinAVR-Projekt
(also avr-gcc).
Wie bereits oben erwähnt kann man sonst nicht die UTFT-Bibliothek
zentral führen und lokal (per Include-Datei) konfigurieren.
- Das Hintergrundbild ist vom UTFT-Demoprogramm
„übrig geblieben“ und garniert die ansonsten etwas lieblos
gestaltete Oberfläche. Es ist statisch.
Es wird auch der Wochentag angezeigt,
hier (Chemnitz) mit Sonnabend statt Samstag.
- Kalibrier-Tool für Touchpanel, aufzurufen durch Touch in obere Bildhälfte
- Feiertags-Anzeige (für Sachsen), Oster-Berechnung bis 2099
- Kalender-Editor per Touchscreen
- Alle Unter-Fenster haben ein Timeout (von 30 Sekunden) eingebaut,
damit nach dem Herumspielen durch Gäste letztlich immer der
Hauptbildschirm angezeigt wird
Aber so ein Arduino ist ja zum Dranherumspielen gemacht.
Der Flash-Speicher ist nun ziemlich voll.
Was man so noch einbauen könnte bzw. was vorsehbar ist:
- Batteriepufferung und 32-kHz-Uhrenquarz an Timer2
(erfordert Schaltungsänderung am Arduino)
- Stromausfall-Früherkennung (zum Speichern der Uhrzeit erst wenn nötig)
(erfordert Schaltungsänderung am Arduino)
- DCF77-Empfänger, am besten mit Wettervorhersage
- Fetziger Bildschirmschoner oder sonstige Untermalung
mit dem Ziel, die Pixel gleichmäßig abzunutzen
(etwa Scrollen des Kalenders zu verschiedenen Positionen)
- Dimmen der Hintergrundbeleuchtung je nach errechnetem Sonnenstand
(Software) oder Umgebungshelligkeit (Fototransistor)
- Verschiedene Kalender-Ansichten (bspw. mit morgen, übermorgen,
Wochenkalender, Monatskalender)
- Mondphasen-Anzeige,
Sonnen-, Mond-, Sternbild- und Planeten-Anzeige,
mehrere Kalender (chinesisch, iranisch, Hidschra u.ä.)
- Geburtstags-Erinnerung
- Akustischer Wecker (zum Schlafen), Kurzzeitwecker (zum Kochen),
erfordert Piepser; Komme-gleich-wieder-Anzeige;
Anzeige entgangener Anrufe (erfordert Verbindung zum Telefon sowie Hardware)
Funktionsfähige Firmware (Müllkalender)
für die beiden untersuchten Displays mit
- ILI9325 auf Shield-TFT-2.8, ein 2,8-Zoll-Display
- ILI9341 auf FRD2803703, ein 2,4-Zoll-Display
Da ich die beiden Displays nicht gleichzeitig zum Test da hatte,
leider mit getrennter UTFT-Bibliothek.
Rätselhaftes Display
Ein September 2016 geliefertes 2,4″-Touch-Display
mit der Aufschrift „S24GF31“ (auf dem Metallgehäuse),
der Prägung „LMS241GF31“
sowie „CK241_REV0.1“ und „IS9F01YOP1P“ auf dem Flexboard
erweist sich zwar ganz sicher als eines mit 240 × 320 Pixeln
(400 Pixel sind Quatsch, ich hab's nachgezählt),
aber mit dem Sketch „st7883.zip/examples/Mygraphicstest/Mygraphicstest.ino“
kommt auch nur ein zuckender (= kurzzeitig auf Schwarz umschaltender) weißer Bildschirm
mit einigen farbigen Pixeln heraus.
Immerhin, alle anderen Sketche zucken gar nicht.
Es könnte sich also tatsächlich um einen ST7883 handeln.
Aber ein Datenblatt dazu ist nicht zu finden.
Ob es ein S6D04H0 ist, muss sich noch erweisen.
Gelöst!
Das Display LMS241GF31 enthält den Chip S6D04H0,
welcher weitestgehend identisch zum ILI9341 ist,
nur die Initialisierungssequenz ist anders.
Siehe Quelltext-Abschnitt
der Initialisierungssequenz.
Damit funktionieren Programme wie die oben gezeigte
Müllkalender-Äpp
auch prompt mit diesem neuen Display.
Der Touchscreen verhält sich anscheinend wie bei älteren Displays
mit ILI9325 und funktioniert nun auch:
Elektrode | Signal | Arduino-Pin | ATmega328-Pin | ATmega328-Funktion | Ruhezustand | X messen | Y messen
|
---|
X- (links) | LCD_D7 | 7 | 11 | PD7 | PCINT23 | Hi-Z + Interrupt | L | Z
|
Y- (oben) | LCD_RS | A2 | 25 | PC2 | ADC2 | L | Z + messen | L
|
X+ (rechts) | LCD_WR | A1 | 24 | PC1 | ADC1 | Z | H | Z + messen
Y+ (unten) | LCD_D6 | ~6 | 10 | PD6 | - | L | Z | H
| |
Direkte Analogwertabfrage beim neuesten Arduino-Shield mit „LMS241GF31“
Noch eins mit ILI9481
Solche 3,5-Zoll-Displays sind (September 2016) preiswert zu kaufen,
haben mit 320 x 480 die doppelte Pixelzahl
und bieten angenehm viel Fläche — leider ohne Touch.
Die Initialisierungssequenz aus der originalen UTFT-Bibliothek eingebaut
läuft diese Version prompt los, nur bei der Rotation hapert's noch.
Siehe Quelltext.
Unbekanntes 2,4-Zoll-Display (August 2017)
Eine neue Lieferung enthält Displays mit der Aufschrift
2,4" TFT LCD SHIELD www.mcufriend.com.
Auf dem Blechmantel steht
M202110419 TFT1P5589-E.
Kein bisher bekannter Display-Chip. Hm.