Flickering OLED

Hi How to stop screen flickering ?

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_MOSI 23  // Data out
#define TFT_SCLK 18  // Clock out
#define TFT_CS   22// 
#define TFT_DC    21 //
#define TFT_RST   -1  // pin# 2

// Create an instance of the display driver
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

//int Hz;
//int amp;
//int faze;

uint Hz;
uint amp;
uint faze;
uint Gb;
uint Thr;
int lastHz;
int botonState = 0;

void setup()
{
  Serial.begin(115200);

  // Initialize the display
  // tft.init(135, 240); // Adjust resolution if your display is different
  tft.init(170, 320);
  tft.setRotation(3); // Adjust rotation as needed (0-3),0 = viertical, 1= horyzontal upside down, 2= viertical 180 deg , 3=horyzontal normal,

  // Clear the screen
  //tft.fillScreen(ST77XX_BLACK);//++++++++++++++++++++++++++++++++
  tft.fillScreen(ST77XX_BLUE);

  // Set text properties
  tft.setTextWrap(false); // Disable text wrapping
  tft.setTextSize(4);     // Set text size
  // tft.setTextColor(ST77XX_WHITE); // Set text color  +++++++++++++++++++
  tft.setTextColor(ST77XX_YELLOW); // Set text color
  // Position and print "Hello World!"
  // tft.setCursor(10, 50); // Set cursor position (x, y)
  // tft.print("Hello World!");

  pinMode(12, INPUT_PULLUP);  //amp ++
  pinMode(14, INPUT_PULLUP);  // amp --
  pinMode(2, INPUT_PULLUP);
}
void loop() {
  /////////////////
  int mV = (amp);                    // Rx comp
  int ph = (faze);                   // Rx comp
  int deg = (Gb);                    //Tx ground comp

  mV = map(mV, 0, 512, 0, 3300);     //  comp amp
  ph = map(ph, 0, 1023, 0, 360);     // comp phaze
  deg = map(deg, 0, 1023, 0, 360);   // Tx phaze

  if (digitalRead(2) == 0) {
    botonState = (botonState + 1) % 3;
    delay (200);
  }
  switch (botonState)
  {
    case 0:
      if (digitalRead(12) == LOW)
      {
        Hz++;

      }
      if (digitalRead(14) == LOW)
      {
        Hz--;

      }
      //////////////////
    
      /*
        if (Hz != lastHz)
        {
        tft.print( Hz);;
        lastHz = Hz;
        }
      */
      ////////////////
      tft.fillScreen(ST77XX_BLUE);
      tft.setCursor(0, 0); // Set cursor position (x, y)
      tft.print("C0 Hz = ");
      tft.print( Hz);
      break;

    case 1:
      if (digitalRead(12) == LOW)
      {
        amp++;

      }
      if (digitalRead(14) == LOW)
      {
        amp--;

      }
      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(0, 40); // Set cursor position (x, y)
      tft.print("C1  A = ");
      tft.print(amp);
      break;
    case 2:
      if (digitalRead(12) == LOW)
      {
        faze++;

      }
      if (digitalRead(14) == LOW)
      {
        faze--;

      }

      tft.fillScreen(ST77XX_RED);
      tft.setCursor(0, 80); // Set cursor position (x, y)
      tft.print("C2");
      tft.print(" F = ");
      tft.print(faze);
      break;
  }
  delay(100);
  Serial.print("  Hz =  "); Serial.print(Hz);
  Serial.print("  amp   =  "); Serial.print(amp);
  Serial.print("  faze  =  "); Serial.print( faze );
  Serial.println();
}
  • Only print to the screen when a displayed value changes
  • Only clear the whole screen when you really need to
  • In order to clear a previously printed value when it changes either write over the original value in the background colour or draw a rectangle over it in the background colour before printing the new value
1 Like

I tried two options = not good

  ///////////////////////////////////////////////////////
      // tft.fillRect(0, 0, 200, 50, ST77XX_BLUE);  // NG
      tft.setTextColor(ST77XX_BLUE);                // Ng
      /////////////////////////////////////////////////////////
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_MOSI 23  // Data out
#define TFT_SCLK 18  // Clock out
#define TFT_CS   22// 
#define TFT_DC    21 //
#define TFT_RST   -1  // pin# 2

// Create an instance of the display driver
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

//int Hz;
//int amp;
//int faze;

uint Hz;
uint amp;
uint faze;
uint Gb;
uint Thr;
int lastHz;
int botonState = 0;
int ST7789_BLUE;

