Arduino mit TFT-Touchscreen

 

 

Früher wurde ein Mikrocontroller fast ausschließlich über ein paar Tasten bedient und die spärlichen Statusanzeigen konnten wir auf einer LCD-Anzeige ablesen. Schon eine hexadezimale Tastatur war im Grunde ein Luxus. Doch das ist lange her. 

 

Heute sind wir in der Lage, selbst eine kleine Arduino-Steuerung komfortabel über einen TFT-Monitor mit integriertem Touchscreen zu steuern. Dabei ist nicht nur der hardwaremäßige Aufbau absolut simpel, dank der vorhandenen Bibliotheken wird auch die Programmierung zum reinen Vergnügen. In diesem kleinen Tutorial möchte ich Ihnen praktisch alle Funktionen vorstellen, die Sie brauchen, um hochwertige grafische Oberflächen auf Ihren Arduino zu zaubern.

Wenn Sie besonders komfortabel optisch attraktive und flexible Bedienerschnittstellen erstellen möchten, sollten Sie unbedingt einen Blick auf die Produkte von 4D Systems  werfen, die wir Ihnen auf unserer Seite "Displays und Touchscreens" anbieten.

Wir nutzen für dieses Tutorial das TFT-Arduino-Shield 30-99-1012 mit 2,8 Zoll großer Anzeige. 

 

Arduino_TFT_1

 

Das Shield wird einfach auf ein Arduino-Board gesteckt, es sind also keinerlei Verdrahtungen notwendig. Für die komfortable Programmierung laden wir uns 2 Bibliotheken herunter:

SEED-Studio Bibliothek für TFT-Anzeige

SEED-Studio Bilbliothek für Touchscreen

Nachdem Sie die beiden Archive heruntergeladen und entpackt haben, benennen Sie sie bitte um, denn die Archivnamen enthalten Sonderzeichen mit denen die Arduino-IDE nicht klar kommt. Wählen Sie z. B. die Namen "TFTV2" und "Touchscreen". Die Wahl bleibt Ihnen aber überlassen. Jetzt kopieren Sie die beiden Ordner in das "libraries"-Verzeichnis in Ihrer Arduino-Installation.

Rufen Sie die Arduino IDE auf und im Menü "Beispiele" finden Sie jetzt die Einträge mit den einzelnen Beispielen:

 

Auswahlmenue

 

Farben und Positionen

 

Wir wollen aber in diesem Tutorial Schritt für Schritt eigene Programme aufbauen und auch Methoden ausprobieren, die in den Beispielen nicht beschrieben sind. Deshalb erstellen wir einen eigenen Sketch und nennen ihn "tft_test_1".

 

tft_test_1 

 

Zunächst binden wir die TFT-Bibliothek und die SPI-Schnittstelle ein, denn das Modul wird über SPI angesprochen, aber das soll uns weiter gar nicht stören, denn diese Abläufe werden über die Bibliotheks-Methoden ausgeführt. Die erste Methode, die wir benötigen ist "TFTInit()", mit der wir die Anzeige initialisieren. Danach ist sie auch schon einsatzbereit. 

Die grundlegendste Grafikfunktion ist das Setzen des Farbregisters eines bestimmten Bildpunktes (Pixel). Damit wird der Bildpunkt sichtbar. In unserem Fall gibt es dafür die Methode "setPixel(x,y,color)". Mit x und y geben wir die Koordinaten an. Wenn wir das Display mit dem USB-Stecker nach unten halten (Hochformat) befindet sich die Koordinate 0,0 oben links. Die Maximalwerte sind 240 in X-Richtung und 320 in Y-Richtung.

 

Koordinatensystem 

 

Im Querformat liegt der Ursprung unten links, idael für die Anzeige von Messwerten. 

Der 3. Parameter bestimmt die Farbe. Dabei können wir vordefinierte Werte (RED, BLUE, GREEN etc.) nutzen oder aber die Farbe selbst festlegen. Dafür steht für jeden Bildpunkt ein 16-Bit-Farbinformation zur Verfügung, die sich wie folgt zusammensetzt:

 

Farbregister

 

