I2C SSD1306 Display Stops Working After Time

I have a display that just stops working after some amount of time. The analog write still functions but the display stops and I've been fighting it for a while. It was working fine until I tried speeding it up.

Any ideas or help? Kind of a noobbbb here but trying to make some sensors for weather monitoring at my house.

Appreciate the help!

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI


Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);   //128, 32 is 0.81 wifi kit 8
unsigned long delayTime;

void setup() {
  Serial.begin(9600);
  Serial.println(F("BME280 test"));
  Wire.begin();
   
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
   // init done
  display.display();
//  delay(100);    //why need?
  display.clearDisplay();
  display.display();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  
  bool status;
  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  Serial.println("-- Default Test --");
  delayTime = 1000;

  Serial.println();
}


void loop() { 
  
  display.setCursor(0,0);
  display.clearDisplay();
  
  Serial.print("Temperature = "); Serial.print(1.8 * bme.readTemperature() + 32); Serial.println(" *F");
  display.print("T "); display.print(1.8 * bme.readTemperature() + 32,1); display.println(" *F");

  Serial.print("Pressure = "); Serial.print(bme.readPressure() / 1000.0F); Serial.println(" kPa");
  display.print("P "); display.print(bme.readPressure() / 1000.0F,1); display.println(" kPa");

  Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %RH");
  display.print("H "); display.print(bme.readHumidity(),1); display.println(" %RH");

  Serial.println();
  display.display();
  delay(10);  

  analogWriteRange(1023);
  analogWriteFreq(250);

  uint16_t hum  =  ((bme.readHumidity()/100)*1023);
  uint16_t pres = ((((bme.readPressure() / 1000.0F)-50)/60)*1023);
  uint16_t temp = ((((1.8 * bme.readTemperature() + 32)+20)/140)*1023);  
  

 
  analogWrite(D3, hum);
}

Try a different program, like a demo from the SSD1306 library.

Your post does not supply enough information for forum members to understand the problem. Please describe what "display stops working" means.

The display shuts off and goes blank but I still can get data out of the analog write and through serial monitor.

It's not the display I have a couple of these same boxes running fine. I've had the dispalys drop out occasionally and thought nothing of it until now where they are dropping out more often.

I wonder what that sentence means.

Did you try some other program?

It's not the physical display that is the problem. I have multiple of these setups... ie same board, display and sensor running fine. I have 3 of them around my house to be exact.

What other program would you have me run? I'm looking to try and debug this one.

It's almost like the display.clearDisplay(); in the loop clears it but then the display print is not working. If I turn the analogwriteFreq down it typically helps it, but I'm not sure why that would help with an I2C communication.

Once the power is cycled the display functions as intended again.

If two of them work and the third does not, then that one might have a hardware problem, for example, the display.

What other program would you have me run?

Any other program that writes stuff to the display. If the display "stops working" after a similar while, the display is the problem.

They all do the same thing. I tried speeding one up to have a more stable 0-3.3v output via analogWrite and I tried doing this by increasing the analogWriteFrequency. When I move the frequency up the problem gets more apparent.

An example at 100hz it can be fine for hours maybe days. At 200 Hz about 10-30 minutes and the same issue where the display will go blank but serial monitor shows activity and the analogWrite is still outputing.

That is VERY useful information and should have been included in your first post. It points to a power problem, like overloading the on board voltage regulator.

Please post a complete wiring diagram, with labels on pins and components (a picture of a hand drawn diagram is preferred). State which Arduino board you are using, how you are powering it, and post links to the product pages for the components.

have a more stable 0-3.3v output via analogWrite

Explain what this output is doing. There are strict limits to the amount of current you can draw from any pin.

@jremington

I am using a Heltec Wifi Kit 8 board.
Link: WiFi Kit 8 – Heltec Automation

Sensor: bosch BME280 I2C with 4 pins
Link: Bosch BME280 - Sensatio - Smart 'Do it Yourself' for everyone

Power supply's I've tried. A Kungber DC Power Supply set at 5v on the power input pin. USB outlet on a laptop and a USB power supply.

Sketch of Diagram

Note that I do show 4 analog write outputs. I have tried it with them connected, disconnected, switched them between the pins shown, tried just 1 and tried 4.

The output goes through an sn74ahct125n that steps up the voltage to an RC circuit and then into a simple analog data logger for long term measurement recordings. Think of it as homeassistant but no connectivity just continuous logging.

Eventually I would like to have 4 outputs functioning for humidity, temperature, pressure and altitude. The goal is to be able to implement the ADC outputs into my PID controller for my greenhouse fan's as I'm struggling with the current onboard PID logic as it's not flexible enough to switch through outputs and it cost me a full harvest of Bell Peppers last year.

IMPORTANT NOTE: Even without anything hooked up to D3 via the code above it will still do the same thing. Meaning powered up on my desk with nothing connected it still will shut the screen off after set amount of time. I could start timing it, not sure if it's cycle count related or what.

EDIT: I disabled the analogWrite function and increased the frequency on analogwritefreq (not sure if it is even doing anything if analogWrite is commented out) and the display has been running for 30 minutes...... at a speed where it would have only stayed up for ~10 min before. Is there anyway to reset the voltage regulator periodically? Seems strange that it would have issues with analogwrite connected to nothing.

If I understand you correctly, with NOTHING attached to any of the analogWrite pins, the display still goes blank.

That brings me back to the very first suggestion: remove the sensor, disconnect everything from the analogWrite pins, and load a different program that just writes something to the display in a continuous loop. Does the display stop working after some time?

If not, the following sounds quite dubious, but again the important details are missing. Without more information I'm out of ideas.

The output goes through an sn74ahct125n that steps up the voltage to an RC circuit and then into a simple analog data logger for long term measurement recordings

@jremington

It just shut off but took just over an hour with the analogwrite pin disabled and only the following diagram.

I'm just uploaded ssd1306_128x62_I2C example on it. It's been running for a few minutes.... I guess now we wait.

Edit..... welll welll wellll...........
It shut off after around 15 min on this code:

/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

#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

// 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
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };

void setup() {
  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
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines

  testdrawrect();      // Draw rectangles (outlines)

  testfillrect();      // Draw rectangles (filled)

  testdrawcircle();    // Draw circles (outlines)

  testfillcircle();    // Draw circles (filled)

  testdrawroundrect(); // Draw rounded rectangles (outlines)

  testfillroundrect(); // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();      // Draw characters of the default font

  testdrawstyles();    // Draw 'stylized' characters

  testscrolltext();    // Draw scrolling text

  testdrawbitmap();    // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}

anyway around this like a reset of the screen?

Sounds like there is either a hardware issue with the Heltec board (about which I know nothing) or possibly, a timed shutoff in the library code.

However, I've used Adafruit example code you just posted with several TFT and OLED displays, and have not seen the shutoff you describe.

I really like the Adafruit Feather boards, and you can count on product support from Adafruit.

I'm thinking I may try to change the I2C pins since the ESP8266 is all software and I have the SSD13306 and the bme 280 on the same buss... have to figure that out. Also need to update the reset pin looks like it's GPIO16.

I watched it shutoff this time and it flashes an orange LED at the same time.

Update: Defined the reset pin looking through some documentation it looks like the reset pin held high fixed this issue others were having.

It's been running for 2 hours now with the updates. GPIO16 is reset pin for screen on Wifi Kit 8.

I have some of those WiFi kit 8s, the displays are 32 pixels high, in your code you set the display height to 64 pixels, why? I don't know if that will cause your problem but I always believe in fixing the obvious problems first.

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