#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
// LCD-Codes Aufzählung
const unsigned char myue=0x01;
const unsigned char EURO=0x02;
const unsigned char GRAD=0xDF;
const unsigned char ae=0xE1;
const unsigned char sz=0xE2;
const unsigned char oe=0xEF;
const unsigned char ue=0xF5;
//
// Forwarddeklaration der verwendeten Funktionen
//
void print_lcd(const unsigned char*);
unsigned char sonderzeichen(const unsigned char);
//
// Bitmuster für eigene Zeichen 5x8 Bit Matrix (5 Spalten, 8 Zeilen)
//
// Version mit PROGMEM. Funktioniert in dieser WokWi Simulation nicht aber in RL mit
// der Version LiquidCrystal_I2C 1.1.4
//
//const char uuml[8] PROGMEM = { 0x0A, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D, 0x00 }; // Umlaut ü
//const char euro[8] PROGMEM = { 0x06, 0x09, 0x1C, 0x08, 0x1C, 0x09, 0x06, 0x00 }; // Euro Zeichen
// Version ohne PROGMEM
unsigned char uuml[8] = { 0x0A, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D, 0x00 }; // Umlaut ü
unsigned char euro[8] = { 0x06, 0x09, 0x1C, 0x08, 0x1C, 0x09, 0x06, 0x00 }; // Euro Zeichen
// String direkt mit den zum LCD passenden ASCII-Codes definieren.
const unsigned char text[] = {ae,oe,ue,myue,sz,'\0'};
// Folgender String "wort" wird automatisch auf die für das Display passenden Zeichen
// umgewandelt. Dafür wird eine "Umsetzfunktion" sonderzeichen() und eine Funktion
// für die Zeichenausgabe print_lcd() verwendet.
// Achtung:
// Werden C-Strings wie folgt definiert, so werden nur die Zeichen mit einem
// ASCII Wert < 128 mit einem Byte gespeichert. Alle anderen Zeichen werden
// im UTF-8 Code, der bis zu 4Byte lang sein kann, vorgehalten!
//
// Die in diesem Beispiel verwendeten Sonderzeichen werden als
// zwei Byte UTF-8 Zeichen gespeichert. Das Euro-Zeichen hat sogar einen
// drei Byte UTF-8 Code (0xE2 0x82 0xAC).
//
// Strings sind demzufolge also länger als es im Programmcode den Anschein hat!!!
//
unsigned char wort[] = "Bödläülß 6€ 42°C"; // <- Nicht 17 sondern 24 Byte inkl. Stringende (\0)!
LiquidCrystal_I2C lcd(0x27,16,2); // LCD I2C Adresse 0x27 für 16 Zeichen und 2 Zeilen Darstellung
//LiquidCrystal_I2C lcd(0x3F,20,4); // LCD I2C Adresse 0x27 für 20 Zeichen und 4 Zeilen Darstellung
void setup()
{
Serial.begin(115200);
Serial.print("Stringlänge von \"wort\" = ");
Serial.print(strlen((char*)wort));
Serial.println(" Byte + 1 Byte fuer Stringterminierung (\\0)");
lcd.init();
lcd.backlight();
lcd.createChar(myue, uuml); // Umlaut in den Displayspeicher schreiben
lcd.createChar(EURO, euro);
lcd.setCursor(5,0);
lcd.print((char*)text); // Bei Liquid Crystal I2C Bibliothek cast auf (char*) notwendig
lcd.setCursor(0,1);
print_lcd(wort);
}
void loop()
{
}
//
// Gib einen String auf dem Display aus.
//
void print_lcd(const unsigned char* text) {
while (*text) {
// Wenn sonderzeichen() eine 0 zurückliefert ist ein UTF-8 Zeichen auszugeben.
unsigned char zeichen = sonderzeichen(*text++);
if (zeichen) {
lcd.write(zeichen);
}
}
}
//
// Wandle UTF-8 Sonderzeichen in ASCII Codes für das LCD-Display um.
// Die Codes 0x01 und 0x02 sind die selbst definierte Zeichen uuml und euro.
//
unsigned char sonderzeichen(const unsigned char ascii) {
static unsigned char istUTF8; // Speichert das "vorletze" Zeichen.
unsigned char zeichen = '\0';
if (ascii < 0x7F) {
istUTF8 = '\0';
return ascii; // Return wenn KEIN UTF-8 Zeichen
}
// Wenn UTF-8 Zeichen
switch (istUTF8) {
case 0xC2:
switch (ascii) {
case 0xB0: zeichen = GRAD; break; // ° Grad UTF-8 = 0xC3 0XB0
default: zeichen = ascii; break;
}
break;
case 0xC3:
switch (ascii) {
case 0xA4: zeichen = ae; break; // ä UTF-8 = 0xC3 0xA4
case 0xB6: zeichen = oe; break; // ö UTF-8 = 0xC3 0xB6
case 0xBC: zeichen = myue; break; // ü UTF-8 = 0xC3 0xBC
case 0x9F: zeichen = sz; break; // ß UTF-8 = 0xC3 0x9F
default: zeichen = ascii | 0xC0; break;
}
break;
// Spezialfall: Euro Zeichen (3 Byte Code -> 0xE2 0x82 0xAC)
case 0xE2: if (ascii == 0x82) zeichen = '\0'; break;
case 0x82: if (ascii == 0xAC) zeichen = EURO; break;
default: break;
}
istUTF8 = ascii;
return zeichen;
}