Die untersten 5 Bit legen den Blau-Anteil fest, die mittleren 6 Bit den Grün-Anteil und die oberen 5 Bit wiederum den Rot-Anteil. Dieses Format wird als RGB565 bezeichnet. Für reines Rot wäre der Wert F800, Grün erreicht man durch 07E0 und Blau schließlich mit 001F. 

Wenn Sie das obige Programm einmal ausgeführt haben, dann müssen Sie schon wirklich genau hinschauen, um den roten Punkt überhaupt erkennen zu können, denn ein einzelnes Pixel ist wirklich sehr klein. Wir wollen im 2. Schritt deshalb eine größere Fläche definieren und einen Zufallsfarbwechsler programmieren.

 

Einfache Grafikbefehle

 

Für geometrische Figuren gibt es einige Befehl in der TFT-Bibliothek: 

  • drawRectangle(x,y,breite,höhe,farbe) zeichnet die Umrisse eines Rechtecks mit der angegebenen Linienfarbe
  • fillRectangle(x,y,breite,höhe,farbe) zeichnet ein gefülltes Rechteck in der angegebenen Füllfarbe
  • drawCircle(x,y,r,farbe) zeichnet den Umkreis mit Mittelpunkt x, y mit dem Radius r in der angegebenen Farbe
  • fillCircle(x,y,r,farbe) zeichnet einen gefüllten Kreis
  • drawTriangle(x1,y1,x2,y2,x3,y3,farbe) zeichnet ein Dreieck mit den angegebenen Eckpunkten
  • fillScreen(x1,y1,x2,y2,farbe) zeichnet ein gefülltes Rechteck mit den angegebenen Eckpunkten  

Die Befehle "fillTriangle()" sowie drawScreen() gibt es allerdings (zmindest momentan noch) nicht. 

Wir wollen jetzt ein kleines Rechteck zeichnen dessen Füllfarbe sich ständig ändert. Dazu zählen wir den Farbwert einfach kontinuierlich hoch.

 

Farbwechsler_1

 

Das Programm zeichnet wie gewünscht ein kleines Rechteck mit den Koordinaten 110, 150 und 130, 170. Da der Mittelpunkt des Bildschirms bei 120, 160 liegt, befindet sich das Rechteck genau in der Mitte. Wenn Sie das Programm so eingeben und laufen lassen, ist das Ergebnis allerdings kein kontinuierlicher Farbwechsler, sondern ein flackerndes Rechteck. Der Grund:

Wir starten mit 00000.000000.00000 und erhöhen zunächst nur den Blauanteil, bis er sein Maximum erreicht hat: 00000.000000.11111. Beim nächsten Wert wird der Blauanteil wieder auf 0 gesetzt und für Rot erhalten wir den Wert 1 (00000.000001.00000), das entspricht aber fast Schwarz. Nun wird wieder der Blauanteil erhöht und nach dem nächsten Maximalwert (00000.000001.11111) springt der Zähler auf 00000.000010.00000), was wiederum einem fast schwarzen Rechteck entspricht. So klappt das also mit unserem Farbwechsler noch nicht.

Wir müssen folgende Logik erreichen: Zunächst wird der Blauanteil hochgezählt, ist das Maximum von 31 erreicht (0x1f) erhöhen wir nicht mehr um 1, sondern um 32, dadurch bleibt der Blautanteil konstant auf 31. Wird der Wert von 2047 erreicht (0x7FF) sind sowohl Blau als auch Grün auf Maximum und es beginnt der Rotanteil, den wir durch Erhöhen um jeweils 2048 erreichen.

Wir müssen aber noch bedenken, dass die Schleife dieses Mal viel weniger Schritte durchläuft und deshalb verzögern wir jeden Schritt um 50 ms. Schauen wir uns einmal an, ob die Theorie auch der Praxis entspricht. Das komplette Code sieht wie folgt aus:

 

Farbwechsel_2

 

