OLED SSD1306 flickering

Hello all,
I am using Adafruit's SSD1306 and GFX library for displaying values in real-time from the A0 (Analog) pin with the SSD1306 display over I2C and Arduino Nano. However, the screen is flickering a lot. On searching more about it I came to know that I must not update the screen all the time and just update the part of the screen that changes. Hence, I used display.setTextColor(WHITE, BLACK); before printing values on the screen, however the flickering does not seem to go. Can someone please tell me what mistake I am making. Thank you very much!!

My code is as follows:

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


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define slow_multiplier 10 //change this to change the slowest speed 
#define time_multiplier    10


#define rate_multiplying_factor  3.35
#define rate_offset  9





// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
#define mode_switch  A3
#define parameter_change_switch  A1
#define start_stop_switch  A2


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);





int mode_switch_value,paramter_switch_value,start_stop_switch_value;
int mode = 1,started = 0;
long motor_set_value;
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
int parameter_cursor = 1;
float timeout=60,analogvalue,volume;
float start_time = 0,RPM =0, rate =0 ; 

void setup() {
  ADCSRA &= ~PS_128;
  ADCSRA |= (1 << ADPS2);
  TCCR1A = 0;
  TCCR1A = (1 << COM1A0);
  TCCR1B = 0;
  TCCR1B = (1 << WGM12) | (1 << CS10);
  pinMode(A0, INPUT);
  pinMode(9, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(mode_switch,INPUT_PULLUP);
  pinMode(parameter_change_switch,INPUT_PULLUP);
  pinMode(start_stop_switch,INPUT_PULLUP);
  digitalWrite(4, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);

  Serial.begin(9600);

  // 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
  }
// Clear the buffer
   delay(2000);
  display.clearDisplay();
  display.display();



}

void loop() {
  delay(100);
  analogvalue = analogRead(A0);
  
  //Serial.println(analogvalue);
  mode_switch_value =  digitalRead(mode_switch);
  paramter_switch_value =  digitalRead(parameter_change_switch);
  start_stop_switch_value =  digitalRead(start_stop_switch);

  display.clearDisplay();
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,50);             // Start at top-left corner
  display.println(mode_switch_value);
  display.setCursor(25,50);             // Start at top-left corner
  display.println(paramter_switch_value);
  display.setCursor(50,50);             // Start at top-left corner
  display.println(start_stop_switch_value);
  display.display();




if(paramter_switch_value == 0)
{
   delay(500);
  if(parameter_cursor == 1)
  {    
    parameter_cursor = 2;
   }
   else if (parameter_cursor == 2)
   {
      parameter_cursor = 1;
    }
}

 if(parameter_cursor == 1)
  {
     display.drawLine(0, 45,20,45,SSD1306_WHITE);
   }
   else if (parameter_cursor == 2)
   {
     display.drawLine(35, 45,55,45,SSD1306_WHITE);
   }







/*

  if(mode_switch_value == 0)
  {
        mode++;
        if(mode >4)
        {
          mode =1;
        }
        delay(500);
    }
*/
 if(start_stop_switch_value == 0)
  {
    if(mode == 1)
    {
      if(started ==0)
      {
        start_time = millis()/1000;
        //motor_set_value = map(analogvalue, 0,1023, 2000*slow_multiplier, 200);
        OCR1A = motor_set_value;
        started = 1;
      }
      else
      {
        OCR1A = 0;
        started = 0;
        }
    }
        delay(500);
   }


