Hi,

Nog steeds voor het oven projectje, ik werk gestaagd door... :+

Ik wou graag een andere font gebruiken dan die standaard in de GFX library zit en ik heb er een paar geprobeerd, maar dat krijg ik niet netjes werkend...
Ik begrijp het verschil niet in het gedrag, waarom overschrijft de ingebouwde font netjes de oude waarde en als je één van de mee geleverde fonts gebruikt van de de GFX library,
dan is het weer bagger...

Dit is het stukje code dat de tijd op het display plaatst in de kleur rood.
Er is goed zichtbaar dat het bagger.
Ik heb wat met die regels voor de kleur van het font en de achtergrond kleur gespeeld, maar ik krijg het niet goed, met de ingebouwde font is alle tekst prima,
maar als ik een andere font wil gebruiken voor dynamische tekst dan is het bagger.


// --------------------------------------------------------------------------------
// Place Time values on the screen
// --------------------------------------------------------------------------------
void Print_Time() {
    tft.setFont(&FreeMonoOblique9pt7b);
    DateTime time = rtc.now();  
    tft.setCursor(219, 210);
    tft.setTextSize(1);
    tft.setTextColor(ST77XX_RED, ST77XX_BLACK);
    tft.print(time.timestamp(DateTime::TIMESTAMP_TIME));
    tft.setFont();
}

En dat ziet er dus zo uit als de interne font gebruikt wordt, er is bij de tijd geen residu/ghosting te zien van de vorige karakters.
https://www.bramcam.nl/NA/NA-HF-Doosje-Oven/Display-Font_Probleem-01.png
.

En dit is het beeld als ik andere fonts gebruik, let op de rode klok waarde daar gaat het om.
Als ik met de fonts speel voor het testen dan verschuiven de posities en je moet goed opletten dat je de basis font voor andere tekst weer hersteld als dat de bedoeling is.
Dit tweede plaatje is hierdoor wat rommelig, maar dat is het probleem nu niet.
Ik heb een drietal fonts geprobeerd die in de library staan van Adafruit GFX, alle drie hebben het zelfde probleem.

Een simpele oplossing is natuurlijk een zwart kadertje over de oude tekst schrijven voor de nieuwe wordt geplaatst en ik kan iets herinneren van sprintf oplossing...

https://www.bramcam.nl/NA/NA-HF-Doosje-Oven/Display-Font_Probleem-02.png
.

Ander werk aan dit project
Voor als jullie er interesse in hebben, in het midden is een meterschaaltje te zien waarvan de wijzer precies in het midden staat van 48°C waar het oventje op ingesteld gaat worden.
Het rode wijzertje komt van links als de oven aan het opwarmen is.
Het gele blokje geeft + en – 0.05°C aan en in principe blijft het oventje als ik het goed doe
binnen het gele blokje tussen 15¼C en iets meer dan 30°C, tenminste daar streef ik naar.

De hele grote rode tekst, is een temperatuur meting met een van de precisie NTC die aan de Teensy-LC verbonden is.
Dit is voor een test geweest en dit soort meting gaat uiteindelijk door de ADS1115 gedaan worden voor de P.I.D oven controler.
Als ik waar ik nu mee test afscherm met een doosje er om heen en ik loop niet heen en weer,
dan veranderd maar langzaam de laatste digit dat is dus 0.0001°C!
Dit alleen om aan te geven dat door over-sampling en middeling, hele mooi resultaten te behalen zijn en heeft weinig met nauwkeurigheid te maken.

De rode tekst met de oven temperatuur moet natuurlijk nog anders worden opgemaakt.
Het hele zwarte vlak moet nog goed worden ingericht/opgemaakt, dit met nog wat andere meetgegeven van meerdere analoge ingangen van de Teensy LC.
De hoofd NTC voor de oven, krijgt dus een eigen ADS1115 ADC waarvan ik maar één ingang ga gebruiken, dit om de loop niet te traag te maken.
De andere analoge ingangen die ik nodig heb, kunnen door de Teensy LC worden afgehandeld zonder veel snelheids problemen.
Deze testen heb ik al gedaan, maar ik wou het stukje aan de onderzijde van het scherm vandaag af hebben, tja dat gaat ff niet lukke. ;)

Gaarne hoor ik van jullie of er een goede oplossing is voor de ghosting die ik ondervind bij onder meer de klok weergave.

Dank en groet,
Bram

Bij een GFX font wordt alleen de voorgrond (tekst) geschreven, de achtergrond wordt niet opnieuw geschreven. Eerst het tekstvenster zwart schrijven is mogelijk, maar ook duidelijk zichtbaar. Een andere oplossing is het gebruik van "sprites". Hier ga je eerst naar het geheugen van de processor schrijven, en als het beeld compleet is opgebouwd wordt deze sprite gekopieerd naar het beeldscherm. Maar dit vreet natuurlijk geheugen. Op een ESP32 goed mogelijk, maar niet met een standaard 8bit Arduino.

Ik gebruik hier de Bodmer library, En daar is de interface verschillend voor 'smooth fonts' dwz fonts met anti-aliasing.

Die fonts gebruiken een extra derde parameter bij setTextColor om het opvullen van de achtergrond aan en uit te zetten:


setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false)

Dus het invullen van de achtergrond staat standaard uit, (beetje dom wel), dus die moet je zelf aanzetten. Dat zal bij de adafruit ook wel zo werken.

Dus :


    tft.setTextColor(ST77XX_RED, ST77XX_BLACK, true );

Dat klinkt misschien overbodig, maar die smooth fonts hebben de achtergrondkleur al nodig voor de anti-aliasing, terwijl de normale fonts dat niet gebruiken.

en je moet goed opletten dat je de basis font voor andere tekst weer hersteld als dat de bedoeling is.

Ik maak meestal een aparte subroutine voor de standaard opmaak van het frame en de tekst. Dan kan je elke keer als dat nodig is dat compleet uitvoeren en blijft de opmaak goed.

Ik heb toen van deKees begrepen dat er meerdere typen fonds zijn.
Zoals:
fonds met vaste en variabele breedte
fonds met eigen achter grond en fonds zonder achtergrond.

Eerst het tekstvenster zwart schrijven is mogelijk, maar ook duidelijk zichtbaar.