void setup()
{
  Serial.begin(115200);

  // Initialize the display
  // tft.init(135, 240); // Adjust resolution if your display is different
  tft.init(170, 320);  // high, with
  tft.setRotation(3); // Adjust rotation as needed (0-3),0 = viertical, 1= horyzontal upside down, 2= viertical 180 deg , 3=horyzontal normal,

  // Clear the screen
  //tft.fillScreen(ST77XX_BLACK);//++++++++++++++++++++++++++++++++
  tft.fillScreen(ST77XX_BLUE);

  // Set text properties
  tft.setTextWrap(false); // Disable text wrapping
  tft.setTextSize(4);     // Set text size
  // tft.setTextColor(ST77XX_WHITE); // Set text color  +++++++++++++++++++
  // tft.print( Hz); // Set text color
  // Position and print "Hello World!"
  // tft.setCursor(10, 50); // Set cursor position (x, y)
  // tft.print("Hello World!");

  pinMode(12, INPUT_PULLUP);  //amp ++
  pinMode(14, INPUT_PULLUP);  // amp --
  pinMode(2, INPUT_PULLUP);
}
void loop() {
  /////////////////
  int mV = (amp);                    // Rx comp
  int ph = (faze);                   
  int deg = (Gb);                    



  if (digitalRead(2) == 0) {
    botonState = (botonState + 1) % 3;
    delay (200);
  }
  switch (botonState)
  {
    case 0:
      if (digitalRead(12) == LOW)
      {
        Hz++;

      }
      if (digitalRead(14) == LOW)
      {
        Hz--;

      }
      //////////////////
      /*
        if (speed != lastspeed)
        {
        display(x,y, speed);
        lastspeed = speed;
        }
      */
      /*
        if (Hz != lastHz)
        {
        tft.print( Hz);;
        lastHz = Hz;
        }
      */
     
      tft.setCursor(0, 0); // Set cursor position (x, y)
      
      ///////////////////////////////////////////////////////
      // tft.fillRect(0, 0, 200, 50, ST77XX_BLUE);  // NG
      tft.setTextColor(ST77XX_BLUE);                // Ng
      /////////////////////////////////////////////////////////
      
      tft.print( Hz);
      tft.setTextColor(ST77XX_YELLOW);
      tft.print("C0 Hz = ");
      tft.print( Hz);

      break;

    case 1:
      if (digitalRead(12) == LOW)
      {
        amp++;

      }
      if (digitalRead(14) == LOW)
      {
        amp--;

      }
      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(0, 40); // Set cursor position (x, y)
      tft.print("C1  A = ");
      tft.print(amp);
      break;
    case 2:
      if (digitalRead(12) == LOW)
      {
        faze++;

      }
      if (digitalRead(14) == LOW)
      {
        faze--;

      }

      tft.fillScreen(ST77XX_RED);
      tft.setCursor(0, 80); // Set cursor position (x, y)
      tft.print("C2");
      tft.print(" F = ");
      tft.print(faze);
      break;
  }
  // delay(1000);
  Serial.print("  Hz =  "); Serial.print(Hz);
  Serial.print("  amp   =  "); Serial.print(amp);
  Serial.print("  faze  =  "); Serial.print( faze );
  Serial.println();
}

FYI: ST7789 screens are not OLED. They are TFT (a type of LCD).

You are still clearing the screen:

tft.fillScreen(ST77XX_BLACK);
tft.fillScreen(ST77XX_RED);

If you want to change the background colour of the screen, this means sending over 160,000 bytes of data to the display. That will be slow and cause flicker.

@tom321
as mentioned above, you are still clearing the whole screen at every change of Hz or amp value.

To make things better you could clear only a small rectangle over old Hz value and than print a new digits at the place.

Or print the old text in the background color to let it disappear and then print the new value.

It is printing in blue = text not visible

      int currentHz;
      int previousHz;
      if (currentHz != previousHz)
      {
        tft.setCursor(0, 0);
        tft.setTextColor(ST77XX_BLUE);
        tft.print( previousHz);
      }
      tft.setCursor(0, 0); // Set cursor position (x, y)

      ///////////////////////////////////////////////////////
      // tft.fillRect(0, 0, 200, 50, ST77XX_BLUE);  // NG
      // tft.setTextColor(ST77XX_BLUE);                // Ng
      /////////////////////////////////////////////////////////
/*
      //tft.print( Hz);
      tft.setTextColor(ST77XX_YELLOW);
      tft.print("C0 Hz = ");
      tft.print( Hz);

      break;
      /*
        

This one is printing is printing numbers in yellow but on the previous text so after some time text become yellow rectangles.


  if (digitalRead(2) == 0) {
    botonState = (botonState + 1) % 3;
    delay (200);
  }
  switch (botonState)
  {
    case 0:
      if (digitalRead(12) == LOW)
      {
        Hz++;

      }
      if (digitalRead(14) == LOW)
      {
        Hz--;

      }
      //////////////////
      /*
        if (speed != lastspeed)
        {
        display(x,y, speed);
        lastspeed = speed;
        }
      */
      /*
        if (Hz != lastHz)
        {
        tft.print( Hz);;
        lastHz = Hz;
        }
      */
      int currentHz;
      int previousHz;
      if (currentHz != previousHz)
      {
        tft.setCursor(0, 0);
        tft.setTextColor(ST77XX_BLUE);
        tft.print( previousHz);
      }
      tft.setCursor(0, 0); // Set cursor position (x, y)

      ///////////////////////////////////////////////////////
      // tft.fillRect(0, 0, 200, 50, ST77XX_BLUE);  // NG
      // tft.setTextColor(ST77XX_BLUE);                // Ng
      /////////////////////////////////////////////////////////

      //tft.print( Hz);
      tft.setTextColor(ST77XX_YELLOW);
      tft.print("C0 Hz = ");
      tft.print( Hz);

      break;