Es ist zwar kein richtiger Farbwechsler, aber die Programmlogik stimmt. Die Farbe wechselt von schwarz nach blau, dann zu hellem Türkis und schließlich zu Weiß. Rot oder Grün sehen wir so nicht, weil ja immer der Blauanteil konstant bleibt. Experimentieren Sie doch ein wenig mit dem Farbregister, wenn Sie z. B. um 31 und nicht um 32 erhöhen, dann reduzieren Sie den Blauanteil und erhöhen den Grünanteil. 

 

Ausgabe von Texten

Es wäre natürlich äußerst mühsam, wenn wir für die Augabe von Texten auf einfache Grafikfunktionen zugreifen müssten. Aber das müssen wir natürlich auch nicht. Es gibt gleich mehrere Methoden für die Darstellung von Texten und Zahlen. Im einzelnen sind dies:

  • drawNumber(number, x, y, size, color) 
  • drawFloat(number, x, y, size, color)
  • drawFloat(number, decimal, x, y, size, color) *decimal gibt die Anzahl der Nachkommastellen an
  • drawChar(*string, x, y, size, color) gibt einen einzelnen Buchstaben aus
  • drawString(const *string, x, y, size, color) gibt eine Zeichenkette aus

 

Eine Messwertausgabe könnte wie folgt aussehen:

 

Messwertausgabe

 

Wir geben zunächst den String "Messwert:" an der gewünschten Stelle aus und in der loop-Funktion lesen wir den Analogwert ein. Den geben wir dann direkt unter dem Label aus. Wir brauchen aber noch eine weitere Funktion und zwar ein Rechteck, das ständig neu gezeichnet wird. Das dient uns zum einen als Hintergrund, auf der anderen Seite löscht es aber auch den Vorgängerwert. Ohne dieses ständige Überzeichnen würden die alten Werte bestehen bleiben und irgendwann würden Sie nur noch rote Rechtecke sehen.

Das Ergebnis sieht folgendermaßen aus:

 

Messwert 

 

Mini-Oszilloskop

 

Genug der Farben, wir wollen jetzt ein kleines Oszilloskop realisieren. Dabei geht es nur um die Grundfunktion der Messkurvendarstellung. Wir nutzen einfach einen offenen Analogeingang und zwar A4, weil A0 bis A3 vom Touchscreen genutzt werden. Wir lesen also einfach den Wert ein, der auf A4 anliegt. Da es sich bei den AD-Wandlern des benutzten Arduino-UNO-Boards um einen 10-Bit-Wandler handelt ist seine Auflösung 1024. Wenn wir den Bildschirm im Querformat nutzen wollen, stehen und aber nur 240 y-Werte zur Verfügung, also müssen wir den Messwert durch 5 teilen, damit erhalten wir maximal 204 Werte. Für eine Demonstration soll das reichen. Gehen wir das Programm Schritt für Schritt durch:

 

Oszilloskop 

 

Wir definieren einige Variablen für die x- und y-Werte und konfigurieren A4 als Eingang. Im loop()-Teil löschen wir zunächst einmal den gesamten Bildschirm mit Tft.fillScreen(). Dann lesen wir A4 ein, speichern den Wert in iY0 und teilen ihn durch 5. Für den ersten Messwert setzen wir einfach nur einen Punkt an der x-Position 0 mit dem y-Wert iY0. Da wir im Querformat arbeiten, müssen wir bei der Übergabe der Parameter x und y vertauschen. 

Jetzt kommen wir zu der eigentlichen Messkurve. Würden wir alle Werte nur mit setPixel() setzen wäre das Ergebnis eine Punktwolke. Anschaulicher wird es allerdings wenn wir eine Linie vom neuen Messwert zum alten ziehen. So bekommen wir eine richtige Kurve. Deshalb lesen wir den neuen Wert in iY1 ein und ziehen dann mit Tft.drawLine() eine Linie vom Vorgängerwert zur aktuellen Position. Auch hier bitte drauf achten, dass y und x wieder vertauscht werden müssen. Das Ergebnis sehen Sie im Video:

 

TFT_Oszilloskop_First_Frame

 

Das sieht schon sehr nach einem Oszilloskop aus. Was noch fehlt wären ein Messgitter und eventuell eine Bechriftung. Das Messgitter können Sie einfach über die Linienfunktion erzeugen, indem Sie in einem bestimmten x-Abstand Linien von ganz unten bis ganz oben zeichnen und das selbe in einem bestimmten y-Abstand für die waagerechten Gitter.

 