Ik heb dat toch gewoon zo gedaan en ik zie er verder niets van.
Ik schrijf dan eerste een kleine rechthoek naar display wat precies of net iets groter als het stuk tekst maximaal kan zijn.

Maar het lijkt zo makkelijk een schermpje aansturen maar het goede opmaken en alles er netjes op krijgen is gewoon een uitdaging.

Net als de Kees gebruik ik de Bodmer library TFT_eSPI samen met OpenFontRender van takkO. Lukt niet op een simpele Arduino of ESP8266. Een ESP32 is geen probleem. Maak een eigen true type font met alleen de karakters die je nodig hebt. Het vreet space. Die zijn nadien op elke grootte schaalbaar.

setTextColor(uint16_t fgcolor, uint16_t bgcolor, bool bgfill = false)

Werkt dan wel niet. Ik houd de variabele die geschreven wordt bij in een old variabele. Net voor de tekst wijzigt, wordt de oude tekst in het zwart op het display gezet. Dit gaat zo snel dat je het gewoon niet ziet. Tekst die niet is gewijzigd, wordt niet terug geschreven.

Is een display dat is opgebouwd met de Bodmer en takkaO librarys. De uren worden pas op het uur opnieuw geschreven. De : elke seconde en de minuten 1 keer per minuut. Datum 's nachts om 0h.

Nog eens scherm gebouwd met beide library's. Alsook de Bodmer JSON_decoder en OpenWheater library.

Ja, die Taco openFontRender is weer anders.
die heeft een aparte method om de achtergrond methode te kiezen:


   void setBackgroundFillMethod(BgFillMethod method);

En dan kun je kiezen welke method je wilt:


enum class BgFillMethod {
	None,    ///< Does not fill the background.
	Minimum, ///< Fill in the smallest area that surrounds each character.
	Block,   ///< Fill in the smallest area that surrounds the string.
};

Dus een aanroep als deze -voordat je gaat schrijven- zou moeten volstaan:


   tft.setBackgroundFillMethod(Block);

Ik gebruik de bodmer funkties. Die heeft ook een renderer voor true-type fonts, evenals een utility om fonts te genereren vanuit de fonts die op de host PC aanwezig zijn.
Zie https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Fon…

PS: Dat zijn wel heel mooie plaatjes.

Op zondag 15 december 2024 23:47:19 schreef deKees:
Ja, die Taco openFontRender is weer anders.
die heeft een aparte method om de achtergrond methode te kiezen:


   void setBackgroundFillMethod(BgFillMethod method);

En dan kun je kiezen welke method je wilt:


enum class BgFillMethod {
	None,    ///< Does not fill the background.
	Minimum, ///< Fill in the smallest area that surrounds each character.
	Block,   ///< Fill in the smallest area that surrounds the string.
};

Dus een aanroep als deze -voordat je gaat schrijven- zou moeten volstaan:


   tft.setBackgroundFillMethod(Block);

Ik gebruik de bodmer funkties. Die heeft ook een renderer voor true-type fonts, evenals een utility om fonts te genereren vanuit de fonts die op de host PC aanwezig zijn.
Zie https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Fon…

PS: Dat zijn wel heel mooie plaatjes.

Of het een groot verschil maakt wat je gebruikt, ik zou het eens moeten testen.

Plaatjes zijn gemaakt met de screengrabber die je ook bij de Bodmer voorbeelden kan vinden.

wat ik doe bij een scherm refresh is eerst de oude waarde nog eens schrijven in backgroundkleur, en dan de nieuwe waarde in rode kleur. is de waarde gelijk van oud en nieuw , doe ik zelf geen update ervan.
al de rest gaf geknipper in het beeld.

in principe zou je nog in een subroutine kijken welke karakters gelijk blijven en die niet refreshen

[Bericht gewijzigd door fcapri op (11%)]

Hi,

Dank weer voor de opmerkingen. :-)

Ik ga niet over naar een andere microcontroler, het blijft een Teensy-LC net als het 320x240 display.
Er zit al zoveel werk in dat ik voor de fonts dit niet weer ga aanpassen.

Ook de code die ik nu heb werkt grotendeels en is mooi in blokjes opgebouwd en deze worden in de loop aangeroepen als nodig een aantal zijn daarvan getimed.
Ik schrijf nu een zwrart vlakje, maar dat is niet knipper vrij, ik zal kort even kijken of de truc die Arco voorsteld of ik dit werkend krijg met de font eerst weer zwart maken voor de nieuwe waarde in de goede kleur op het scherm wordt geplaatst.

Eigenlijk vind ik het prutswerk van Adafruit, maar ik kan er natuurlijk niets van zeggen, het is kostenloos. :-)
Het gene dat ik liet zien gisteren is een volle dag werk, dat is de meetgegevens onderin plaatsen en daarna proberen met een mooiere font te werken.
Andere font kiezen, dan mag je alle posities weer opnieuw instellen...

Een flink deel is mijn metertje voor de oven temperatuur met het rode "naaltje" en dan de streepjes van de schaalverdeling netjes neerzetten zodat ik later een goede "map" opdragt kan doen voor dit ingezooomde schaaltje voor de oven temperatuur.

Voor het vele instellen van alle elementen heb ik goed gebruik gemaakt van het i2x printje van deKees met drie maal een rotary encoder er op.
Voor elementen waarvan ik de positie moest bepalen gaf ik dan SW1, SW2 en SW3 in, in de terminal las ik dan de positie af waarna deze positie dan in de code werd gezet, erg handig!
Er is ook een website waarbij he het scherm in de browser kan opbouwen die je direct in een venster er onder de Arduino code laat zien.
Daar speel ik dan eerst mee voor ene visuele indruk van wat ik graag zou willen en of het mogelijk is, later zal ik de URL laten zien, nu geen tijd om dit op te zoeken.

Groet,
Bram

ik probeer hier ook altijd de core van het programma te maken dat die alles naar serial stuurt.
eens dat goed werkt, maak ik een functie om het scherm te refreshen en daar staat alles in.
wil ik een 2de manier van weergeven, maak ik een 2de functie met de scherm instellen. groter font, andere lokatie....

