Schriftarten Flackern mit Adafruit-GFX-Library

Hallo liebes Forum,

Ich verwende für den Arduino GIGA Schild, die Arduino_GigaDisplay_GFX die, die Adafruit-GFX-Library intern mit einbindet, allerdings habe ich das Problem bei den mitgelieferten Fonts sowohl als auch bei den Custom Fonts das die Schriften ununterbrochen flackern, durch das übermalen des alten Textes beim Anzeigen von Datum der RTC habe ich das semi gut beheben können indem der Text erst übermalt wird wenn sich der Text auch wirklich ändert das geht auch flackert dann nur noch 1x in der Minute satt alle 2 Sekunden. ich möchte aber auch werte eines SHT31 Sensors auslesen dort geht das nicht so einfach, da der Sensor Parament Werte liefert.
kennt da jemand einen Workaround das Flackern mit der Adafruit-GFX-Library in den Griff zu bekommen? Oder gibt es für das GIGA Shield eine Alternative die mit Schriften, Farben und Bitmaps/bmps umgehen kann?

Hier ist noch mein aktueller Code:

#include "Arduino_GigaDisplay_GFX.h"
GigaDisplay_GFX display;

#include <Arduino_GigaDisplay.h>
GigaDisplayRGB rgb;

#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;

#include <Adafruit_SHT31.h>
Adafruit_SHT31 sht31 = Adafruit_SHT31();

#define RED     0xf800
#define BLUE    0x459F
#define WHITE   0xffff
#define BLACK   0x0000

#include "bitmap.h"
#include <Fonts/calibri40pt7b.h> // Beispiel einer Schriftart

const int motionSensorPin = 2;  // Pin, an den der AM312 Bewegungsmelder angeschlossen ist
const int backlightPin = D74;   // Pin für die Steuerung der Hintergrundbeleuchtung
unsigned long motionDetectedTime = 0;  // Zeit, zu der die letzte Bewegung erkannt wurde
const unsigned long backlightDuration = 5000;  // 5 Minuten in Millisekunden
bool isBacklightOn = false;  // Status der Hintergrundbeleuchtung




boolean isSummer; // Globale Variable deklarieren
void adjustForDST(DateTime &d) 
{
  if (isSummer) 
{
  d = d + TimeSpan(0,1,0,0);
}
}





void setup() 
{
  pinMode(motionSensorPin, INPUT);  // Setze den Bewegungsmelder-Pin als Eingang
  pinMode(backlightPin, OUTPUT);    // Setze den Hintergrundbeleuchtungs-Pin als Ausgang
  digitalWrite(backlightPin, LOW);  // Stelle sicher, dass die Hintergrundbeleuchtung zu Beginn ausgeschaltet ist
 
  Wire.begin(); // SDA an Pin 20, SCL an Pin 21
  rtc.begin();
  sht31.begin(0x44);
  
  display.begin();
  display.setRotation(1); // 1: 90 Grad im Uhrzeigersinn drehen, 2: 180 Grad, 3: 270 Grad
  display.fillScreen(BLUE);
  display.drawRGBBitmap(15, 150, bitmap, 528, 104);
  
  rgb.begin();
}





void loop() 
{
  readAndPrintRTC();
  backlightOnOff(); // Rufe die Funktion zur Steuerung der Hintergrundbeleuchtung auf
  //LEDfedback_receivingDATA();
  //readAndPrintSensorData();
}




void backlightOnOff() {
  int motionState = digitalRead(motionSensorPin);  // Lese den Zustand des Bewegungsmelders

  if (motionState == HIGH) {  // Wenn Bewegung erkannt wird
    motionDetectedTime = millis();  // Speichere die aktuelle Zeit
    if (!isBacklightOn) {  // Wenn die Hintergrundbeleuchtung nicht bereits eingeschaltet ist
      digitalWrite(backlightPin, HIGH);  // Schalte die Hintergrundbeleuchtung ein
      isBacklightOn = true;  // Aktualisiere den Status
    }
  }
  // Prüfe, ob die 5 sek vergangen sind, seit die letzte Bewegung erkannt wurde
  if (isBacklightOn && (millis() - motionDetectedTime >= backlightDuration)) {
    digitalWrite(backlightPin, LOW);  // Schalte die Hintergrundbeleuchtung aus
    isBacklightOn = false;  // Aktualisiere den Status
  }
}




