I wanted to avoid flickering but I got another problem with OLED display

My code is here:

#include <Adafruit_SSD1306.h>
#include <splash.h>

#include <Adafruit_GFX.h>
#include <Adafruit_GrayOLED.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#include <SPI.h>
#include <Wire.h>

#define SCREEN_WIDTH 128 // OLED display width,  in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define CLK 2
#define DT 3
#define SW 4

//Adafruit_SSD1306 display(-1);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

int counter = 0;
int currentStateCLK;
int lastStateCLK;
String currentDir = "";


int ButtonState;
int btn;
//int btn1;
unsigned long lastButtonPress = 0;


int current_val;
int prev_val;

int x1 = 17;
int y1 = 26;
int z1 = 34;
int t1 = 43;
int frame = 0;

void setup() {
  // initialize with the I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  // Clear the buffer.
  display.clearDisplay();

  // Set encoder pins as inputs
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DT, INPUT_PULLUP);
  pinMode(SW, INPUT_PULLUP);

  // Setup Serial Monitor
  Serial.begin(9600);

  // Read the initial state of CLK
  lastStateCLK = digitalRead(CLK);

  // Call updateEncoder() when any high/low changed seen
  // on interrupt 0 (pin 2), or interrupt 1 (pin 3)
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop() {

  button();

  Serial.println(btn);
  frame = counter;
  if (frame < 0) {
    frame = abs(frame % 4);
    if (frame == 1) frame = 4;
    else if (frame == 2) frame = 3;
    else if (frame == 3) frame = 2;
    else if (frame == 0) frame = 1;
  }
  else if (frame < 0 && frame % 4 == 0) frame = 1;
  else if (frame > 4 && frame % 4 != 0) frame = frame % 4;
  else if (frame > 4 && frame % 4 == 0) frame = 4;

  if (btn == 0) {
    switch (frame) {
      case 0:
        frame0();
        break;
      case 1:
        frame1();
        break;
      case 2:
        frame2();
        break;
      case 3:
        frame3();
        break;
      case 4:
        frame4();
        break;
    }
  }
  else if (btn == 1) {
    switch (frame) {
      case 0:
        frame0();
        btn = 0;
        break;
      case 1:
        subFrame1();
        break;
      case 2:
        subFrame2();
        break;
      case 3:
        subFrame3();
        break;
      case 4:
        subFrame4();
        break;
    }
  }

}

void frame0() {
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Generated matrix");
  display.setCursor(0, y1);  display.print (" Time delay");
  display.setCursor(0, z1);  display.print (" Project info");
  display.setCursor(0, t1);  display.print (" Help");
  display.display();
}
void frame1()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (">Generated matrix");
  display.setCursor(0, y1);  display.print (" Time delay");
  display.setCursor(0, z1);  display.print (" Project info");
  display.setCursor(0, t1);  display.print (" Help");
  display.display();
}
void frame2()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Generated matrix");
  display.setCursor(0, y1);  display.print (">Time delay");
  display.setCursor(0, z1);  display.print (" Project info");
  display.setCursor(0, t1);  display.print (" Help");
  display.display();
}
void frame3()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Generated matrix");
  display.setCursor(0, y1);  display.print (" Time delay");
  display.setCursor(0, z1);  display.print (">Project info");
  display.setCursor(0, t1);  display.print (" Help");
  display.display();
}
void frame4()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Generated matrix");
  display.setCursor(0, y1);  display.print (" Time delay");
  display.setCursor(0, z1);  display.print (" Project info");
  display.setCursor(0, t1);  display.print (">Help");
  display.display();
}


