Rothschopf Werner

rowex ganz privat

Angebote

Arduino: Deutsche Umlaute am LCD (liquid crystal I2C)

LC-Displays ermöglichen die einfache Darstellung von Zeichen mit dem Arduino. Bei Verwendung der I2C Schnittstelle werden nur  zwei Pins vom Arduino benötigt. Üblicherweise wird dazu die Liquid Crystal I2C verwendet. Leider ist die Ausgabe der deutschen Umlaute (ä ö ü) oder dem scharfen s (ß) nicht ganz einfach.

Prinzipiell gibt es für die Anzeige folgende Möglichkeiten:

  • Umlaute als Custom Characters erstellen
  • Spezielle Steuersequenzen für die Umlaute verwenden
  • Man passt die Liquid Crystal Library so an, dass Sonderzeichen (deutsche Umlaute, scharfes s, ...) ordnungsgemäß am LCD angezeigt wird

Die ersten beiden Möglichkeiten findet man leicht im Internet. Hier stelle ich meine Noiasca Liquid Crystal I2C vor die alles im Hintergrund erledigt.

Umlaute als Custom Characters am LCD

Man könnte die Umlaute als Custom Characters definieren. Mit den 8 zur Verfügung stehenden Custom Characters kann man die großen und kleinen Umlaute sowie das ß unterbringen. Leider löst das noch nicht der einfachen Ausgabe. Ich wollte daher eine neue Library erstellen, die in der Lage ist mit den bekannten .print Anweisungen Umlaute und Sonderzeichen darzustellen. Mir war das zu unpraktisch, daher habe ich eine neue LCD Library erstellt.

Teaser: Das kann die neue LCD Library mit deutschen Umlauten

Deutsche Umlaute und das scharfe-S (ß) werden im Fließtext dargestellt. Große Umlaute stehen mit einem speziellen Konstruktor auch zur Verfügung. Dazu gibt es am Ende mehr:

LCD mit deutschen Umlauten für Arduino

Die Ausgabe erfolgt mit einem normalen .print()

lcd.print("ÄäÖöÜüß");

Wir haben jetzt einen einfachen Zugriff auf einige griechische Buchstaben, wie man Sie in der Mathematik benötigt. Beispielsweise das µ (mu) oder Σ (Sigma) ist enthalten:

LCD mit griechischen Buchstaben für Arduino

(alpha, beta, epsilon, pi, mu, rho, Sigma)

Weiters gibt es eine Menge an Sonderzeichen, die im ROM des LC-Displays vorhanden sind. Das Grad-Zeichen und die Pfeile finden sicher eine Verwendung:

Sonderzeichen am LCD für Arduino

(Degree, Division, middle Point, n with tilde, Pound, Yen, Tilde, Sqareroot, Proportional to, Infinity, Left Arrow, Right Arrow, Backslash)

Hintergründe zur "Noiasca LCD Library I2C"

Am Ende der Seite (bei den Links) steht die neue LCD Library zum Download zur Verfügung. Ich will aber auch für den interessierten Leser erklären, was dazu notwendig war.

Ausgangsbasis für die Änderungen war die "Adafruit Liquid Crystal I2C" in der Version 1.2.1 von Frank de Brabander die zwischenzeitlich von Marco Schwartz gewartet wird. Ich habe mich für die I2C Variante entschieden, da ich davon ausgehe, dass die meisten Anwender die zweipolige Verkabelung vorziehen.

Der Zeichensatz des LC Displays

Eigentlich findet man im Zeichensatz (ROM Code A00) eines Hitachi HD44780U kompatiblen LCDs viele Sonderzeichen. Es gibt dabei drei Herausforderungen:

  • Im unteren Bereich (bis 127) sind einige Zeichen "falsch" (In der Zeichensatztabelle rot markiert). Statt dem Backslash ist ein Yen Zeichen, die Tilde musste einem "Pfeil nach Rechts" weichen. Außerdem gibt es noch einen Pfeil nach Links.
  • Die für uns interessanten Sonderzeichen (ä, ö, ü, ß) sind zwar im ROM vorhanden, liegen aber an anderen Adressen (am Bild grün markiert). Die Großbuchstaben Ä Ö Ü sind nicht vorhanden
  • "Sonderzeichen" werden als UTF-8 gesendet. Das heißt ein Zeichen kann aus bis zu 4 Bytes bestehen. Dazu unten noch mehr.

Auf Basis des Zeichensatzes im Datenblatt ergeben sich somit für uns folgende relevante Abweichungen von UTF-8:

