ST7735 display flickering

Thread Starter

zazas321

Joined Nov 29, 2015
936
Hey. I have used an OLED 1.3" display for my project and did not have any problems.
for my OLED, i had a function:
Code:
void OLED_display(int number1){
    int address=0;

    display.setTextSize(4);
    display.clearDisplay();
    display.setCursor(0,0);                
    display.println(EEPROM.readUShort(address));
    //Serial.print("OLED display quantity = ");
    //Serial.println(EEPROM.readUShort(address));
    address += sizeof(unsigned short); 
    //display.display();
    display.setCursor(0,32);                 
    display.println(number1);        // number2 means number to_pick
    display.setTextSize(1);
    display.setCursor(64,32);
    display.println(current_status);       
    display.setCursor(64,40);
    display.println(DEVICE_ID);       
    display.setCursor(64,48); 
    display.println(EEPROM.get(address,eeprom_serial));      //print SERIAL id
    address += 10;
    display.setCursor(64,56); 
    display.println(encoder.displaycounter);      //print SERIAL id
    display.display();
}
Being called every 1second to update all the values that I need on my display.

I have decided to switch to bigger display ST7735 and wrote an identical function for it:
Code:
void TFT_setup(){
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(1);
  pinMode(TFT_BACKLIGHT, OUTPUT);
  //tft.invertDisplay(false);
  digitalWrite(TFT_BACKLIGHT, HIGH); // Backlight on
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_GREEN);

}


void TFT_display(int number1){
    int address=0;
    tft.setTextSize(3);
    tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(0, 0);   
    tft.print(EEPROM.readUShort(address));            
    address += sizeof(unsigned short); 
    tft.setCursor(0,32);                 
    tft.print(number1);        // number2 means number to_pick
    tft.setTextSize(1);
    tft.setCursor(64,32);
    tft.print(current_status);       
    tft.setCursor(64,40);
    tft.print(DEVICE_ID);       
    tft.setCursor(64,48); 
    tft.print(EEPROM.get(address,eeprom_serial));      //print SERIAL id
    address += 10;
    tft.setCursor(64,56); 
    tft.print(encoder.displaycounter);      //print SERIAL id

}
However, this TFT display flickers everytime I call TFT_display function. I believe the reason for that is because when i use tft.fillscreen it takes a while to print all the values on the screen?. Im not sure why I am not able to see any flickering on my SSD1306 OLED display.

Could someone suggest me a way to fix this problem since its very annoying and not convenient to look at such delay that is flickering every time a value is being changed.
 

Ian Rogers

Joined Dec 12, 2012
1,136
Two ways to stop flicker.. A) use a screen buffer ( Needs oodles of RAM ) or 2) only refresh the parts of the screen thats needed.

If you have text at 10,10 and the font is 26 x 24 you need to blank the text out before re-writing. OR! re-write the font routine to print the backcolour when needed... ( This is what I do.. ) If this is on an Arduino platform I think the printchar() allows non transparent characters.. but you'll need to check.
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Two ways to stop flicker.. A) use a screen buffer ( Needs oodles of RAM ) or 2) only refresh the parts of the screen thats needed.

Thanks for response.
If you have text at 10,10 and the font is 26 x 24 you need to blank the text out before re-writing. OR! re-write the font routine to print the backcolour when needed... ( This is what I do.. ) If this is on an Arduino platform I think the printchar() allows non transparent characters.. but you'll need to check.
I am using ESP32 microcontroller so I might get away with using ram method? refreshing the parts that I need is probably gonna be very difficult to keep track since I have quite a few variables that I want to display and they change quite often
 

ericgibbs

Joined Jan 29, 2010
18,848
hi z,
The way I use a TFT with multiple line text data is to Write the TFT background colour only over a rectangular area of the the screen thats going get a data change, don't refresh the whole screen.
What is your SPI data transfer rate.?
E
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
hi z,
The way I use a TFT with multiple line text data is to Write the TFT background colour only over a rectangular area of the the screen thats going get a data change, don't refresh the whole screen.
What is your SPI data transfer rate.?
E
I am not too certain about the SPI speed. I havent set any configuration for that. I use default setting


About writing the TFT backgorund colour over the area thats going to change. Do I just write a black rectangle on my black background? I need to also ensure that this rectangle does not cover any data arround it
 
Last edited:

Thread Starter

zazas321

Joined Nov 29, 2015
936
Yes sure.
1598415017545.jpeg

The most important part of the display are the first 2 numbers at the top left:
void TFT_display(int number1){
//tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
int address=0;
tft.setTextSize(3);
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(0, 0);
tft.print(EEPROM.readUShort(address));
address += sizeof(unsigned short);
tft.setCursor(0,32);
tft.print(number1); // number2 means number to_pick
}

I am writing those numbers in textsize 3 coordinates (0,0) and (0,32)


I have managed to find few other simmilar discussions about this problem and someone suggests to use function tft.setColor(foreground, background) . However, this function does not even exist on the Adafruit library that I am using.
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
So I managed to make some progress. In my TFT_display_setup() function I had setup a text colour as following:
tft.setTextColor(ST77XX_GREEN);

Since I only pass one argument to this function, it makes my text green but transparent background.

If I use tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK); instead, that makes my background black instead of transparent which means everytime I want to print something on my display, its simply just going to "overwrite" the previous data by drawing a black background on top of it , perhaps thats what you meant initially.