void subFrame1()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Generated matrix");
  display.setCursor(0, y1);  display.print (" Matrix");
  display.display();
  //duzelt


}
void subFrame2()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Choose time delay");
  display.setCursor(0, y1);  display.print (" Time delay");
  display.display();
  //duzelt

}
void subFrame3()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" This device generates bla bla bla");
  display.display();
}
void subFrame4()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (" Help");
  display.setCursor(0, y1);  display.print (" For more information please visit");
  display.display();
}
void header() {
  display.setTextSize(1);          // text size
  display.setTextColor(WHITE);     // text color
  display.setCursor(0, 0);        // position to display
  display.println("Any header"); // text to display
  display.display();               // show on OLED
}
void button() {
  ButtonState = digitalRead(SW);
  if (ButtonState == 0) { //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 80) {
      Serial.println("Button pressed!");
      btn = (btn + 1) % 2;
			display.clearDisplay();
    }
    lastButtonPress = millis();
  }
  delay(100);
}
void updateEncoder() {
	
  // Read the current state of CLK
  currentStateCLK = digitalRead(CLK);

  // If last and current state of CLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK !=lastStateCLK  && currentStateCLK == 1) {
		display.clearDisplay();
    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(DT) != currentStateCLK) {
      counter --;
      currentDir = "CCW";
    } else {
      // Encoder is rotating CW so increment
      counter ++;
      currentDir = "CW";
    }

    Serial.print("Direction: ");
    Serial.print(currentDir);
    Serial.print(" | Counter: ");
    Serial.println(counter);
  }

  // Remember last CLK state
  lastStateCLK = currentStateCLK;
}

I want menu item selection like this:
oled
But sometimes I get this:
oled1
It selects both items. How can I solve it?
Thanks in advance.

check if displaying a space erases what's there on the screen

A comment describing what this does would have been useful!

It detects if the rotary encoder is pressed and counts how many times it has been pressed. Whenever it's pressed you enter into subMenus

void button() {
  ButtonState = digitalRead(SW);
  if (ButtonState == 0) { //if 80ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 80) {
      Serial.println("Button pressed!");
    //counts the number of button press
      btn = (btn + 1) % 2;
			display.clearDisplay();
    }
    lastButtonPress = millis();
  }
  delay(100);
}

No, it didn't react at all :frowning:

Try

display.setTextColor(WHITE, BLACK);

The same problem:
image

can you replace the white space in your frameX() functions with a star

void frame0() {
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print ("*Generated matrix");
  display.setCursor(0, y1);  display.print ("*Time delay");
  display.setCursor(0, z1);  display.print ("*Project info");
  display.setCursor(0, t1);  display.print ("*Help");
  display.display();
}

void frame1()
{
  //display.clearDisplay();
  header();
  display.setCursor(0, x1);  display.print (">Generated matrix");
  display.setCursor(0, y1);  display.print ("*Time delay");
  display.setCursor(0, z1);  display.print ("*Project info");
  display.setCursor(0, t1);  display.print ("*Help");
  display.display();
}

// etc

and see what you get

Are you running this in a simulator? Does it work if you use a read Arduino and oled display?

It's still the same:

image

Generated matrix and Help are selected

Yes, it's a simulation. And yes, I have tried the code with real Arduino and OLED display, it is the same and looks even more awful :slight_smile:
It seems like display.clearDisplay() doesn't want to work every time.

image

you can clearly see here that the > is painted over the previous *

it means you don't clear the screen enough when you need to repaint it.

➜ paint a black rectangle over the space occupied by the first column

you could avoid also the flickering by not repainting the full text and just moving the '>' around

I added this function to the end of each frame:

void refresh()
{
  display.display();
  delay(00);
  display.clearDisplay();
}

Now it works perfectly. I don't get why OLED should firstly display and then clear what it displayed.

The clear is applied next time you call display. So whatever you paint in between will start from a clean slate and will be displayed with the next call to display

1 Like

This function does not in fact clear the display! It's name is a little confusing and misleading.

The Arduino keeps a copy of the contents of the display in its memory (ram). clearDisplay() clears only that copy in memory, the display itself is not cleared at that point. The next time display() is used, the real display is updated from that copy in memory.

1 Like

I am confused about which change fixed the problem. I thought my display.setTextColor(WHITE, BLACK) suggestion would fix the problem, but it didn't. When you added that in multiple places and you say the problem was then fixed. But I did not expect adding that function multiple times would make any difference. Maybe you added more display.clearDisplay() and this is what fixed the problem?

it seems OP added a call to his refresh() function for each frameX() function. so that should take care of clearing up the intermediary frame buffer. The blinking went away likely because the frameX() are called only when needed and so the screen does not keep being erased and repainted

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.