Alle Sonderzeichen inkl. deutscher Umlaute am LCD für Arduino

Übrigens, es gibt im Datenblatt noch einen Zeichensatz ROM A02. Der Schwerpunkt von ROM A02 sind kyrillische Zeichen und europäische Sonderzeichen - auch große Umlaute gäbe es darin. Meine bisher gekauften LC-Displays haben jedoch alle das ROM A00, weshalb meine Änderungen nur für diese LCDs entstanden sind.

Die UTF-8 Zeichencodierung

UTF-8 ist eine weit verbreitete Zeichencodierung. UTF-8 ist in den ersten 128 Zeichen (Indizes 0–127) deckungsgleich mit ASCII.

Die Zeichen können mit bis zu 4 Byte kodiert sein. Das ist auch der Grund, warum bei der Ausgabe von beispielsweise ä zwei "japanische" Zeichen am Display dargestellt werden. Genauer: es sind Katakana Schriftzeichen halber Breite aus dem UTF-8 Bereich 0xFF65-0xFF9F.  ä wird in UTF-8 als 0xC3A4 codiert. Es ist ein zwei Byte Zeichen. Daher erfolgt die Ausgabe des Zeichens 0xC3 (das tanzende Männchen) und 0xA4 (der kurze schräge Strich).

In der nachfolgenen Tabelle sind exemplarisch einige Zeichen aus der neuen Library angeführt inklusive dem Mapping auf den ROM A00 Zeichensatz des LCD Treibers.

char UTF-8 A00 Name
\ 5C 7C REVERSE SOLIDUS ("Backslash")
~ 7E 2D TILDE
£ C2 A3 ED POUND SIGN
¥ C2 A5 5C YEN SIGN
° C2 B0 DF DEGREE SIGN
µ C2 B5 E4 MICRO SIGN
· C2 B7 A5 MIDDLE DOT
ä C3 A4 E1 LATIN SMALL LETTER A WITH DIAERESIS
ö C3 B6 EF LATIN SMALL LETTER O WITH DIAERESIS
ü C3 BC F5 LATIN SMALL LETTER U WITH DIAERESIS
Ä C3 84 E1 LATIN CAPITAL LETTER A WITH DIAERESIS
Ö C3 96 EF LATIN CAPITAL LETTER O WITH DIAERESIS
Ü C3 9C F5 LATIN CAPITAL LETTER U WITH DIAERESIS
ß C3 9F E2 LATIN SMALL LETTER SHARP S
ñ C3 B1 EE LATIN SMALL LETTER N WITH TILDE
÷ C3 B7 FD DIVISION SIGN
ñ C6 9F F2 LATIN CAPITAL LETTER O WITH MIDDLE TILDE
Σ CE A3 F6 GREEK CAPITAL LETTER SIGMA
α CE B1 E0 GREEK SMALL LETTER ALPHA
β CE B2 E2 GREEK SMALL LETTER BETA
ε CE B5 E3 GREEK SMALL LETTER EPSILON
μ CE BC E4 GREEK SMALL LETTER MU
π CF 80 F7 GREEK SMALL LETTER PI
ρ CF 80 E6 GREEK SMALL LETTER RHO
E2 86 90 7F LEFTWARDS ARROW
E2 86 92 7E RIGHTWARDS ARROW
E2 88 E8 E8 SQUARE ROOT
E2 88 9D E0 PROPORTIONAL TO
E2 88 9E F3 INFINITY

 

Letztere Zeichen sind Beispiele für 3 Byte Zeichen.

  • Beginnt ein Zeichen mit 0b11xxxxxx (0xC0 aufwärts), ist generell mit Folgezeichen zu rechnen.
  • 0b110xxxxx Startbyte und ein Folgezeichen, die deutschen Umlaute sind z.B. derartige Sonderzeichen
  • 0b1110xxxx (0xE0 und höher) Startbyte und zwei Folgezeichen (z.B. das Wurzelzeichen)
  • 0b11110xxx (0xF0 und höher) Startbyte und drei Folgezeichen

Das klingt jetzt komplizierter als es ist. Im Wikipedia Link (Verlinkt am Ende der Seite) ist es gut beschrieben.

Adaptierung der .write Methode für einwandfreies .print

