Kleines Problem bei der Ausagbe aufs OLED Display

Ich gebe jede Sekunde einmal Zeit und Datum aufs OLED Display aus. Klappt eigentlich, bis auf das Problem, dass man ja die Zeile auf die man geänderte Ziffern ausgibt, erst mal löschen muss. Hier ist der Programmteil:

void Zeitausgabe() {
  tm local;
  getLocalTime(&local);
  oled.setFont(u8g2_font_6x12_tr);  // Kleine Schrift 6x12
  oled.setCursor(10, (1 * 10));
  oled.print(&local, " Datum: %d.%m.%y");
  // Hier das Problem. Die Zeitausgabe
  oled.setCursor(10, (2 * 10));
  oled.print("                "); // 16 Zeichen löschen
  oled.sendBuffer();
  oled.setCursor(10, (2 * 10));
  oled.print(&local, " Zeit : %H:%M:%S"); // 16 Zeichen Zeit schreiben
  oled.sendBuffer();

Das macht alles Wunderbar, aber das Löschen mit 16 Leerzeichen scheint nicht zu klappen. Denn wenn schmale Zahlen wie eine “1” hinten bei den Sekunden, oder auch bei den Minuten kommen, sieht man, dass die Leerzeichen offenbar nicht alles darunter überschreiben.

Also ich gebe immer erst eine Leerzeile ein, sende den Buffer und gebe dann die Uhrzeit ein und sende wieder den Buffer. Klappt trotzdem nicht. Wenn ich anstelle der 16 Leerzeichen, 16 Unterstriche mache, reichen die genau bis zum Ende der Zeile, ich sehe also dass ich weit genug lösche. Trotzdem erscheinen dann oben neben einer 1 z.B. weiße Überpleipsel, von was weis ich was. :roll_eyes:

Man muss doch nicht das ganze Display jede Sekunde Löschen, um eine saubere Anzeige zu haben ?

Franz

Mit Leerzeichen ist immer ein Problem.
Speicher dir den letzten Wert und überschreibe mit schwarzer Schrift, bevor du den neuen Wert schreibst. Und das Datum muss doch nicht jede Sekunde neu geschrieben werden. Da reicht es, das am Anfang des Tages 00:00 Uhr neu zu setzen.

1 Like

Ahhh OK danke. Ja, den Tipp habe ich schon mal irgendwo hier im Forum gelesen, jetzt fällt es mir wieder ein, aber das Hirn scheint immer mehr die Eigenschaften eines Siebes zu bekommen. :roll_eyes:

Danke
Franz

Ja, das kenn ich.
Da hilft dann ein Denkanstoß und der Rest macht Google. :sweat_smile:

Habe das getestet, ist so. Abhilfe printf nehmen.

 oled.printf("%02u:%02u  ",
               t.hour, t.minute );
               oled.setCursor(2, 9);
   oled.printf("%02u.%02u. % 4u ",
               t.day, t.month, t.year);

Anpassen !

Das %02u bedeutet das immer eine "0" gesetzt wird wenn der Wert kleiner als 10 ist

Nutzt Du U8g2? Dann kannst Du #2, #4 und #5 vergessen, gilt für andere Bibliotheken.

Verwende stattdessen clearBuffer(). Ungetestet so:

void Zeitausgabe() {
  tm local;
  getLocalTime(&local);
  oled.clearBuffer();
  oled.setFont(u8g2_font_6x12_tr);  // Kleine Schrift 6x12
  oled.setCursor(10, (1 * 10));
  oled.print(&local, " Datum: %d.%m.%y");
  oled.setCursor(10, (2 * 10));
  oled.print(&local, " Zeit : %H:%M:%S"); // 16 Zeichen Zeit schreiben
  oled.sendBuffer();

Nein! printf gilt für alle Bibliotheken was nutzen print.h, also wirklich alle Arduino Display Bibliotheken,

Ein Irrtum!
AVR Print.h kennt kein printf
ESP Print.h schon

Ja, wenn ich “ oled.printf(….” benutze, bekomme ich eine Fehlermeldung.

Und das mit der Zeile “oled.clearBuffer();” zum Löschen und die Displayanzeige jedesmal komplett neu aufbauen, dauert zu lange. An der Stelle ich Zeit ein wichtiger Facktor.

Ich habe jetzt im Moment auf die Sekundenanzeige verzichtet, mache somit nur noch alle 60 Sekunden das Display neu, und zwei Zeilen mit Großen zahlen ersetze ich ohne Löschen. Also da, wo ich diese Zeitprobleme habe. Das sind “u8g2_font_10x20_mf” Zahlen & Buchstaben.

Danke
Franz

Stimmt.

OK, soooo groß wie ich dachte ist der Unterschied nicht. Der Unterschied zwischen überschreiben, oder das Diplay löschen und neu schreiben sind 49 millis. Aber das ist eine Zeitkritische Stelle. Da zählen diese Zeiten.

OK, danke euch einstweilen.

Franz

Aber beachte dabei, beim Löschen des Displays flackert es meistens.

Ja genau. Da ich jetzt auf die Sekunden Anzeige verzichten kann, ist es nur noch jede Minute einmal ein Flackern. Das ist eigentlich egal. Aber ich mache mich da später nochmal dran, wenn das ganze Programm erst mal steht. Dann wird wahrscheinlich das Display eh nicht drin bleiben.

Dann verwende doch U8x8lib, braucht bei mir mit ESP32 nur ein Drittel der Zeit von U8g2.

void Zeitausgabe() {
  uint32_t vorhin = millis();
  tm local;
  getLocalTime(&local);
  /*oled.setCursor(0, 1);
  oled.print(&local, " Datum: %d.%m.%y");*/
  oled.setCursor(0, 2);
  oled.print(&local, " Zeit : %H:%M:%S"); // 16 Zeichen Zeit schreiben
  Serial.print("Zeit A ");
  Serial.print(millis() - vorhin);
  Serial.println(" ms");
}

Wie die Zeitersparnis beim AVR ist, mußt Du mal ermitteln.

Danke dir. Probiere ich aus. Das Programm hier läuft auf nem ESP32.

Franz

11 ms für #14.

U8x8lib überschreibt den Hintergrund, löscht damit die alte Anzeige.

void ZeitausgabeA() {
  uint32_t vorhin = millis();
  tm local;
  getLocalTime(&local);
  oled.clearBuffer();
  oled.setFont(u8g2_font_6x12_tr);  // Kleine Schrift 6x12
  //oled.setCursor(10, (1 * 10));
  //oled.print(&local, " Datum: %d.%m.%y");
  oled.setCursor(10, (2 * 10));
  oled.print(&local, " Zeit : %H:%M:%S"); // 16 Zeichen Zeit schreiben
  oled.sendBuffer();
  Serial.print("Zeit A ");
  Serial.print(millis() - vorhin);
  Serial.println(" ms");
}

Mit Datum 35 ms, ohne 34 ms.

Beim ESP32 kann man printf sogar verwenden, allerdings konnte ich keinen signifikanten Zeitvorteil feststellen, da sendBuffer wohl die meiste Zeit benötigt. Und auch gegen das Flackern hilft es eher nicht. Zur formatierten Ausgabe ist es aber ebenso wie snprintf gut geeignet.

Danke. Ich muss mal noch bischen Testen bei mir. Printf ist bei mir def. nicht gegangen. Obwohl ich ja einen ESP32 benutze. Aber heute geht bei mir nichts mehr. Ist ein richtiger :woozy_face: Tag.

Servus
Franz

Bei printf mus außer Formatierung zeichen auch bekannt geben wass soll gezeigt werden, zB.

oled.printf("%02:%02", stunde, minute);

Das ist gut zum formatierten Ausgeben und faßt mehrere print-Zeilen zusammen, sollte man also "drauf" haben. Einen signifikanten Geschwindigkeitsvorteil bringt es aber nicht.

Geschwindigkeit bringt die Ausgabe von festem Text in setup:

  oled.setCursor(0, 2);
  oled.print("Zeit : 00:00:00");

Dann brauchst Du nur die sich ändernden Ziffern an das Display zu übertragen:

void Zeitausgabe() {
  uint32_t vorhin = micros();
  tm local;
  getLocalTime(&local);
  if (h != local.tm_hour) {
    h = local.tm_hour;
    oled.setCursor(7, 2);
    oled.print(&local, "%H");
  }
  if (m != local.tm_min) {
    m = local.tm_min;
    oled.setCursor(10, 2);
    oled.print(&local, "%M");
  }
  if (s != local.tm_sec) {
    s = local.tm_sec;
    oled.setCursor(13, 2);
    oled.print(&local, "%S");
    Serial.printf("%lu µs für Zeit %02u:%02u:%02u\n", micros() - vorhin, local.tm_hour, local.tm_min, local.tm_sec);
  }
}

Spart viel Zeit:

1425 µs für Zeit 17:01:57
1425 µs für Zeit 17:01:58
1426 µs für Zeit 17:01:59
2799 µs für Zeit 17:02:00
1426 µs für Zeit 17:02:01
1426 µs für Zeit 17:02:02

Nur 1,4 ms ist doch ein Fortschritt :smiley:

komplettes Programm
#include <Arduino.h>
#include <U8x8lib.h>

#include <zugangsdaten.h>  // you could use a dedicated credentials file for your WIFI Password
#include <WiFi.h>
#include <time.h>
#include <Wire.h>

const char* ssid = STA_SSID;
const char* password = STA_PASSWORD;
//const char* ntpServer = "pool.ntp.org";
const char* ntpServer = "fritz.box";
const long gmtOffset_sec = 3600;  //3600 // 0=GMT
const int daylightOffset_sec = 3600;

uint8_t h = -1, m = -1, s = -1;

U8X8_SSD1306_128X64_NONAME_HW_I2C oled(/* reset=*/U8X8_PIN_NONE);

void setup(void) {
  oled.begin();
  oled.setPowerSave(0);
  Serial.begin(115200);
  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  oled.setFont(u8x8_font_chroma48medium8_r);
  oled.setCursor(0, 2);
  oled.print("Zeit : 00:00:00");
}

void loop(void) {
  Zeitausgabe();
}

void Zeitausgabe() {
  uint32_t vorhin = micros();
  tm local;
  getLocalTime(&local);
  if (h != local.tm_hour) {
    h = local.tm_hour;
    oled.setCursor(7, 2);
    oled.print(&local, "%H");
  }
  if (m != local.tm_min) {
    m = local.tm_min;
    oled.setCursor(10, 2);
    oled.print(&local, "%M");
  }
  if (s != local.tm_sec) {
    s = local.tm_sec;
    oled.setCursor(13, 2);
    oled.print(&local, "%S");
    Serial.printf("%lu µs für Zeit %02u:%02u:%02u\n", micros() - vorhin, local.tm_hour, local.tm_min, local.tm_sec);
  }
}

Du hast die Buchstaben für den Typ vergessen!

Ich würde mich freuen, wenn Du mehr Sorgfalt walten lassen würdest :wink:

1 Like

Danke euch. Das wird auf jeden Fall noch ein Thema bei mir. Nur jetzt bin ich an einem Projekt, wo noch weitere Probleme aufgetaucht sind. Die ich erst mal lösen muß. Wenn die durch sind, dann bin ich wieder bei der Verschönerung und Optimierung Display Augabe.

Servus
Franz