Programmierung des Touchscreens

 

Jetzt haben wir alle Funktionen der Anzeige kennen gelernt, bleibt uns nur noch der Touchscreen selbst. Ein Tochscreen ist etwas komplizierter aufgebaut, als eine herkömmliche Tastatur. Wir benötigen 4 analoge Eingänge, um die Zeilen- und Spaltenwiderstände zu ermitteln sowie für die Erfassung des Anpressdrucks. Wir wollen zunächst nur die Position erfassen und über die serielle Schnittstellel ausgeben, um das Prinzip zu verstehen. Das Programmm dazu:

 

touch_prog_1

 

Nach der Definition der Analogeingänge, legen wir die Grenzwerte für X-Minimum, X-Maximum, Y-Minimum und Y-Maximum fest. Das sind die Werte, die wir einlesen, wenn der Bildschirm an den entsprechenden Positionen berührt wird. Die Werte werden vom TFT-Hersteller angegeben. Anschließend erzeugen wir eine Tochscreen-Instanz und übergeben dem Konstruktor die Angaben für die Analogeingänge.

In der loop-Funktion erzeugen wir ein Objekt vom Typ "Point" und holen über die Methode ts.getPoint() die aktuellen Koordinaten. Im Point-Objekt sind die x- und y-Werte für die Position aber auch ein z-Wert für den Druck vorhanden. Jetzt folgt die Arduino-Funktion map(), mit der wir einen Wert skalieren können, denn bei 0 haben wir den Wert x = 232 und y = 166. Wir wollen aber korrekte Koordinaten und die erhalten wir mit dem Ausdruck:

p.x = map(p.x, TS_MINX, TS_MAXX, 0 , 240)

Dadurch wird der eingelesene x-Wert vom Bereich TS_MINX bis TX_MAXX auf 0 bis 240 skaliert und an p.x zurückgegeben. Das gleiche machen wird mit dem y-Wert.

In der if-Schleife wird abgefragt, ob der Anpressdruck größer als 10 ist und danach werden die Daten auf der seriellen Schnittstelle ausgegeben. Das Ergebnis sieht dann folgendermaßen aus, wenn Sie z. b. mit dem Finger von oben links  eine Linie ziehen: 

 

touch_output_1

 

Im nächsten Programm erstellen wir eine ganz simple Tastatur. Sie soll lediglich aus vier Feldern ganz oben am Bildschirm bestehen. Berühren wir ein Feld soll der darunterliegende freie Bildschirm mit einer bestimmten Farbe gefüllt werden. Das Programm:

 

Tastatur

 

Zunächst zeichnen wir mit den drawLine()-Methoden die Linien für die vier Felder am oberen Bildschirmrand. Im loop-Teil holen wir wieder unsere Koordinaten und fragen in einer if-Schleife, falls der Druck ausreichend ist, welches Feld berührt wurde. In Abhängigkeit davon färben wir den Bildschirm darunter.

Das Ergebnis sieht dann folgendermaßen aus, allerdings werden durch die Videokamera die Farben stark verfälscht.

 

Touchscreen_First_Frame

 
 

Für weitere Informationen und Bestellungen des     2.8" TFT-Touchscreen

einfach auf nachfolgenden Link klicken:   2.8" TFT-Touchscreen

 

 

Falls Sie Fragen zum Thema haben, wenden Sie sich einfach an uns.

Wir helfen Ihnen gern weiter!

 

Ihr Team von Böcker Systemelektronik

 

Hinweis: Unser Tutorialangebot wird in unregelmäßigen Abständen erweitert. Wenn Sie sofort über eine Neuerscheinung informiert werden möchten, tragen Sie sich bitte hier in unsere Benachrichtigungsliste "Tutorials" ein. Sie können diesen unverbindlichen Service jederzeit in Ihrem Kundenkonto oder per E-Mail wieder abbestellen.  

 

 

 
 
 

Copyright © Böcker Systemelektronik