Ich musste daher die Library derartig ändern, dass die .write Methode, mit Multi-Byte Zeichen korrekt umgehen kann. Warum die .write Methode? Lange Geschichte ganz kurz: die LCD Library erbt von der Print Klasse die .write() Methode. Die .write() Methode druckt ein Zeichen. Die .print() Methode ruft die .write() Methode für jedes benötigte Zeichen auf bzw. kümmert sich auch um die formatierte Ausgabe (z.B. die über die Zusatzparameter HEX oder BIN bei Zahlen).

Da .write() immer nur ein Zeichen von .print() bekommt, merkt sich die Library einer Variable special, dass ein Steuerzeichen (z.B. 0xC2) gesendet wurde. Derartige Steuerzeichen geben wir nicht mehr aus (zumindest wenn es als erstes Byte ankommt). Beim nächsten Aufruf von .write(), ermittelt die Library dann das entsprechende Sonderzeichen. Im Prinzip hat die neue .write() Methode nur viele If und Switch-Case Anweisungen um dieses Mapping zu ermöglichen. Damit erklärt sich auch der größere Programmspeicherbedarf der Library.

Zugriff auf Sonderzeichen mit .writeOld()

Wenn du heute schon einzelne ROM-Sonderzeichen mit der .write() Methode schreibst, so müssen diese Aufrufe auf .writeOld() geändert werde. Mit .writeOld() wird die neue Logik umgangen und die Ausgabe des Sonderzeichens erfolgt wie in der originalen Library. Die Verwendung ist einfach:

lcd.writeOld(0xE1); // Ausgabe eines ä

Betroffen sind alle Sonderzeichen im ROM ab 0xC0. Darunter fallen auch die manchmal verwendeten 0xE1 (ä), 0xEF (ö), 0xF5 (ü) und 0xE2 (ß). Mit Einsatz der neuen Library wäre aber ohnehin das direkte Schreiben der Umlaute unterstützt.

Nicht davon betroffen ist die Ausgabe von Special Characters / Custom Characters. Diese können weiterhin mit lcd.write(0) bis lcd.write(7) ausgegeben werden. Der Grund ist einfach erklärt: 0 - 7 liegt unter 0xC0 und wird somit auch von .write() unverändert ausgegeben.

Darstellungsvarianten der großen Umlaute Ä Ö Ü

Ab Version 1.0.1 unterstützt die Library mehrere Darstellungsvarianten für die großen Umlaute. Die Auswahl der jeweiligen Variante geschieht mit unterschiedlichen Konstruktoren.

Das Beispiel "03 German Umlauts" enthält alle verfügbaren Konstruktoren und zeigt, wie die unterschiedlichen Varianten verwendet werden können.

LiquidCrystal_I2C_Large lcd(addr, cols, rows);       // Ä --> A

Der Standard Konstruktor benötigt am wenigsten Programmspeicher und ist gut lesbar. Die Umlaute Ä Ö Ü werden durch die einfachen Zeichen A O U ersetzt. Die Variante ist verwendbar, wenn man die Unterscheidung groß/klein Benötigt, aber nicht zu viel Speicher verwenden möchte.

 

LiquidCrystal_I2C_Small lcd(addr, cols, rows);             // Ä --> ä

Der Small Konstruktor ersetzt die großen Umlaute gegen kleine Umlaute. Das kleine ö auf einem LC Display ist gerade einmal ein Pixel niedriger als für ein großes Ö zur Verfügung stehen würde. Ähnlich beim ü - Ü. Nur beim Ä /ä fällt der Unterschied deutlicher auf. Bei 446 gelisteten Wörtern die mit Ä beginnen ist das aber verschmerzbar.

LiquidCrystal_I2C_Ae lcd(addr, cols, rows);          // Ä --> Ae

Mit dem _Ae Konstruktor werden die großen Umlaute gegen Ae, Oe, Ue substituiert. Bei dieser Variante muss man acht gegben, da durch die Ersetzung je großem Umlaut zwei Zeichen dargestellt werden.

LiquidCrystal_I2C_Special lcd(addr, cols, rows);   // Ä --> Ä 

Mit dem _Special Konstruktor werden die großen Umlaute mit Hilfe von "Custom Characters" korrekt dargestellt. Dafür werden die drei letzten "Special Characters" (auch Custom Characters) 5, 6 und 7 verwendet und stehen für eigene Sketche nicht mehr zur Verfügung. Diese Variante sieht zwar am besten aus, benötigt aber auch am meisten Programmspeicher.

LiquidCrystal_I2C_ST7070 lcd(addr, cols, rows);   // Ä --> Ä 