en die wordt dan uit de core opgeroepen. als ik dus zeg om het font 50% groter te zetten, zal ik bepaalde data nog weergeven en andere niet meer
ik bereken hierbij ook altijd hoe groot een font in pixels is. en ik weet hoe groot het scherm is, dus nog voor ik de code schrijf, heb ik al op papier getekent hoe het eruit moet zien. en dan valt het programmeren op zich ook al super goed mee.

ik bouw de hardware ook 2x:
1e prototype om code enzo op te testen
2e versie in gebruik.

alle font testen gebeuren op nr 1, eens het goed is, wordt de code naar nr 2 gezet

verander ik van display, plug ik die in op prototype, kijk of het beeld nog goed werk. indien niet, behoud ik de originele code, maar komt er een 3de routine met het nieuwe display erin

De achtergrondkleur wordt met de text mee geschreven als je dat opgeeft met de derde parameter van setTextColor():


    tft.setTextColor(ST77XX_RED, ST77XX_BLACK, true );

En ook de andere libraries hebben zo hun methode om de achtergrond mee te nemen. Dus het s nergens voor nodig om zwarte vlakken te tekenen en/of de oude text in het zwart te tekenen.

PS: Of toch niet?
Dit werkt wel op de Bodmer TFT-eSPI library, maar blijkbaar niet op de library van Adafruit. Volgens hun eigen documentatie heeft die library die optie niet.

[Bericht gewijzigd door deKees op (21%)]

Hi deKees,

Ik had gisteren je opmerking nog even getest, maar je was er al achter, de font settings ondersteund geen extra argument voor de achtergrond.

Was het je opgevallen dat ik nog steeds plezier heb van je i2C printen?
Het enige is dat ik het nog in een kastje moet bouwen, dat zet ik voor komende vakantie dagen op de planning :-)

Ik ga een groot deel van de font standaard laten, ik wil namelijk graag met de oven regeling gaan testen.
Ben bij elkaar als een uur of 10 bezig geweest het onderste deel van het display zo in te richten dat het mij bevalt, dan maar basis GFX font.
De oven werking is belangrijker en ja benleentje, het is een aardige uitdaging, dat doe je niet eventjes voor een nieuw project.

Ik zet het zo wel door, al die info op het scherm, ik heb dit ook als leerproces gekozen,
ik laat bij dit project logging achterwegen via een disk je of WiFi maar door de opbouw die ik nu toe pas is dit vrij makkelijk er bij te plaatsen.

Als ik weer een stukje verder ben zal ik de hele code laten zien en dan kunnen jullie mij even doorzagen hierover. ;-)
Nu als eerste de handel weer terug zetten naar de standaard GFX font.

Nogmaals dank voor jullie info.

Groet,
Bram

Hi,

Vanavond na een lange dag werken toch maar even de tekst zo goed mogelijk geplaatst en gebruik gemaakt van een zwarte balk die ik vlak voor het schrijven van de nieuwe waarde plaatst.

Dit is het resultaat, er is geen "Ghosting" meer en het knipperen is beperkt, soms zichtbaar bij de seconden.
een aantal waarden worden veel minder vaak vernieuwd dit omdat het vernieuwen bij iedere loop doorgang onzin is.
Rechtonder heb ik de achtergrondkleur even blauw gelaten om te laten zien dat ik net om de tekst heen werk, meestal maar 1 pixel.

https://www.bramcam.nl/NA/NA-HF-Doosje-Oven/Display-Font_Probleem-03.png
.

De extraruimte achter de Humidity waarde is omdat er een extra nul kan komen bij 100% lucht vochtigheid.
Klaar voor de bovenzijde!

Groet,
Bram

°C kan je nog mooier krijgen. 4 lijntjes van 4 pixels lang. Zit ° niet in het tekstbestand?

Het is inderdaad onzinnig elke loop de datum te schrijven. Luchtdruk en vochtigheid wijzigen ook niet elke loop.

Je hebt blijkbaar ook al 2 waardes om te vergelijken of je iets al dan niet moet wijzigen. Kan je net zo goed de tekst terug schrijven in de achtergrondkleur. Hoef je jezelf niet druk te maken hoe groot je rechthoek moet zijn en waar die juist moet komen.

Nog een voordeel van de Bodmer library. Daar zit een bounds functie in waarmee je de grootte van je tekst kan opvragen.

Hi,

Ik zal eens kijken of in de tabel van het gebruikte font het graden tekentje beschikbaar is.
Even snel gekeken hoe ik het graden tekentje gemaakt heb, of eigenlijk uit een ander projectje gestolen. :-)


tft.fillRect(300, 221, 4, 4, ST77XX_WHITE);               // Degree circle <= Dit was het
tft.drawRect(300, 221, 4, 4, ST77XX_WHITE);               // Degree circle <= En dit is het nu, probleem opgelost

Dank er voor om me er op te wijzen, in de font file heb ik nog niet gekeken, dit doe ik later vandaag om dat ik het wel graag wil weten voor de volgende keer.

Dan zijn er dacht ik twee die me vertelde dat als ik de tekst eerst in zwart over de oude tekst schrijf en daarna de nieuwe waarde daar er overheen, dat dan er veel minder kans op flikker is.
Willen jullie mij die software truc laten zien aan de hand van de code die hieronder staat, in mijn hoofd krijg ik dit niet goed op een rijtje hoe dit netjes aan te pakken. :-)
Volgens mij is het wat lastiger door de opbouw van de tijd notatie, maar dat kan ik mis hebben...


// --------------------------------------------------------------------------------
// Place Time values on the screen
// --------------------------------------------------------------------------------
void Print_Time() {

    DateTime time = rtc.now();  
    tft.setFont(&FreeMonoOblique9pt7b);                   // Set specifieke font
    tft.setCursor(227, 208);                              // Positie waar de tijdwaarde op het scherm komt
    tft.setTextSize(1);                                   // Tekst grote is 1
    tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);         // Zet de voorgrond en de achtergrond kleur van de tijd
    tft.fillRect(228, 198, 88, 12, ST77XX_BLACK);         // Zwarte "wis balk"
    tft.print(time.timestamp(DateTime::TIMESTAMP_TIME));  // Plaatst te tijd op het scherm
    tft.setFont();                                        // Reset naar de standaard GFX font
}

Dank en groet,
Bram

De adafruit kan ook circels en gevulde circels maken dat is net even iets mooier voor het graden teken.

