Go Down

Topic: Wemos D1 Mini und LCD 1602(A) Umlaute (Read 491 times) previous topic - next topic

derseb

Mar 17, 2020, 11:08 am Last Edit: Mar 17, 2020, 01:31 pm by derseb
Hi,

ich habe folgende Problematik. Ich habe mir mit einem Wemos D1 Mini und einem 16x2 Display (1602A) eine Anzeige gebastelt mit Progressbar. Nun habe ich das Problem mit den Umlauten "äöüÄÖÜ" das diese als Heroglyphen angezeigt werden.

Da ich nur der Rechte Teil der ersten Reihe Scrollen soll muss ich etwas tricksen. Die habe ich mit:

Code: [Select]
String Scroll_LCD_Left(String StrDisplay){
  String result;
  String StrProcess = "         " + StrDisplay + "         ";
  result = StrProcess.substring(Li,Lii);
  Li++;
  Lii++;
  if (Li>StrProcess.length()){
    Li=10;
    Lii=0;
  }
  return result;
}


und

Code: [Select]
void loop () {
  client.loop();
          
  lcd.setCursor(5, 0);
  
  if (game != "None")
  {
    if (strtopic != "")
    {
      lcd.print(Scroll_LCD_Left(title + " | " + strtopic + " | " + game));
    }else
    {
      lcd.print(Scroll_LCD_Left(title + " | " + game));
    }
  }else
  {
    if (strtopic != "")
    {
      lcd.print(Scroll_LCD_Left(title + " | " + strtopic));
    }else
    {
      lcd.print(Scroll_LCD_Left(title));
    }

  }
  delay(350);
}


gelöst.

Nun gibt es ja einmal die möglichkeit die Hex? "Codes" für Umlaute zu nutzen zB.
Code: [Select]
lcd.print("\xE1");

Nur wie bekomme ich das vernünftig in den loop bzw. Scroll_LCD_Left?

Andere Möglichkeit wären ja die Custom Character. Da sind durch die Progressbar 0-6 belegt und laut Kommentar sind noch 7 Übrig was ja reichen würde. Aber auch dort habe ich das Problem das dies ja via
Code: [Select]
lcd.write(0);
aufgerufen wird.

Die Strings um die es geht kommen Dynamisch rein und können sind Dynamisch. Ist also nichts statisches sonst würde ich das hinbekommen glaube ich.

Hier mein kompletter Code:

Code: [Select]
#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
 
const char* ssid = "";
const char* password =  "";
const char* mqttServer = "";
const int mqttPort = 1883;
const char* mqttUser = "";
const char* mqttPassword = "";

String title = "";
String strtopic = "";
String game = "None";
 
WiFiClient espClient;
PubSubClient client(espClient);
 
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display

const int LCD_NB_ROWS = 2;
const int LCD_NB_COLUMNS = 16;

int Li = 10;
int Lii = 0;

byte START_DIV_0_OF_1 [ 8 ] = {
  B01111,
  B11000,
  B10000,
  B10000,
  B10000,
  B10000,
  B11000,
  B01111
};  // Start tank 0/1

byte START_DIV_1_OF_1 [ 8 ] = {
  B01111,
  B11000,
  B10011,
  B10111,
  B10111,
  B10011,
  B11000,
  B01111
};  // Tank start 1/1

byte DIV_0_OF_2 [ 8 ] = {
  B11111,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111
};  // Middle tank 0/2

byte DIV_1_OF_2 [ 8 ] = {
  B11111,
  B00000,
  B11000,
  B11000,
  B11000,
  B11000,
  B00000,
  B11111
};  // Middle tank 1/2

byte DIV_2_OF_2 [ 8 ] = {
  B11111,
  B00000,
  B11011,
  B11011,
  B11011,
  B11011,
  B00000,
  B11111
};  // Middle tank 2/2

byte END_DIV_0_OF_1 [ 8 ] = {
  B11110,
  B00011,
  B00001,
  B00001,
  B00001,
  B00001,
  B00011,
  B11110
};  // Char end 0/1

byte END_DIV_1_OF_1 [ 8 ] = {
  B11110,
  B00011,
  B11001,
  B11101,
  B11101,
  B11001,
  B00011,
  B11110
};  // Fine tank 1/1


// Configuration function of the LCD screen for the progress bar.
// Use custom characters from 0 to 6 (7 remains available).

void setup_progressbar () {

  // Stores custom characters in the LCD screen memory
  lcd.createChar ( 0 , START_DIV_0_OF_1);
  lcd.createChar ( 1 , START_DIV_1_OF_1);
  lcd.createChar ( 2 , DIV_0_OF_2);
  lcd.createChar ( 3 , DIV_1_OF_2);
  lcd.createChar ( 4 , DIV_2_OF_2);
  lcd.createChar ( 5 , END_DIV_0_OF_1);
  lcd.createChar ( 6 , END_DIV_1_OF_1);
}