/*
void LEDfedback_receivingDATA()
{
  rgb.on(0, 255, 0);
  delay(250);
  rgb.off();
}





void readAndPrintSensorData() 
{
    float Temperatur = sht31.readTemperature();
    float Luftfeuchtigkeit = sht31.readHumidity();


    tft.drawString(String(Temperatur, 1) + " °C", 223, 305); // IN Temp

    tft.setTextPadding(tft.textWidth("888 8")); 
    tft.drawString(String((int)Luftfeuchtigkeit) + " %", 463 , 305); // IN Humidity
}
*/




void check_SummerTime() 
{
  DateTime now = rtc.now();
  isSummer = summertime_EU(now.year(), now.month(), now.day(), now.hour(), 1);
}
  boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours) 
{
  if (month < 3 || month > 10) return false;
  if (month > 3 && month < 10) return true;
  if (month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7)))
  return true;
  else
  return false;
}





char lastTimeDisplay[15] = "";
char lastDateDisplay[15] = "";

void readAndPrintRTC() 
{
    DateTime now = rtc.now();
    check_SummerTime(); // Aufruf der Funktion zur Überprüfung der Sommerzeit
    adjustForDST(now);
    char dateDisplay[15];
    char timeDisplay[15];
    sprintf(dateDisplay, "%.02d.%.02d.%.2d", now.day(), now.month(), now.year());
    sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());
  
    if (strcmp(timeDisplay, lastTimeDisplay) != 0) 
    {
        display.fillRect(10, 20, 220, 70, BLACK); 
        display.setTextColor(WHITE);  
        display.setFont(&calibri40pt7b);
        display.setCursor(10, 70);
        display.print(timeDisplay);  
        strcpy(lastTimeDisplay, timeDisplay);  // Speichere den aktuellen Zeitstring
    }
    if (strcmp(dateDisplay, lastDateDisplay) != 0) 
    {
        display.fillRect(240, 20, 150, 70, BLACK); 
        display.setTextColor(WHITE);  
        display.setFont(&calibri40pt7b);
        display.setCursor(240, 70); 
        display.print(dateDisplay);
        strcpy(lastDateDisplay, dateDisplay);  // Speichere den aktuellen Datumsstring
    }
}

Ich sage schonmal vielen Dank im Voraus😊

Meinst Du, wenn Du Dein Thema auf mehrere Threads verteilst, bekommst Du mehr und bessere Antworten? Ich denke das Gegenteil wird der Fall sein.

Gruß Tommy

Das ist ein komplett neues Thema in dem es speziell um die Adafruit-GFX Library geht, ist besser als verschiedene Themen in ein Thread zu stecken.

so wird ein Thread nicht unübersichtlich

Es ist nicht notwendig Rechtecke die einmal gezeichnet wurden permanent neu zu zeichnen. Es ist auch nicht notwendig permanent den Schriftsatz und Schriftfarbe neu zu setzen, wenn sie sich gar nicht ändert…

Der Text ist nicht Statisch, Uhrzeit und Datum ändert sich

Das ist mir klar… aber mach was du willst…

Auf Ratschläge und Tipps hoffen, ist ja nichts falsch daran

Die ohne zu überlegen und ohne sich mal seinen eigenen Code anzuschauen aber schon.

Das sind Unterstellungen und Behauptungen, dinge die du doch überhaupt nicht wissen kannst, aber das ist wohl ein generelles Problem an Online Foren🙄. Ich habe mir die ganze Nacht darüber den Kopf zerbrochen und alles versucht was mir als Tipp gegeben wurde oder was ich aufgreifen konnte