Hi benleentje,

Dat ik daar zelf niet naar gekekeken heb...
Dit gebruik ik nu voor het graden teken en ja dat is netter. :-)


tft.drawCircle(302, 222, 2, ST77XX_WHITE);    // Degree circle

Net en paar pixels minder dan mijn open vierkantje en ondanks dat het erg klein is, zie je goed dat dit beter is, dank je!

Groet,
Bram

Op maandag 16 december 2024 22:08:18 schreef blackdog:
gebruik gemaakt van een zwarte balk die ik vlak voor het schrijven van de nieuwe waarde plaatst.

Wat ik bij dit probleem heb overwogen is om de "teken letter" functie aan te passen. Gewoon even de source van de library induiken en dan die "if" er uit halen.

Het zit in de functie "drawChar",


     if (line & 1) {
          if (size_x == 1 && size_y == 1)
            writePixel(x + i, y + j, color);
          else
            writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y,
                          color);
        } else if (bg != color) {
          if (size_x == 1 && size_y == 1)
            writePixel(x + i, y + j, bg);
          else
            writeFillRect(x + i * size_x, y + j * size_y, size_x, size_y, bg);
        }

volgens mij heb ik die "else" hier zelf toegevoegd.

Op dinsdag 17 december 2024 14:32:56 schreef blackdog:

Dan zijn er dacht ik twee die me vertelde dat als ik de tekst eerst in zwart over de oude tekst schrijf en daarna de nieuwe waarde daar er overheen, dat dan er veel minder kans op flikker is.
Willen jullie mij die software truc laten zien aan de hand van de code die hieronder staat, in mijn hoofd krijg ik dit niet goed op een rijtje hoe dit netjes aan te pakken. :-)

Vrijwel geen enkel scherm/schermlibrary bewaart de geschreven tekst. En om de oude tekst te overschrijven in background-kleur moet je de oude tekst weten.

Die moet je dus zelf onthouden.

Ongetest:


// --------------------------------------------------------------------------------
// Place Time values on the screen
// --------------------------------------------------------------------------------
static char oldtime[11];

void Print_Time() {

    DateTime time = rtc.now();  
    tft.setFont(&FreeMonoOblique9pt7b);                   // Set specifieke font
    tft.setCursor(227, 208);                              // Positie waar de tijdwaarde op het scherm komt
    tft.setTextSize(1);                                   // Tekst grote is 1
    tft.setTextColor(ST77XX_BLACK, ST77XX_BLACK);         // Zet tekstkleur op achtergrond
    tft.print(oldtime);
    tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);         // Zet de voorgrond 
    //tft.fillRect(228, 198, 88, 12, ST77XX_BLACK);         // Zwarte "wis balk"
    strcpy(oldtime, time.timestamp(DateTime::TIMESTAMP_TIME);
    tft.print(oldtime);  // Plaatst te tijd op het scherm
    tft.setFont();                                        // Reset naar de standaard GFX font
}

De reden dat dit zin heeft (oude tekst met tekst overschrijven i.p.v. zwart balkje) is dat vrijwel ieder display pixel-voor-pixel gesschreven wordt. De Adafruit library heeft mooie functies voor blokjes en teksten, maar onder water komt dat uiteindelijk neer op een lange lijst pixels die een voor een via I2C of SPI naar een display worden geschreven.

En in dat schrijven naar het display zit de tijd: Dat duurt het langst.
Een stukje tekst van 10 karakters bevat veel minder pixels dan een even groot blokje. Dus dat is veel sneller, dus is de kans dat je het ziet gebeuren ook lager.

[Bericht gewijzigd door blurp op (14%)]

Hi blurp, :-)

Dank je, maar dit gaat niet zonder horten en stoten. *grin*

Het eerste probleem, jouw aanpassing van de code legt een probleem bloot betreffende de grote hoeveelheid tijdelijke bestanden,
die worden weggeschreven in de \AppData\Local\Temp van je gebruikers profiel in hier Windows-11.
Dat wijst mij er op, dat ik in mijn startup folder nog een script moet opnemen die deze temp directory moet wissen, ik doe niet anders voor mijn klanten, maar voor mijzelf... ;)

Hierdoor kreeg ik deze error bij het toepassen van jouw stukje code:
mingw32_gt_pch_use_address, at config/i386/host-mingw32.c:190: MapViewOfFileEx:

Ok /Temp is nu opgeschoond en dan komt deze error melding:

C:\Users\BlahBlah\Documents\Arduino\TFT-240-320-ST7789\TFT_240_320_ST7789_Teesny_LC_HFOven_08\TFT_240_320_ST7789_Teesny_LC_HFOven_08.ino:864:35: error: cannot convert 'String' to 'const char*'
864 | strcpy(oldtime, time.timestamp(DateTime::TIMESTAMP_TIME));
| ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| String
In file included from C:\Users\BlahBlah\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\cores\teensy3/WProgram.h:35,
from C:\Users\BlahBlah\AppData\Local\arduino\sketches\E91383A44E215B5120A0A5DD41E26393\pch\Arduino.h:6:
c:\users\BlahBlah\appdata\local\arduino15\packages\teensy\tools\teensy-compile\11.3.1\arm\arm-none-eabi\include\string.h:38:36: note: initializing argument 2 of 'char* strcpy(char*, const char*)'
38 | char *strcpy (char *__restrict, const char *__restrict);
| ^~~~~~~~~~~~

exit status 1

Compilation error: cannot convert 'String' to 'const char*'

Er was trouwens één haakje vergeten, achter dit stukje: (DateTime::TIMESTAMP_TIME); wat dit zou moeten zijn: (DateTime::TIMESTAMP_TIME));
Je wilt niet weten als ik code schrijf, hoeveel ik vergeet, als ik op de helft van de regel ben, dat ik dan al niet meer weet wat ik aan het begin heb bedoeld, dislecty is a BITCH!

Oja, dit commando heb ik nog nooit gezien: strcpy, ik neem even aan dat dit betekend: StringCopy?
Deze regel staat boven de Setup code, ik denk dat dit de bedoeling was: static char oldtime[11];

Zou dit een Teensy probleem zijn of iets in het stukje code dat je laat zien?