void draw_progressbar (byte percent) {

  // Displays the new value in numerical form on the first line
  lcd.setCursor ( 0 , 0 );
  lcd.print (percent);
  lcd.print (F ( "%" ));
  // NB The two spaces at the end of the line allow you to delete the percentage figures
  // previous when going from a two or three digit value to a two or one digit value.

  // Move the cursor to the second line * /
  lcd.setCursor ( 0 , 1 );

  // Map the range (0 ~ 100) to the range (0 ~ LCD_NB_COLUMNS * 2 - 2) * /
  byte nb_columns = map (percent, 0 , 100 , 0 , LCD_NB_COLUMNS * 2 - 2 );
  // Each character displays 2 vertical bars, but the first and last character displays only one.

  // Draw each character of the line * /
  for (byte i = 0 ; i < LCD_NB_COLUMNS; ++ i) {

    if (i == 0 ) { // First box

      // Displays the starting char according to the number of columns * /
      if (nb_columns > 0 ) {
        lcd.write ( 1 );  // Tank start 1/1
        nb_columns -= 1 ;

      } else {
        lcd.write ((byte) 0 );  // Start tank 0/1
      }

    } else if (i == LCD_NB_COLUMNS -1 ) { // Last box

      // Displays the end char according to the number of columns * /
      if (nb_columns > 0 ) {
        lcd.write ( 6 );  // Fine tank 1/1

      } else {
        lcd.write ( 5 );  // Char end 0/1
      }

    } else { // Other boxes

      // Displays the correct char according to the number of columns * /
      if (nb_columns >= 2 ) {
        lcd.write ( 4 );  // Char div 2/2
        nb_columns -= 2 ;

      } else if (nb_columns == 1 ) {
        lcd.write ( 3 );  // Char div 1/2
        nb_columns -= 1 ;

      } else {
        lcd.write ( 2 );  // Char div 0/2
      }
    }
  }
}

String Scroll_LCD_Left(String StrDisplay){
  String result;
  String StrProcess = "         " + StrDisplay + "         ";
  result = StrProcess.substring(Li,Lii);
  Li++;
  Lii++;
  if (Li>StrProcess.length()){
    Li=10;
    Lii=0;
  }
  return result;
}

void callback(char* topic, byte* payload, unsigned int length) {
  

  if (strcmp(topic,"d1mini/rbtvdisplay/progress") == 0) {
    lcd.setCursor(0, 0);
    lcd.print("    ");
    payload[length] = '\0'; // Make payload a string by NULL terminating it.
    int progress = atoi((char *)payload);
    draw_progressbar(progress);
    Serial.println("Progress Update");
  }

  if (strcmp(topic,"d1mini/rbtvdisplay/title") == 0) {
    payload[length] = '\0';
    title = String((char*)payload);
    Serial.println("Title Update");
  }

  if (strcmp(topic,"d1mini/rbtvdisplay/topic") == 0) {
    payload[length] = '\0';
    strtopic = String((char*)payload);
    Serial.println("Topic Update");
  }

  if (strcmp(topic,"d1mini/rbtvdisplay/game") == 0) {
    payload[length] = '\0';
    game = String((char*)payload);
    Serial.println("Game Update");
  }
  
}

void setup () {

  // Initializes the LCD screen
  lcd.init();
  lcd.backlight();
  setup_progressbar();
  lcd.clear();
  Serial.begin(115200);
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
 
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
 
  while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("RBTVDisplay", mqttUser, mqttPassword )) {
 
      Serial.println("connected");  
 
    } else {
 
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
 
    }
  }
 
  client.subscribe("d1mini/rbtvdisplay/#");
  client.publish("d1mini/rbtvdisplay/getstatus", "true", false);
}


// loop () function
void loop () {
  client.loop();
          
  lcd.setCursor(5, 0);
  
  if (game != "None")
  {
    if (strtopic != "")
    {
      lcd.print(Scroll_LCD_Left(title + " | " + strtopic + " | " + game));
    }else
    {
      lcd.print(Scroll_LCD_Left(title + " | " + game));
    }
  }else
  {
    if (strtopic != "")
    {
      lcd.print(Scroll_LCD_Left(title + " | " + strtopic));
    }else
    {
      lcd.print(Scroll_LCD_Left(title));
    }

  }
  delay(350);
}


Und ja ich weiss die Variablen pack ich noch in eine Settings.h :D

Vielen Dank schonmal für Vorschläge.

Tommy56

Hast Du mal den Zeichenvorrat Deines LCD von 0 ... 255 getestet? Teilweise sind da evtl. Umlaute mit dabei. Ansonsten die verbleibenden User-Zeichen nehmen.

In beiden Fällen beim "Reinkommen" der Zeichenketten ein Ersetzen durchführen.
Dabei sollten die Zeichenketten aber ASCII/ANSI und nicht UTF8 sein.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

derseb