Das habe ich so machen müssen, weil sonst überhaupt nichts funktioniert hätte.
Ich habe viele Foren/Threads durchgelesen und mir den Kopf darüber zerbrochen, sowie mir sehr viel Hilfe von @fony eingeholt wofür ich ihm wirklich sehr dankbar bin.

EDIT:
Diese Problematik mit den Schriftarten der Adafruit-GFX-Library ist übrigens schon seid 2017 bekannt

Ich kann dir nur eins sagen, das Flackern bekommst nicht weg (wie gelesen habe).
Auf LVGL umsteigen, dann sind deine Probleme weg, ja man muss sehr viel neues lernen, alle Displays was haben über 400 x 400 Pixel nutzen nur da genannte.
Mit LVGL bin erst am Hello World, habe mir das nur angeschaut, Vor allem ist die so schnell wie TFT_eSPI.

@Kai-R da du mich ja schon so freundlich darauf hingewiesen hast kannst du mir ja sehr gerne mitteilen was ich im Code falsch gemacht oder übersehen habe

Ich habe den Code der RTC geringfügig verändert und ich bin überrascht das dieser nicht flackert auch wenn sich der Text ändert, so kann es gerne bleiben.

Alerdings Flackert entweder die Temperatur oder die Luftfeuchtigkeit

Die Temperatur Flackert wenn ich den Code so schreibe:

void readAndPrintSensorData() 
{
        // Sensorwerte lesen
        float Temperatur = sht31.readTemperature();
        float Luftfeuchtigkeit = sht31.readHumidity();

        // Erzeuge die String-Variablen für Temperatur und Luftfeuchtigkeit
        String tempString = String(Temperatur, 1) + " C";
        String humidityString = String((int)Luftfeuchtigkeit) + " °%";
        
        display.setTextColor(WHITE);  
        display.setFont(&aptos45pt7b);
        // Anzeige aktualisieren
        display.fillRect(100, 375, 280, 75, BLACK); 
        display.setCursor(100, 440); // Position für Temperaturanzeige
        display.print(tempString);

        display.fillRect(100, 280, 280, 75, BLACK); 
        display.setCursor(100, 340); // Position für Luftfeuchtigkeitsanzeige
        display.print(humidityString);

}

Die luftfeuchtigkeit flackert wenn ich den Code so schreibe:

void readAndPrintSensorData() 
{
        // Sensorwerte lesen
        float Temperatur = sht31.readTemperature();
        float Luftfeuchtigkeit = sht31.readHumidity();

        // Erzeuge die String-Variablen für Temperatur und Luftfeuchtigkeit
        String tempString = String(Temperatur, 1) + " C";
        String humidityString = String((int)Luftfeuchtigkeit) + " °%";
        
        display.setTextColor(WHITE);  
        display.setFont(&aptos45pt7b);
        // Anzeige aktualisieren
        display.fillRect(100, 375, 280, 75, BLACK); 
        display.setCursor(100, 440); // Position für Temperaturanzeige
        display.print(humidityString);

        display.fillRect(100, 280, 280, 75, BLACK); 
        display.setCursor(100, 340); // Position für Luftfeuchtigkeitsanzeige
        display.print(tempString);

}

Der Text der RTC Flackert wenn der Code so verändert wird:


void readAndPrintRTC() 
{
    DateTime now = rtc.now();
    check_SummerTime(); // Aufruf der Funktion zur Überprüfung der Sommerzeit
    adjustForDST(now);
    char dateDisplay[15];
    char timeDisplay[15];
    sprintf(dateDisplay, "%.02d.%.02d.%.2d", now.day(), now.month(), now.year());
    sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

        display.fillRect(30, 15, 225, 75, BLUE); 
        display.setTextColor(WHITE);  
        display.setFont(&aptos45pt7b);
        display.setCursor(35, 80);
        display.print(timeDisplay);  

        display.fillRect(320, 15, 440, 75, BLUE); 
        display.setTextColor(WHITE);  
        display.setFont(&aptos45pt7b);
        display.setCursor(330, 80); 
        display.print(dateDisplay);
}