Goed dat je uitlegt dat hoe het naar het scherm schrijven werkt, dan kan ik daar ook rekening mee houden met mijn rode wijzer streepje van de meter balk.
Deze wordt nu over de volle breedte iedere loop doorgang gewist, en dat zijn veel pixels!

Dank en groet,
Bram

Print je de nieuwe tijd voor de str(ing)c(o)py, win je weer net wat tijd tussen wissen tekst en schrijven nieuwe tekst. Stringcopy blijkt geen copy naar char array toe te laten. Als ik me niet vergis is het dan toCharArray().

zie https://www.arduino.cc/reference/tr/language/variables/data-types/stri…

Op woensdag 18 december 2024 10:37:09 schreef blackdog:
Compilation error: cannot convert 'String' to 'const char*'[/i]

Oke, blijkbaar werd er met een String object gewerkt i.p.v. een ouderwetsche C char*. Aangepaste versie (met zonder ontbrekend haakje :-):


// --------------------------------------------------------------------------------
// Place Time values on the screen
// --------------------------------------------------------------------------------
String oldtime;

void Print_Time() {

    DateTime time = rtc.now();  
    tft.setFont(&FreeMonoOblique9pt7b);                   // Set specifieke font
    tft.setCursor(227, 208);                              // Positie waar de tijdwaarde op het scherm komt
    tft.setTextSize(1);                                   // Tekst grote is 1
    tft.setTextColor(ST77XX_BLACK, ST77XX_BLACK);         // Zet tekstkleur op achtergrond
    tft.print(oldtime);
    tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);         // Zet de voorgrond 
    //tft.fillRect(228, 198, 88, 12, ST77XX_BLACK);         // Zwarte "wis balk"
    oldtime = time.timestamp(DateTime::TIMESTAMP_TIME);
    tft.print(oldtime);  // Plaatst te tijd op het scherm
    tft.setFont();                                        // Reset naar de standaard GFX font
}

Op woensdag 18 december 2024 12:54:53 schreef buckfast_beekeeper:
Print je de nieuwe tijd voor de str(ing)c(o)py, win je weer net wat tijd tussen wissen tekst en schrijven nieuwe tekst.

En loop je het risico op een raceconditie waar de tijd verspringt tussen het printen en copieren, waardoor je de volgende update bagger krijgt.

Dan kun je beter met een tweede variabele werken, en de tijd opvragen voor je de oude tijd wist.

Hi,

blurp

Deze regel staat bij mij globaal boven in de code, ik neem aan dat dit de goede positie is? => String oldtime;


    DateTime time = rtc.now();  
    tft.setFont(&FreeMonoOblique9pt7b);                   // Set specifieke font
    tft.setCursor(227, 208);                              // Positie waar de tijdwaarde op het scherm komt
    tft.setTextSize(1);                                   // Tekst grote is 1
    tft.setTextColor(ST77XX_BLACK, ST77XX_BLACK);         // Zet tekstkleur op achtergrond
    tft.print(oldtime);                                   // Plaatst oude tijd in "zwart" over de aanwezigwe waarde heen
    tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);         // Zet de voorgrond kleur nieuwe tijd waarde
    oldtime = time.timestamp(DateTime::TIMESTAMP_TIME);   // Volt de "String" oldtime met de nieuwe klok tijd
    tft.setCursor(227, 208);                              // Positie waar de nieuwe tijdwaarde op het scherm moet komen
    tft.print(oldtime);                                   // Plaatst te tijd uit de string op het scherm
    tft.setFont();                                        // Reset naar de standaard GFX font

Dit is het stukje wat bijgewerkt is, het was opvallen dat ik de derde regel van onder, dat is voor de tweede keer dat ik de tekst positie moest aangeven.
Als ik dit niet doe komt de waarde "oldtime" half op de volgende regel terrecht.

Eigenlijk is het knipperen niet minder geworden, maar wat anders, dat kan betrekking hebben op de andere dynamische items die door een zwarte balk overschreven worden.
De items die door timers en zwarte balkjes op het scherm worden geplaatst, zal ik later vandaag door jouw constructie vervangen.
Ik neem dan aan dat ik b.v. deze string commando's moet gaan gebruiken:

String old_date
String old_hPa
String old_LabTemp
String old_MeterPoint
String old_Hum

Hieronder trouwens de hele code met nog tijdelijke code er in voor de i2c rotary print van deKees die er later uit gaat.


/**************************************************************************
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
 **************************************************************************/

#include <Adafruit_GFX.h>                                                               // Core graphics library
#include <Adafruit_ST7789.h>                                                            // Hardware-specific library for ST7789
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <UniversalTimer.h>
#include <Adafruit_ADS1X15.h>
#include <Adafruit_BME280.h>
#include "RTClib.h"
#include <ADC.h>
#include <I2C_Rotary_003.h>

// Extra Font
#include <Fonts/FreeMonoOblique9pt7b.h>
#include <Fonts/FreeSans9pt7b.h>


ADC *adc = new ADC();                                                                 // ADC object for the Teensy ADC

Adafruit_ADS1115 ads;                                                                 // Start ADC                                  
Adafruit_BME280 bme;                                                                  // Start BME Sensor
RTC_DS3231 rtc;                                                                       // Start Real Time Clock

unsigned long delayTime;

// Pin defenition SPI Display
  #define TFT_CS  10
  #define TFT_RST 8 
  #define TFT_DC  7

// For 1.3", 1.54", and 2.0" TFT with ST7789:
  Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// Timer Setting for BME280 Sensor value on the display
  UniversalTimer bme_Timer(5000, true);                                               // Every 5 seconds

// Timer Setting for DS3231 Time on the display
  UniversalTimer klok_Time_Timer(1000, true);                                         // Every 0.2 seconds

// Timer Setting for DS3231 Date on the display
  UniversalTimer klok_Date_Timer(60000, true);                                        // Every 60 seconds

// Timer Setting for DS3231 Date on the display
  UniversalTimer Main_oven_Temp_Timer(200, true);                                     // Every 0.2 seconds