Hast Du mal den Zeichenvorrat Deines LCD von 0 ... 255 getestet? Teilweise sind da evtl. Umlaute mit dabei. Ansonsten die verbleibenden User-Zeichen nehmen.
Nein habe ich nicht. Wie gesagt die "Anzeige" funktioniert (zumindest mit "lcd.print("\XE1")") aber ich habe keine idee wie ich das in den Scroll Text bringen soll.

Die Zeichen kann ich aufrufen wenn ich einen festen Text vergebe. Aber wie mach ich das über den dynamischen MQTT Payload der reinkommt?

Tommy56

Das habe ich Dir doch geschrieben. Jedes Zeichen was rein kommt anschauen, ob es ein Umlaut ist. Wenn ja, das entsprechende Ersatzzeichen rein schreiben.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

derseb

Das habe ich Dir doch geschrieben. Jedes Zeichen was rein kommt anschauen, ob es ein Umlaut ist. Wenn ja, das entsprechende Ersatzzeichen rein schreiben.

Gruß Tommy
Ja genau das ist mein Problem. Wie muss die funktion aussehen? Den String in ein char array und dann in einer schleife durchgehen?

Ich hab einfach keine Idee Wie.

Tommy56

Das wäre ein Weg.
Ansonsten wie liest Du die Daten von MQTT ein? Wahrscheinlich auch zeichenweise. Da könntest Du das gleich an der Stelle machen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

derseb

Das wäre ein Weg.
Ansonsten wie liest Du die Daten von MQTT ein? Wahrscheinlich auch zeichenweise. Da könntest Du das gleich an der Stelle machen.

Gruß Tommy
Hast du ein Beispiel?

Ich bekomm es ehrlich gesagt nicht hin.

noiasca

wenn man sich drüberdraut könnte man auch die Lib patchen und in der write Methode
im Anlassfall auf das Sonderzeichen gehen. Print wird sowieso schon vereinzelt.

Nur wundert mich, dass das noch niemand gemacht hätte. Gegoogelt nach einer eingedeutschten Lib hast schon?
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

derseb

wenn man sich drüberdraut könnte man auch die Lib patchen und in der write Methode
im Anlassfall auf das Sonderzeichen gehen. Print wird sowieso schon vereinzelt.

Nur wundert mich, dass das noch niemand gemacht hätte. Gegoogelt nach einer eingedeutschten Lib hast schon?
Nein habe ich noch nicht. War am Anfang froh das das Display überhaupt läuft :D Aber vielen dank für den Tip!

derseb

Ich raff es einfach nicht. Mit lcd.print und gewissen Codes geht es ja. Ich bekomm es einfach nur nicht hin das dementsprechend zu printen da ich ja eine String Variable habe. Eingedeutschte Libs gibt es zumindest bei PlatformIO nicht. Russisch könnte ich anbieten :D

noiasca

a) mit welcher i2c Lib arbeitest du (GANZ GENAU angeben, sodass ich die auch finde)

b) mach mal einen Minimalen Sketch der nur folgendes Ausgibt:

Zeile 0
a A o Ö u U s

Zeile 1
ä Ä ö Ö ü Ü ß

poste den hier in Code-Tags

(hab aktuell keinen Zugriff auf ein LCD, daher musst du fleißig mitarbeiten).
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

derseb

#11
Mar 17, 2020, 01:06 pm Last Edit: Mar 17, 2020, 01:07 pm by derseb Reason: Bild Upload
a)
https://github.com/johnrickman/LiquidCrystal_I2C

b)
Code: [Select]
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Arduino.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("a A o O u U s");
  lcd.setCursor(0,1);
  lcd.print("ä Ä ö Ö ü Ü ß");
}


void loop()
{
}



noiasca

Nö schon so dass man die Umlaute sieht!!!
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

derseb

Nö schon so dass man die Umlaute sieht!!!
Ja man sieht was. Aber nicht wie die Umlaute eigentlich aussehen sollten. Versteh die aussage nicht sorry!

Serenifly

#14
Mar 17, 2020, 01:30 pm Last Edit: Mar 17, 2020, 01:33 pm by Serenifly
Die Umlaute sind nunmal nicht teil des einfachen ASCII Zeichensatzes und liegen im Code ROM des Displays weiter hinten

Quote
Nun gibt es ja einmal die möglichkeit die Hex? "Codes" für Umlaute zu nutzen zB.
Das kann man doch direkt in einen String einfügen:
Code: [Select]

lcd.print("R\xE4ume");

Wo ist da das Problem?

Das einzige wo du aufpassen musst ist wenn das Zeichen direkt nach dem Hex-Byte auch als Hex-Ziffer interpretiert werden kann (z.B. 'a' bis 'f'). Da versucht der Compiler das auch als Teil der Hex-Zahl zu Parsen. Dann kann man aber das machen:
Code: [Select]

lcd.print("R\xE4""ume");

Go Up