Noch seltsamer wird es wenn ich den Code von void readAndPrintSensorData() so abändere:

void readAndPrintSensorData() 
{
        // Sensorwerte lesen
        float Temperatur = sht31.readTemperature();
        //float Luftfeuchtigkeit = sht31.readHumidity();

        // Erzeuge die String-Variablen für Temperatur und Luftfeuchtigkeit
        String tempString = String(Temperatur, 1) + " °C";
        //String humidityString = String((int)Luftfeuchtigkeit) + " %";
        
        display.setTextColor(WHITE);  
        display.setFont(&aptos45pt7b);
        // Anzeige aktualisieren
        //display.fillRect(100, 375, 280, 75, BLACK); 
        //display.setCursor(100, 440); // Position für Temperaturanzeige
        //display.print(humidityString);

        display.fillRect(100, 280, 280, 75, BLACK); 
        display.setCursor(100, 340); // Position für Luftfeuchtigkeitsanzeige
        display.print(tempString);
}

Dann fängt das Datum an zu flackern. Sieht eher danach aus das es ein Timing Problem ist, beim Hinzufügen von delay(); verschwindet zwar das Flackern des Textes aber erscheint an anderer Stelle

Beispiele:
https://1drv.ms/v/s!AjaN9LRRY5J2m7U22vQ-LPyeFJSEgA?e=GEgacH

Vielleicht ist es ratsam, Texte nur neu zu beschreiben, wenn sie sich geändert haben, und nur die Stellen die sich geändert haben.

Auch bei soetwas:

Du malst ein Viereck, um den alten Text zu entfernen. Bevor du den neuen Text schreibst, machst du noch andere Dinge. In der Zeit sieht dein Auge für ein Bruchteil
kein Wert. Dies kann als flackern Wahrgenommen werden.
Auch wurde schon darauf hingewiesen, das du nicht ständig Textfarbe und Schriftart setzen musst. Diese sind doch hinterlegt und werden verwendet. Erst wenn sie sich ändern sollen, musst du sie neu setzen.

Wie fony schon geschrieben hat: Das flackern wirst du nicht wegkriegen. Minimieren kannst du es, wenn du den alten wert speicherst, und diesen anstelle des Rechtecks in der Hintergrundfarbe ausgibst. Ansonsten ausweichen auf ESP32 und TFT_eSPI
Damit du nicht jedes Mal die Schriftart neu setzen musst, und den Cursor platzierst könntest du dir auch eine funktion dafür schreiben.
sowas wie das

//Template Für showmsgXY
template<typename t> void showmsgXY(int x, int y, int sz, const GFXfont* f, t msg, uint16_t vFarbe, uint16_t hFarbe) {//Position X, Position Y, Textgrösse, Schriftart, Text, Textfarbe, Hintergrundfarbe
  tft.setFont(f);
  tft.setCursor(x, y);
  tft.setTextColor(vFarbe,hFarbe);
  tft.setTextSize(sz);
  tft.print(msg);
  tft.setFont();
  tft.setTextSize(1);
}

Der TO hat schon das mit ESP + Display gemacht, und es funktioniert,

Jetzt will er aber auf einen IPS Display umsteigen was wird nur durch 3 Bibliotheken unterstützt 2 X Adafruit und die dritte LVGL.

Ja genau, das ist allerdings sehr problematisch. War höchstwahrscheinlich keine gute Idee damit zu arbeiten, wenn die Hardware gerade mal erst ein Jahr alt ist. Man ist halt ziemlich beschränkt, wenn es nur drei librarys dafür gibt, ob TFT-eSPI irgendwann mein Display auch unterstützt, bleibt zu hoffen

hier wird mit canvas gearbeitet, was das bringt ist was anderes,

den Therad habe ich gar nicht gesehen. Darum mache ich das bei meinen Projekten lieber in eine kompletten thread...wird halt länger, aber es sind alle informationen enthalten

nee ist schon IO ist ganz andere Thematik.

1 Like