// Thermistor properties Vishay NTCLE300E3502SB
#define RT0 5000                                                                      // NTC 25C value
#define B   3977                                                                      // Beta value Vishay NTC
//#define VCC 3,29901                                                                 // External reference voltage
#define VCC 1.247565                                                                  // External reference voltage
#define RA1 2540.000                                                                  // Pull-Up weerstand naar de referentie spanning voor de NTC in Ohm voor de A0 input ADS1115
#define RA2 2539.984                                                                  // Pull-Up weerstand naar de referentie spanning voor de NTC in Ohm voor de A1 input ADS1115
#define T0  (25 + 273.15)                                                             // Temperature T0 from datasheet, conversion from Celsius to kelvin for the NTC Sensor


float AVG_Celcius;


// Temperature progres bar settings
byte X = 10;
byte Y = 60;
byte W = 240;
byte H = 10;
byte progress = 0;

// -------------------------------------------------------------------------
//  Filter Classsetup
// -------------------------------------------------------------------------
class Filter 
{
public:
  int N = 0;                                                                          // Aantal te middelen waarde
  float *meetwaardes;                                                                 // Opslag individuele meetwaarden
  float accumulator = 0;                                                              // Optelsom van alle individuele meetwaarden
  int index = 0;                                                                      // Meetwaarden teller

  Filter(const int n)
  {
    meetwaardes = new float[n];
    N = n;
    for(int i = 0; i < n; i++)
    {  
      meetwaardes[i] = 0;
    }
  }

  ~Filter()
  {
    delete[] meetwaardes;
  }

  void AddSample(float NewSample)
  {  
    accumulator -= meetwaardes[index];        
    meetwaardes[index] = NewSample;                                                   // Bewaar nieuwe meetwaarde
    accumulator += meetwaardes[index];                                                // Accumuleer nieuwste meetwaarde
    index++; 
    index %= N;                                                                       // Teller loopt van 0 tot N-1
  }

  float Average()
  {  
    return accumulator/N;                                                             // Bereken de gemmiddelde waarde
  }
};

// Configuration averaging for the ADC inputs
Filter Filter_Oven(128);
Filter Filter_Ruimte(64);
Filter Filter_Voeding(16);
Filter Filter_Current(16);


String oldtime;


// 'Knuppel-235', 235x235px boot Logo Bitmap

// Hier staat normaal de code voor de BitMap Logo, maar de forum softare staat dit niet toe, te veel karakters :-)

// Declare 3 rotary objects.
// - All use the same I2C address
// - But different switch nrs 
I2C_Rotary Rotary_SW1(0xA0, 1);  // SW1
I2C_Rotary Rotary_SW2(0xA0, 2);  // SW2
I2C_Rotary Rotary_SW3(0xA0, 3);  // SW3

int SW1 = 0;
int SW2 = 0;
int SW3 = 0;



// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void setup(void) {
    
  Serial.begin(115200);
  Serial.println("Hello!");

// -------------------------------------------------------------------------
// Configuration Teensy LC ADC_0
// -------------------------------------------------------------------------
  adc->adc0->setReference(ADC_REFERENCE::REF_EXT);                                    // Selecteer de externe referentie ingang voor ADC_0
  adc->adc0->setAveraging(64);                                                        // Selecteer de middeling van de gebruikte ADC
  adc->adc0->setResolution(16);                                                       // Selecteerd de resolutie van de geselecteerde ADC
  adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);             // Selecteerd de conversie snelheid
  adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);                         // Selecteerd de sample snelheid
  adc->adc0->recalibrate();                                                           // Kalibreeer de ADC



// This initializer 240x320 TFT:
  tft.init(240, 320);                                                                     // Init ST7789 240x320
  tft.fillScreen(ST77XX_BLACK);
  tft.setRotation(3);
  tft.setSPISpeed(40000000);

// Displays NoiseAmp Logo on the screen
//  tft.drawBitmap(45, 0, epd_bitmap_Knuppel_235, 235, 235, ST77XX_BLACK, ST77XX_WHITE);
//  delay(500);                                                                           //Keeps the logo 0.5 seconds on the screen before Looping

//
  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
// Setup ADS1115 ADC
  ads.setGain(GAIN_ONE);                                                                // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  ads.startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_1, /*continuous=*/true);            // Start continuous conversions.
  ads.setDataRate(128);                                                                 // Set SampleRate


// Start the BME sensor at the correct i2c address
  bme.begin(0x76, &Wire);

// BME280 Sensor configuratie
  bme.setSampling(Adafruit_BME280::MODE_NORMAL,
                   Adafruit_BME280::SAMPLING_X16,                                       // temperature
                   Adafruit_BME280::SAMPLING_X16,                                       // pressure
                   Adafruit_BME280::SAMPLING_X16,                                       // humidity
                   Adafruit_BME280::FILTER_X16,
                   Adafruit_BME280::STANDBY_MS_250 );

// Srart the DS3231 Clock function 
  rtc.begin();

// Place standard characters and lines on the screen
  Basic_Screen_Setup();

// Put Date and Time for the first time on the screen
  Print_Date();

// Place the BME sensor value on the screen for the first time
  Print_bme();

// Start the timers
  bme_Timer.start();
  klok_Time_Timer.start();
  klok_Date_Timer.start();
  Main_oven_Temp_Timer.start();


// Temporary code for the three rotary encoders
   
// Set parameters for Rotary_SW1
  Rotary_SW1.m_MinValue =   5;
  Rotary_SW1.m_MaxValue = +314;
  Rotary_SW1.m_StepSize =   1;
  Rotary_SW1.m_Value    =   10;
  Rotary_SW1.SetDirection(0);
  Rotary_SW1.SetAccelleration(1);

// Set parameters for Rotary_SW2
  Rotary_SW2.m_MinValue =  0;
  Rotary_SW2.m_MaxValue =  +320;
  Rotary_SW2.m_StepSize =   1;
  Rotary_SW2.m_Value    =  10;
  Rotary_SW2.SetDirection(0);
  Rotary_SW2.SetAccelleration(1);

// Set parameters for Rotary_SW3
  Rotary_SW3.m_MinValue =  0;
  Rotary_SW3.m_MaxValue =  +320;
  Rotary_SW3.m_StepSize =   1;
  Rotary_SW3.m_Value    =  10;
  Rotary_SW3.SetDirection(0);
  Rotary_SW3.SetAccelleration(1);
// End temporary code for the three rotary encoders

}




// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void loop() {

unsigned long startTime = millis();                                                       // Get the current time at the start of the loop, just some debug code