Einige Displays verwenden statt einen HD44780 einen ST7070 Treiber IC. Diese Displays haben einen sehr viel umfangreicheren Zeichensatz und haben eine native Unterstützung für Ä Ö Ü, das heißt es werden keine Custom Characters benötigt und diese können weiterhin für eigene Zwecke verwendet werden. Auf der nächsten Seite findest du weitere Informationen zum ST7070 LCD.

LiquidCrystal_I2C_ST7070_Ext lcd(addr, cols, rows);   // Ä --> Ä 

Mit diesem Konstruktor werden weitere Zeichen des ST7070 unterstützt. Damit ist die Darstellung aller europäischen Sprachen die auf Latin-1 oder Latin-2 benötigen möglich.

 

Einsatz der neuen Noiasca Liquid Crystal I2C Library

Der Einsatz der neuen Noiasca Liquid Crystal ist ganz einfach:

  • Zip downloaden und Inhalt in das eigene Library Verzeichnis entpacken.
  • Arduino IDE neu starten.
  • Hello World Beispiel aus der Library ausprobieren, evtl. muss die I2C Adresse des Displays angepasst werden.
  • Bestehende Sketche die bisher mit der Adafruit Library 1.2.1 funktioniert haben, müssen auch mit der neuen Library funktionieren. Im Regelfall ist nur die Änderung des #include notwendig:
#include <NoiascaLiquidCrystal_I2C.h>
  • In das setup() kommt noch vor dem lcd.init() der Start der I2C Wire Library
Wire.begin();
  • Hast du heute bereits Sonderbehandlungen für Umlaute im Fließtext oder gibst du Umlaute mit einzelnen .write() aus, so müssen diese Codeteile angepasst werden.
  • Wenn sonstige Sonderzeichen mittels .write() ausgegeben wurden und diese nicht in echte UTF-8 Texte geändert werden können, so sind diese Aufrufe auf .writeOld() zu ändern.

Exkurs: Die I2C Adressen 0x27 vs. 0x3F

Gibt es Schwierigkeiten mit der generellen Anzeige auf einem I2C LCD, empfiehlt es sich, mit einem I2C Scanner zu überprüfen, auf welcher Adresse das Display angeschlossen ist. In den Beispielen im Internet finden sich sowohl die Adresse 0x27 und 0x3F. Hintergrund sind die ansonsten kompatiblen Chips. Die ICs PCF8574P,  PCF8574T, PCF8574TS unterstützen die Adressen 0x30 - 0x3F. Die ICs PCF8574AP,  PCF8574AT und 8574A (mit A in der Gehäusebezeichnung) verwenden die Adressen 0x20 - 0x27. Verwendet man zwei verschiedene Chips könnte man also bis zu 16 Displays ansteuern.

Exkurs: Kleinbuchstaben mit Unterlängen (g j p q y)

Bei den Kleinbuchstaben mit Unterlängen g, j, p, q und y erreicht man durch addieren von 0x80 (quasi 8 Spalten nach rechts) die Anzeige von Varianten die in die Unterlänge reichen. Nach einigen Tests habe ich beschlossen, das in der Library nicht umzusetzen. Die Kleinbuchstaben g p q y mit Unterlängen sind nämlich höher. Diese Zeichen haben eine Höhe von 7 Pixel und trotz Ausnutzung der Unterlänge, überragen sie somit die anderen Kleinbuchstaben um ein Pixel. Da die meisten Displays nur 5x7 Pixel je Zeichen zur Verfügung stellen, ist die Darstellung nicht besser möglich. Hier ein Vergleichsbild: erste Zeile die Standard-Buchstaben - zweite Zeile mit Unterlängen:

Kleinbuchstaben mit Unterlängen am LCD Display

Wer es dennoch mal probieren will, der schreibt beispielsweise:

lcd.writeOld('g' + 0x80);

Zusammenfassung

Die neue Noiasca Liquid Crystal I2C eignet sehr gut für die Ausgabe von deutschen Texten. Sonderzeichen - wie auch deutsche Umlaute und das scharfe s -  können einfach mit den gewohnten .print Methoden ausgegeben werden. Für den unveränderten Zugriff auf Zeichen im höheren ROM Bereich gibt es einen Aufruf der alten write Methode. Abschließend noch der Hinweis, dass die neue Library wegen dem Zeichen-Mapping mehr Programmspeicher und auch 4 Byte mehr SRAM benötigt.


Links


Protokoll

First upload: 2020-03-20 | Version: 2020-05-18