Gedrag OLED niet zoals verwacht

Ik programmeerde een timer (op basis RTClib.h) en toon de datum, tijdstip en dag op een OLED.
In de loop vraag (nu nog even met een delay) de tijd op in de routine Get_RTCtime() en presenteer die op de OLED (met de routine Update_display() ).

Deze werkwijze werkt met een LED-display goed: de oude tekst wordt gewoon overschreven.
In bijgaande sketch voor de OLED lopen de pixels van seconden en minuten allemaal vol; het is niet zo dat de oude waarden overschreven worden.

Heeft iemand een oplossing? Ik wil niet de inhoud van het hele display wissen, maar slechts een deel overschrijven.

/*
PROGRAM:
Name:         Timer_.ino
Author:       Me
Created:      17-3-2025
Modified:     
Blockdiagram: Not relevant

Ref: 
https://github.com/adafruit/RTClib/blob/master/examples/toString/toString.ino
https://wolles-elektronikkiste.de/en/ds3231-real-time-clock
*/

//================================================================================================
//Libraries  (28..35)
#include <Wire.h>               //Enables I2C communication (used for display, RTC and so on)
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>   //Enables communication with OLED-display
#include <ClickButton.h>        //Enables to detect key entries
#include <EEPROMex.h>           //Enables storage to EEPROM on Arduino processor, 
#include "RTClib.h"             //Enables Real Time Clock


//Define veriables for RTC ((48-57)
DateTime now, futureTime;  

//Define I2C addresses  (114..118)
#define SCREEN_ADDRESS   0x3C   //See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
//#define addrI2Cmem 0x57   //Address of I2C EEPROM (24C32 on RTC 3231 shield)
#define addrDS3231 0x68   //Address if DS3231

//Define OlED1306 parameters
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

//Declaratioin for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin  
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//Parameters for striking the bell (70..90)
int intTime;         //Formula: 100*hours+minutes

//Define (special) characters for LCD (92...103)
//String strSpace = String(32);                                  //character 32 ia a blanc space
//String strLine1, strLine2, strLine3, strLine4, strLine4_old;  //Contains the string for LCD
//String strSpaces = "                  ";                      //string with spaces
//int CursorPos[7] = {0, 0, 5, 8, 12, 15, 18};
//int CursorPos2[6] = {0, 0, 9, 12, 15, 18};      //Cursor position in menu 2 (bell period) in row 4
//int CursorPos4[3] = {0, 0, 9};
String strDate, strTime, strDOW;                  //contains date, time and day of week as string
//String strBellPeriod, strFutureTime;
//String strYMDHMS;

String DOW[7] = {"Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"};

//boolean blnLeft, blnLongLeft, blnUp, blnLongUp, blnDown, blnLongDown, blnRight, blnLongRight;

RTC_DS3231 RTC;

//========================================================================================================
void setup() {
   Serial.begin(9600);  //(127 ..131)
   RTC.begin();         //Enables Real Time Clock
   Wire.begin();        // Enable TWI, join i2c bus (address optional for master)

  //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
  
  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

   // Clear the buffer
   display.clearDisplay();
   display.setTextColor(SSD1306_WHITE);        // Draw white text
}
//==========================================================================================
void loop() {
    Get_RTCtime();            //make strTime, strDate and strDOW
    Update_display();        
    delay(1000);
    }    //End loop 


//===============================================================================================================
void Get_RTCtime(){    //Called every second to dispaly time (585..604)
  // Ref https://forum.arduino.cc/t/rtclib-questions-solved/919613
  // https://github.com/adafruit/RTClib/blob/master/examples/toString/toString.ino  
  
  now = RTC.now();
  char buf2[] = "YYYY-MM-DD";   strDate = (now.toString(buf2));
  char buf3[] = "hh:mm:ss";     strTime = (now.toString(buf3));
  strDOW = DOW[now.dayOfTheWeek()];    //DayOfWeek loopt van 0 tot 6

  intTime = 100*now.hour()+now.minute();  //Easy for compairing times in alarm clocks
  
  }  // End Get_RTCtime