int16_t adc_TI_0;
float volts0;

// ADC-0 of the ADS1115 is read here asymmetrically in the raw ADC conversion value
  adc_TI_0 = ads.readADC_SingleEnded(0);

// Here, from the ADS1115, the voltage is calculated from the ADC-0 input
  volts0 = ads.computeVolts(adc_TI_0);


// NTC Thermistors Steinhart and Hart Equation
float sample_Filter_Oven = (float)analogRead(A1);           // Here the oven NTC is still read by the Teensy LC ADC for the time being
float VRT = 1.247565 * sample_Filter_Oven / 65536.00; 
float VR = VCC - VRT;
float RT = VRT * RA1 / VR; 
float ln = log(RT / RT0);
float TX = (1 / ((ln / B) + (1 / T0)));                                        
 float Oven_Celcius = TX - 273.15;   

// Samples toevoegen en uitlezen van het middelings filter.
  Filter_Oven.AddSample(Oven_Celcius);
  float avg_Oven_Celcius = Filter_Oven.Average();

tft.setCursor(75, 35);                                    //Tijdelijke tekst Teensy ADC Thermistor Rode tekst op zwarte achtergrond
tft.setTextSize(2);
tft.setTextColor(ST77XX_RED, ST77XX_BLACK);
  tft.print(avg_Oven_Celcius, 4);



// Temporary code for setting various text positions using variable SW1, SW2 and SW3.
unsigned long loopTime = millis() - startTime;            // Calculate the loop time  Debug code
Serial.print("Loop time: ");
Serial.print(loopTime);
Serial.println(" ms");                                    // Print the loop time in milliseconds

int  Clicks2 = Rotary_SW2.Clicks();
int  Clicks3 = Rotary_SW3.Clicks();
int  Clicks1 = Rotary_SW1.Clicks();

SW1 = Rotary_SW1.m_Value;
SW2 = Rotary_SW2.m_Value;
SW3 = Rotary_SW3.m_Value;

Serial.print("SW1- "); Serial.println(SW1);
Serial.print("SW2- "); Serial.println(SW2);
Serial.print("SW3- "); Serial.println(SW3);
// End of temporary code


// Bar meter
tft.fillRect(5, 115, 310, 20, ST77XX_BLACK);                  // Zwarte "wis balk"
tft.drawFastVLine(SW1, 115, 20, ST77XX_RED);                  // Rode vertikale lijn, welke een ingezoomd deel deel van de waarde van de oven sensor aangeeft


// Here the timers are controlled for functions to be executed at a certain time
 if  (bme_Timer.check()) 
    {
      Print_bme();
    }
 if (klok_Time_Timer.check())
     {
      Print_Time();
     }
if (klok_Date_Timer.check())
     {
      Print_Date();
     }
}
// ------------------------ End loop ---------------------------------------




void Main_oven_Temp() {

// Samples toevoegen en uitlezen van het middelings filter.
//   Filter_Oven.AddSample(Oven_Celcius);
//   float avg_Oven_Celcius = Filter_Oven.Average();

// tft.setCursor(75, 35);                                    //Tijdelijke tekst Teensy ADC Thermistor Rode tekst op zwarte achtergrond
// tft.setTextSize(4);
// tft.setTextColor(ST77XX_RED, ST77XX_BLACK);
//   tft.print(avg_Oven_Celcius, 4);
}


void Print_Date() {

// Place Date values on the screen
  DateTime time = rtc.now();
  tft.setFont(&FreeMonoOblique9pt7b);
tft.setCursor(57, 208);
tft.setTextSize(1);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.fillRect(58, 198, 110, 12, ST77XX_BLACK);               // Black &#8220;erase bar&#8221;
  tft.print(time.timestamp(DateTime::TIMESTAMP_DATE));      // Places time on the display

   
tft.setCursor(3, 208);
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
tft.print("Date:");
tft.setCursor(173, 208);
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
tft.print("Time:");
tft.setFont();                                              // Reset font
}


void Print_Time() {

// Place Time values on the screen
  DateTime time = rtc.now();  
    tft.setFont(&FreeMonoOblique9pt7b);                   // Set specifieke font
    tft.setCursor(227, 208);                              // Positie waar de tijdwaarde op het scherm komt
    tft.setTextSize(1);                                   // Tekst grote is 1
    tft.setTextColor(ST77XX_BLACK, ST77XX_BLACK);         // Zet tekstkleur op achtergrond
    tft.print(oldtime);                                   // Plaatst oude tijd in "zwart" over de aanwezigwe waarde heen
    tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);         // Zet de voorgrond kleur nieuwe tijd waarde
    oldtime = time.timestamp(DateTime::TIMESTAMP_TIME);   // Volt de "String" oldtime met de nieuwe klok tijd
    tft.setCursor(227, 208);                              // Positie waar de nieuwe tijdwaarde op het scherm moet komen
    tft.print(oldtime);                                   // Plaatst te tijd uit de string op het scherm
    tft.setFont();                                        // Reset naar de standaard GFX font
}

void Print_bme() {

// Places the humidity value from the BME sensor on the display     
  tft.setFont(&FreeMonoOblique9pt7b);    
tft.setCursor(121, 182);
tft.setTextSize(1);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.fillRect(121, 172, 33, 12, ST77XX_BLACK);               // Black &#8220;erase bar&#8221;
  tft.print(bme.readHumidity(), 0);  

// Places the Pressure value from the BME sensor on the display
tft.setCursor(238, 182);
tft.setTextSize(1);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.fillRect(237, 172, 78, 12, ST77XX_BLACK);               // Black &#8220;erase bar&#8221;
  tft.print(bme.readPressure()/100);  
        
// Places the Temperature value from the BME sensor on the display
tft.setCursor(238, 232);
tft.setTextSize(1);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
tft.fillRect(239, 222, 56, 12, ST77XX_BLACK);               // Black &#8220;erase bar&#8221;
  tft.print(bme.readTemperature());
tft.setFont();
}


