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 1 Kilobyte RAM!) 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 und (einfachere) binäre Rasteroperationen nicht realisierbar. Zudem lässt sich so kein echtes Scrolling realisieren. Scrollen muss durch kompletten Bildneuaufbau realisiert werden.

Arduino-Kritik

Huh, da muss man auch noch eine fette Java-Programm­installation über sich ergehen lassen. Für jedes Betriebs­system 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:

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:

Implementiert aber ungesehen weil Demo gekürzt werden musste:

Anmerkung: Die Rund-Rechtecke sind mit festem Eckenradius. Ellipsen gibt's nicht, die Display-Pixel müssen gefälligst vom Seitenverhältnis 1:1 sein.

Richtungsweisend für mich war die Von-Neumannisierung von String-Zeigern mit dem Makro F. Das funktioniert am besten für AVR-Mikrocontroller mit ≤ 32 KByte Flash. Dafür ist das hervorragend für ATtinys geeignet, insbesondere rund um das Thema USB und seine Deskriptoren. Im Nachhinein betrachtet ist es schade, dass avr-gcc bzw. WinAVR nicht diesen Weg gegangen ist. Es hätte die unsäglichen Routinen aus avr/pgmspace.h wie memcpy_P und printf_P erspart.

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:

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:

Das alles erscheint nur sinnvoll für Mikro­controller mit mindestens 16 Bit Verarbeitungs­breite und mindestens 64 KByte Flash-Speicher. Der RAM-Verbrauch hält sich hingegen in Grenzen. Daher sind alle diese Displays Kandidaten für STM32F103 und STM32F401.

Software
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:

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-Ohm-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:

Anschlussbelegung des Displays — nicht des Arduino-Shields
IM3IM2IM1IM0ModusDB15:8DB7:0
1000 16-bit-Interface IID17:10D8:1
18-bit-Interface II

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:

Direkte Analogwertabfrage beim „TFT-Shield 2.8″ R3“
ElektrodeSignalArduino-PinATmega328-PinATmega328-FunktionRuhezustandX messenY messen
X- (links) LCD_D7A124PC1ADC1 Z L Z + messen
Y- (oben) LCD_RS~610PD6- L Z L
X+ (rechts)LCD_WR 711PD7PCINT23Hi-Z + InterruptH Z
Y+ (unten) LCD_D6A225PC2ADC2 L Z + messenH

So, hier ist eine halbfertige aber funktionierende Firmware. 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:

Direkte Analogwertabfrage beim „2.4″TFT LCD SHIELD“
ElektrodeSignalArduino-PinATmega328-PinATmega328-Funktion RuhezustandX messenY messen
X- (links) LCD_D0 814PB0PCINT0Hi-Z + InterruptL Z
Y- (oben) LCD_RSA326PC3ADC3 L Z + messenL
X+ (rechts)LCD_WRA225PC2ADC2 Z H Z + messen
Y+ (unten) LCD_D6~915PB1PCINT1L Z H

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 Hintergrund­farbe daran, die entsprechende Tonne an den Straßenrand zu stellen. Von Vorteil ist der geringe Stromverbrauch von ca. 100 mA, der sicherlich aus 80 % Hintergrund­beleuchtung besteht. Die gleiche Lösung mit einem Raspberry Pi wäre deutlich gefräßiger — und teurer.

Die 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 Proportional­schriften mit 19 und 24 Pixeln Zellenhöhe und je 224 Zeichen eingebaut, was trotzdem nur ca. 13 kByte Speicher verbraucht. Das Konvertierungs­programm für die UB-PixelFontGenerator-Dateien ist in awk geschrieben.

Die jetzige Implementierung ist mit einigen Unvollständigkeiten verbunden:

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:

Funktionsfähige Firmware (Müllkalender) für die beiden untersuchten Displays mit 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:

Direkte Analogwertabfrage beim neuesten Arduino-Shield mit „LMS241GF31“
ElektrodeSignalArduino-PinATmega328-PinATmega328-FunktionRuhezustandX messenY messen
X- (links) LCD_D7711PD7PCINT23Hi-Z + InterruptLZ
Y- (oben) LCD_RSA225PC2ADC2LZ + messenL
X+ (rechts)LCD_WRA124PC1ADC1ZHZ + messen
Y+ (unten) LCD_D6~610PD6-LZH

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.