//===============================================================================================================
// Update OLED-information, called when necessary (606..620)
void Update_display() {    
  display.setCursor(0,0);             // Start at top-left corner
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.println("Timer experiment");
 
  display.setCursor(12,24);
  display.setTextSize(2);             // Draw 2X-scale text
  display.println(strTime);           //Display time
  display.display();
 
  display.setCursor(0,56);
  display.setTextSize(1);             // Draw 1:1 pixel scale
  display.println(strDOW);
  display.setCursor(64,56);
  display.println(strDate);
  display.display();
 
  }  //End Update_display
 

Ook als je er een spatie overheen print?

Nee, de oude waarden worden niet overschreden, maar er komen extra pixels bij.
Na erg lang zoeken twee (niet al te fraaie) oplossingen gevonden.

Oplossing 1:
Een niet zo elegante methode blijkt om het pixelbereik te wissen alvorens je gaat printen.
</>
display.setCursor(12,24);
display.setTextSize(2); // Draw 2X-scale text
display.fillRect(12,24,103,16, BLACK);
display.println(strTime); //Display time
</>
De tweede methode is het gebruik van andere bibliotheken speciaal geschreven voor het gebruik van Ascii's.
</>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
</>
De laatste libraries laten slechts vier (grove( regels op de OLED zien.

Ik durf niet te beweren dat dit je probleem zal oplossen, maar ik raad je graag aan om in de library manager te zoeken naar de U8G2 library door @olikraus, en die te gebruiken voor dit display.
Oli Kraus is ook op dit forum actief (niet in het Nederlandstalige deel, want van origine Duitstalig), en geeft heel goede ondersteuning.
Normaal zou ik wel zeggen dat Adafruit dat ook doet, maar schijnbaar heb je toch problemen.

In principe zijn er voor dit soort schermen geen verschillen tussen tekenen en schrijven, de karakters worden feitelijk ook getekend op je scherm.
Daarom werkt het wissen ook, zoals je dat nu gedaan hebt, je vult een rechthoek met zwart.
Eigenlijk zou het ook moeten werken met spaties, maar wanneer je een font gebruikt waar de karakters niet allemaal even groot zijn, kom je met evenveel spaties als tekens vaak niet goed uit (een spatie kan een heel stuk smaller zijn dan een W bijvoorbeeld, zoals je in deze regel zien kunt).

Ik zou display.clearDisplay(); opnemen in het begin van Update_display() en niet moeilijk doen met fillRect of zoiets. Het is trouwens heel goed mogelijk dat het printen van een spatie helemaal niets wist en alleen maar de positie van het volgende karakter aanpast. Om dat zeker te weten kun je de AdafruitGFX sourcecode raadplegen.

TS geeft heel duidelijk aan dat het wissen van het gehele scherm niet gewenst is, en dat neemt ook behoorlijk veel tijd in beslag (eerst alles wissen, dan het scherm opnieuw vullen met de gewenste inhoud).
Een spatie zal wel degelijk wat wissen, maar zoals gezegd kan het zijn dat niet alles gewist wordt afhankelijk van het lettertype, het aantal te overschrijven tekens en het aantal spaties dat je gebruikt.
Uiteraard moet je wel altijd bijhouden waar je op je scherm was gebleven tijdens het beschrijven ervan.

Je hebt gelijk, daar heb ik overheen gelezen.

Wanneer snelheid het probleem is, kan ik je ook aanbevelen om gebruik te maken van een snellere library. In een project met een LCD schermpje heb ik de Adafruit bibliotheek wel eens vergeleken met U8G2 en het snelheidsverschil was een factor 8. Afhankelijk van je processor zou je ook nog een hogere I2C snelheid kunnen proberen.

Je kunt een karakter ook wissen door hetzelfde karakter in achtergrondkleur op dezelfde plek te printen...