// ----------------------------------------------------------------------------------
// Below is the code for the characters that are always on the screen and only written once.
// ----------------------------------------------------------------------------------
void Basic_Screen_Setup() {
  
  tft.fillScreen(ST77XX_BLACK);                               // Erase the screen to black
tft.drawRect(0, 0, 320, 240, ST77XX_WHITE);                   // Frames and lines for screen layout
tft.drawFastHLine(0, 164, 320, ST77XX_WHITE);                 // Frames and lines for screen layout
tft.drawFastHLine(0, 190, 320, ST77XX_WHITE);                 // Frames and lines for screen layout
tft.drawFastHLine(0, 216, 320, ST77XX_WHITE);                 // Frames and lines for screen layout
tft.drawFastVLine(171, 166, 51, ST77XX_WHITE);                // Vertical line for separation of values at the bottom of the display

tft.fillRect(4, 140, 313, 4, 0x07E0);                         // Thick green line for the meter scale
tft.fillRect(150, 134, 21, 12, 0xFFEA);                       // Yellow block in the middle indicating the +0.01C and the -0.01C oven temperature range.
tft.drawFastVLine(10, 136, 10, 0xFFE0);                       // Vertical Yellow Line for Bar 47.85 C
tft.drawFastVLine(60, 136, 10, 0xFFE0);                       // Vertical Yellow Line for Bar 47.90 C
tft.drawFastVLine(110, 136, 10, 0xFFE0);                      // Vertical Yellow Line for Bar 47.95 C
tft.drawFastVLine(210, 136, 10, 0xFFE0);                      // Vertical Yellow Line for Bar 4.05 C
tft.drawFastVLine(260, 136, 10, 0xFFE0);                      // Vertical Yellow Line for Bar 48.10 C
tft.drawFastVLine(310, 136, 10, 0xFFE0);                      // Vertical Yellow Line for Bar 48.15 C

tft.drawFastVLine(159, 135, 11, 0xF800);                      //
tft.drawFastVLine(160, 135, 11, 0xF800);                      // Vertical RED Line for Bar 48.00C, three in the middle of the yellow bar
tft.drawFastVLine(161, 135, 11, 0xF800);                      //

tft.drawFastHLine(4, 112, 312, ST77XX_GREEN);                 //
tft.drawFastVLine(4, 112, 30, ST77XX_GREEN);                  // Green frame around the red meter pointer
tft.drawFastVLine(316, 112, 30, ST77XX_GREEN);                //

tft.drawFastHLine(4, 92, 312, ST77XX_GREEN);                 //
tft.drawFastVLine(4, 92, 22, ST77XX_GREEN);                  // Green frame around the P.I.D Value
tft.drawFastVLine(316, 92, 22, ST77XX_GREEN);                //

// Characters P, I and D Value's
  tft.setFont(&FreeMonoOblique9pt7b);
tft.setTextSize(1);
tft.setTextColor(0x07E0);
tft.setCursor(7, 106);
tft.print("P:");
tft.setCursor(128, 106);
tft.print("I:");
tft.setCursor(220, 106);
tft.print("D:");
tft.setFont();

// Characters under the meter scale
  tft.setFont(&FreeMonoOblique9pt7b);
tft.setTextSize(1);
tft.setTextColor(0x07E0);
tft.setCursor(35, 159);
tft.print("47.9");
tft.setCursor(148, 159);
tft.print("48");
tft.setCursor(235, 159);
tft.print("48.1");

// Humidity characters BME sensor  
tft.setCursor(3, 182);
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN);
tft.print("Humidity:");
tft.setTextColor(ST77XX_WHITE);
tft.setCursor(156, 182);
tft.print("%");

// Preasure characters BME sensor
tft.setCursor(176, 182);
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN);
tft.print("hPa: ");
tft.setFont();

// characters ambient temperature
  tft.setFont(&FreeMonoOblique9pt7b);
tft.setCursor(3, 232);
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN);
tft.print("LAB Temperature: ");

// Degree caracters BME sensor    
tft.setCursor(1, 111);
tft.setTextSize(1);
tft.drawCircle(302, 222, 2, ST77XX_WHITE);                     // Degree circle
tft.setTextColor(ST77XX_WHITE);    
tft.setCursor(304, 232);
tft.print("C");                                                // "C&#8221; from the degree unit
tft.setFont();

}

Er schien me net voor ik op Posten druk iets te binnen, bij het plaatsen van de nieuwe tijd over de zwarte tijd heen, gebruikt de compiler misschien de positie achter de oude "zwarte" tekst, klopt dit volgens jullie, of is er een andere rede?

Dank weer voor de input!
Bram

ik gebruikte dit in één van mijn vorige software versies. ik stuur vanuit een 'updateScreen' functie dan een aantal regels uit die onderstaande oproept

void printTFT (float oldValue, int xOld, float value, int x, int y, int color, int bgcolor) {
  if (oldValue != value) {
    tft.setCursor(xOld, y);
    tft.setTextColor(bgcolor, bgcolor);
    tft.print(oldValue);
    tft.setCursor(x, y);
    tft.setTextColor(color, bgcolor);
    tft.print(value);
  }
}

ik zeg dan bv

printTFT(oldTemp, 15, newTemp, 15, 100, white, black);
oldTemp = newTemp;
xOld = laatste X waarde;

dan wordt er dus op X=15 en Y=100 tekst gezet.
is de waarde gelijk, gebeurt er niks

is de waarde verschillend, zet ik eerst de oude waarde weer op het display in de achtergrondkleur
en dan de nieuwe waarde in het tekstkleur.

is het nieuwe getal een karakter langer, dan kon ik ook de Xwaarde nog wat meer opschuiven.
als je dus enkel updates doet als de waarde effectief veranderd, dan zie je weinig geknipper.

heb je 10 waardes en is er 1veranderd, dan knipperen de overige 9 ook niet

is er bv een waarde die negatief is, die rood moet worden, kan je ook gewoon dit toevoegen in die subroutine. alle negatieve waardes komen dan rood.


if (value < 0){
  color = red;
}

of je zet het waar je die regel oproept
printTFT(oldTemp, 15, newTemp, 15, 100, red, black);

Er schiet me net voor ik op Posten druk iets te binnen, bij het plaatsen van de nieuwe tijd over de zwarte tijd heen, gebruikt de compiler misschien de positie achter de oude "zwarte" tekst, klopt dit volgens jullie, of is er een andere rede?

Op zich klopt dat wel inderdaad, maar dat heb je al opgelost door de cursor opnieuw te zetten.