Also, Is it good idea to keep rewriting data even if its not changing? I have set up my TFT_display loop to write new data every 1 second. That way, I do not need to keep track whether the variables have changed or not, if they did, they will be updated, if not, they will remain the same.

I could also implent a global_flag variable that would check if any one of the variables inside display have changed, If the flag is set, I would run the tft_display function once redrawing all the data ( or just the portion of the data) and reset the flag. But I am not sure if that is necessary?
 

trebla

Joined Jun 29, 2019
542
Since displays are usually slow devices, rewriting whole display can be visible for human eye. Therefore is better to make temporary variables to check particular data change and if there is difference between old an new data only then send this data to display. If i understood right this library, you can set before each string color attributes (if needed) or set those at once in the beginning of your code. Then you can send only this text to display which is needed to be changed and text/background color will be same as before.
 

ericgibbs

Joined Jan 29, 2010
18,848
hi z,
That layout is similar the TFT I use, ie: 4 lines of 'large' text.
Only refresh the Text line data that has changed since the last update.
If it has changed write a Rectangular area in the Background colour to clear the old data, then the new data line.

I find that the slight 'flicker effect' of doing it this way, draws the attention to the person reading the display to the line change that has taken place.

If you use fixed labels on a data line, don't refresh that display area under the Label.

E
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Thanks for the help.

I believe that should do the trick:
Code:
int local_eeprom_quantity = eeprom_quantity; // SETS THE VALUES ONLY AT THE BEGGINING OF PROGRAM
int local_number_to_pick = number_to_pick;
void TFT_display_update(int number1){   
    tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
    int address=0;
    tft.setTextSize(3);
    //tft.fillScreen(ST77XX_BLACK);  
    if(local_eeprom_quantity =! eeprom_quantity)
    {
      tft.setCursor(0, 0);
      tft.print(EEPROM.readUShort(address));   //quantity inside         
      address += sizeof(unsigned short);
      local_eeprom_quantity = eeprom_quantity;
    }
    if(local_number_to_pick != number_to_pick)
    {
      tft.setCursor(0,32);                 
      tft.print(number1);        // number2 means number to_pick
      local_number_to_pick = number_to_pick;
    }
}
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
I realized my previous method wont work very well. Lets say I am displaying a number 100. When I want to display the number 99, I am going to write a 99 with a background colour which should just replace the number 100, but since number 99 is smaller ( 2 digits instead of 3), I am not going to clear the lat digit therefore resulting in displaying number 990
 

jpanhalt

Joined Jan 18, 2008
11,087
It is hard to be general as there are a lot of possibilities. In the situation you mention some possibilities are:
1) Right justify all numbers and print null, 9, 9
2) Assume the largest number to be displayed is 4 digits. Then erase only 4 digit and write the new number.
3) As in #2, but pad all prints to fill the spaces.
4) Left justify, then print 99 + clear rest of line. Easily done if you can read the screen, but that is not required.

And so forth.
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Thanks for the response.
I like your suggestion at #2

I am a bit confused because I am not actually erasing anything I am just overwriting the data on top of the previous data:
Code:
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
    if(local_eeprom_quantity != eeprom_quantity)
    {
      tft.setCursor(0, 0);
      tft.print(eeprom_quantity);   //quantity inside          
      address += sizeof(unsigned short); 
      local_eeprom_quantity = eeprom_quantity;
    }
As you can see from the code above, if the local_eeprom_quantity does not match the eeprom_quantity, I am going to print a latest eeprom_quantity value.

What I would need to do I guess is something like that:
Code:
tft.setTextColor(ST77XX_GREEN, ST77XX_BLACK);
    if(local_eeprom_quantity != eeprom_quantity)
    {
      tft.setCursor(0, 0);
      tft.print(9999);   // write 4 digit number to clean area  
      tft.print(eeprom_quantity);   //quantity inside          
      address += sizeof(unsigned short); 
      local_eeprom_quantity = eeprom_quantity;
    }
I am not sure how efficient is writing twice but that should work
 

ericgibbs

Joined Jan 29, 2010
18,848
hi z,
The time to write a rectangle in the background colour in order to over write the previous data area and then write the new data in the foreground colour is very small.
Try it.
E
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
hi z,
The time to write a rectangle in the background colour in order to over write the previous data area and then write the new data in the foreground colour is very small.
Try it.
E
I have found a function :
Code:
tft.drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
for w and h, I need to know the length and height of my rectangle. For example if I want to clear an area of textsize = 3 and 4 digits, How can I calculate the length and height?
 

jpanhalt

Joined Jan 18, 2008
11,087
Of course, there is no "erase". I always write something. For a single byte, writing 0x00 clears that byte. If the characters are 8x8 (unusual), then you write that 8 times.
 

ericgibbs

Joined Jan 29, 2010
18,848
for w and h, I need to know the length and height of my rectangle. For example if I want to clear an area of textsize = 3 and 4 digits, How can I calculate the length and height?
Hi,
You must already know the X,Y coordinates on the TFT.
If in doubt write some test rectangles in a different colour to the background and adjust X,Y until you match the required location.
E
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Hi,
You must already know the X,Y coordinates on the TFT.
If in doubt write some test rectangles in a different colour to the background and adjust X,Y until you match the required location.
E
Thanks! The only problem was the
drawRect function is actually not filliing the background but only the outline of rectangle.
I need to use fillRect() function. Now it works fine!
 
Top