Let's suppose that you have printed 123 in yellow text on a blue background at 10, 12 and now want to print 456 at the same place in yellow text. Here is the sequence that you need to use

  1. Change to printing blue text
  2. Print 123 at 10, 12 to erase the 123
  3. Change to printing yellow text
  4. Print 456 at 10, 12 to show the new value

Post #2 is the solution.

  1. Set main background color.
  2. Set main text color.
  3. Set text location.
  4. Write newText.
  5. If newText does not equal oldText...
    • set text color to main background color
    • set text location
    • write newText (as background color)
    • store newText as oldText
    • set text color to main text color.

and what I missing ?

#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>

#define TFT_MOSI 23  // Data out
#define TFT_SCLK 18  // Clock out
#define TFT_CS   22// 
#define TFT_DC    21 //
#define TFT_RST   -1  // pin# 2

// Create an instance of the display driver
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

//int Hz;
//int amp;
//int faze;

uint Hz;
uint amp;
uint faze;
uint Gb;
uint Thr;
int lastHz;
int botonState = 0;
int ST7789_BLUE;

void setup()
{
  Serial.begin(115200);

  // Initialize the display
  // tft.init(135, 240); // Adjust resolution if your display is different
  tft.init(170, 320);  // high, with
  tft.setRotation(3); // Adjust rotation as needed (0-3),0 = viertical, 1= horyzontal upside down, 2= viertical 180 deg , 3=horyzontal normal,
tft.fillScreen(ST77XX_BLUE);
  tft.setTextWrap(false); // Disable text wrapping
  tft.setTextSize(4);     // Set text size
  tft.setTextColor(ST77XX_YELLOW); // Set text color  +++++++++++++++++++

  pinMode(12, INPUT_PULLUP);  //amp ++
  pinMode(14, INPUT_PULLUP);  // amp --
  pinMode(2, INPUT_PULLUP);
}
void loop() {
  if (digitalRead(2) == 0) {
    botonState = (botonState + 1) % 3;
    delay (200);
  }
  switch (botonState)
  {
    case 0:
      if (digitalRead(12) == LOW)
      {
        Hz++;

      }
      if (digitalRead(14) == LOW)
      {
        Hz--;

      }
    
      int currentHz;
      int previousHz;
      currentHz = Hz;
      if (currentHz != previousHz)
      {
        tft.setCursor(0, 0);
        tft.setTextColor(ST77XX_BLUE);
        tft.print( previousHz);
      }
      tft.setCursor(0, 0); // Set cursor position (x, y)
      tft.setTextColor(ST77XX_YELLOW);
      tft.print("C0 Hz = ");
      tft.print( Hz);

      break;
      /*
             case 1:
               if (digitalRead(12) == LOW)
               {
                 amp++;

               }
               if (digitalRead(14) == LOW)
               {
                 amp--;

               }
              // tft.fillScreen(ST77XX_BLACK);
               tft.setCursor(0, 40); // Set cursor position (x, y)
               tft.print("C1  A = ");
               tft.print(amp);
               break;
             case 2:
               if (digitalRead(12) == LOW)
               {
                 faze++;

               }
               if (digitalRead(14) == LOW)
               {
                 faze--;

               }

              // tft.fillScreen(ST77XX_RED);
               tft.setCursor(0, 80); // Set cursor position (x, y)
               tft.print("C2");
               tft.print(" F = ");
               tft.print(faze);
               break;
      */
  }
  // delay(1000);
  Serial.print("  Hz =  "); Serial.print(Hz);
  Serial.print("  amp   =  "); Serial.print(amp);
  Serial.print("  faze  =  "); Serial.print( faze );
  Serial.println();
}

Post an image/picture.

            int currentHz;
            int previousHz;
            currentHz = Hz;

You keep resetting the value of previousHz by declaring it rather than saving currentHz as previousHz so the comparison of current and previous is meaningless as there is no real previous value

i whould reccomend to use millis(); instead of delay();

Using millis() for timing would not improve the sketch in this case. What would improve it would be proper detection of a state change of the button pin. As it stands, if the button is pressed for more than 200 milliseconds then the outcome of the press is uncertain. This would still be the case if mills() was used for the timing

What would also help would be to give the pins meaningful names rather than using anonymous pin numbers

I would put any print statements into the same condition block. This way anything would be printed on the display only when the condition is met.

        tft.print("C0 Hz = ");

There is no need to reprint static text and the suggested code is wrong if there is actually text at 0, 0 rather than a previous value

that´s right but then you need to set the position of the cursor to another place on the screen.

Why is that a problem ?

Personally I would be inclined to put the whole thing in a suitably named function with parameters for x, y, previous value, new value, background colour and text colour and maybe even text size and font

Doing that would make the use of different position, text and background colour throughout the sketch much easier

I know from personal experience that changes in screen layout as a project develops are all too common

1 Like