if((millis()/1000) - start_time > timeout )
{
        OCR1A = 0;
        started = 0;
  }



   
  if(mode == 1)
  {
     display.setCursor(0,0); 
     display.setTextColor(WHITE,BLACK);           
     display.println("Mode 1");
     
     display.setCursor(0,20);
     display.setTextColor(WHITE,BLACK);
     display.println("RPM");
     display.setCursor(0,32);
     if (parameter_cursor ==1)
     {
       motor_set_value = map(analogvalue, 0,1023, 2000*slow_multiplier, 200);
      }
     else
     {
      
      timeout = float(map(analogvalue, 0,1023, 0, 10*time_multiplier));
      }
     RPM = float((float)150000/(float)motor_set_value);
     rate = RPM * rate_multiplying_factor + rate_offset;// ul/sec
     volume = (timeout * rate)/1000;  //ml
     display.println((int)RPM);

     display.setCursor(37,20);
     display.setTextColor(WHITE,BLACK);
     display.println("T");
     display.setCursor(40,32);
     display.setTextColor(WHITE,BLACK);
     display.println((int)timeout);
     display.setCursor(65,20);
     display.setTextColor(WHITE,BLACK);
     display.println("R"); //rate
     display.setCursor(65,32);
     display.setTextColor(WHITE,BLACK);
     display.println((int)rate);
     
     display.setCursor(90,20);
     display.setTextColor(WHITE,BLACK);
     display.println("V");
     display.setCursor(90,32);
     display.setTextColor(WHITE,BLACK);
     display.println((int)volume);
     
     display.setCursor(50,0);
     display.setTextColor(WHITE,BLACK);
     display.println("Started=");
     display.setCursor(100,0);
     display.setTextColor(WHITE,BLACK);
     display.println(started);
     display.display();
    }
    else if(mode == 2)
  {
     display.setCursor(0,0);   
     display.setTextColor(WHITE,BLACK);         
     display.println("Mode 2");
     
     display.setCursor(10,20);
     display.setTextColor(WHITE,BLACK);
     display.println("Speed");
     display.setCursor(10,32);
     display.setTextColor(WHITE,BLACK);            
     display.println(analogvalue);

     display.setCursor(64,20);
     display.setTextColor(WHITE,BLACK);
     display.println("Time");
     display.setCursor(64,32); 
     display.setTextColor(WHITE,BLACK);           
     display.println(analogvalue);

     
     display.display();
    }
    else if(mode == 3)
  {
     display.setCursor(0,0); 
     display.setTextColor(WHITE,BLACK);           
     display.println("Mode 3");
     
     display.setCursor(10,20);
     display.setTextColor(WHITE,BLACK);
     display.println("Speed");
     display.setCursor(10,32); 
     display.setTextColor(WHITE,BLACK);           
     display.println(analogvalue);

     display.setCursor(64,20);
     display.setTextColor(WHITE,BLACK);
     display.println("Time");
     display.setCursor(64,32);  
     display.setTextColor(WHITE,BLACK);          
     display.println(analogvalue);
     
     display.display();
    }
    else if(mode == 4)
  {
     display.setCursor(0,0);  
     display.setTextColor(WHITE,BLACK);          
     display.println("Mode 4");
     
     display.setCursor(10,20);
     display.setTextColor(WHITE,BLACK);
     display.println("Speed");
     display.setCursor(10,32);  
     display.setTextColor(WHITE,BLACK);          
     display.println(analogvalue);

     display.setCursor(64,20);
     display.setTextColor(WHITE,BLACK);
     display.println("rate");
     display.setCursor(64,32);   
     display.setTextColor(WHITE,BLACK);         
     display.println(analogvalue);
     
     display.display();
    }

}

Not familiar with your display. Maybe it helps if you don't update that often; you have a delay(100) in the beginning of loop(). Change that to e.g. 2 seconds for testing and check if it improves the situation; if yes you can work on solutions by e.g. only updating the display when data changes.

PS
Are you using a Nano or a Nano Every?

What you say about not updating the whole screen is correct but that does not seem to be what you have done. You repeatedly use

    display.setTextColor(WHITE, BLACK);

but it is not obvious what you think that will achieve

In order to reduce screen flickering to a minimum the logic should be

start of loop()
if nothing displayed has changed 
  do nothing
else
if something has changed
  print the previous value in the background colour 
  or draw a box in the background colour over the previous value
  print the new values in the text colour
end if
update the display only if something changed
end of loop()

Thanks sterretje,
I am using the Nano. Yes, increasing the delay works, but the rate at which the data updates is critical to my application. Is there any other alternative you could suggest, Thanks!!

Thanks UKHeliBob,

I tried making my logic as you suggested, but it is not working out yet.
Can you please help me out with respect to my code. I am trying to check if the variable storing data from A0 is changing or not and on basis of that applying the logic that you have suggested. But getting the same result.
Thanks!!

I said "for testing". That would determine if your code is the issue or the display.

So why did you post in the Nano Evevry section. Topic moved :wink:

Yes sterretje,
I feel I will have to make changes to the intricacies of the code. Using another display also yielded the same result i.e. flickering.

It is a s simple as this

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

void loop()
{
  delay(100);
  static int previousValue = analogRead(A0);
  int currentValue = analogRead(A0);
  if (abs(currentValue - previousValue) > 10)  //value has changed by at least 10
  {
    Serial.println(currentValue);
    previousValue = currentValue; //save for next time
  }
}

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