greiman / SSD1306Ascii

Text only Arduino Library for SSD1306 OLED displays
MIT License
490 stars 120 forks source link

Issues Initializing Multiple OLEDs #112

Closed treyus30 closed 10 months ago

treyus30 commented 11 months ago

About 80% of the time, my displays initialize like the attached or some combination of correct and corrupt. They initialize left to right in the code, and display 1 always appears correct. 20% of the time they all initialize perfectly, but usually display 3 or 4 have the issue. Sometimes they just appear black.

Once initialized, all further updates occur successfully, just vertically offset like pictured, so I've ruled out my wiring. What might need to change either in my code or the library?

PXL_20230727_164227322 LONG_EXPOSURE-01 COVER

Here is the relevant code section. I use one instance of the library and vary the CS pin to update one display at a time.

//SPI display
    oled.begin(&Adafruit128x64, OLED_CS_0, DC_PIN, RST_PIN);  //start primary instance
    oled.setFont(Adafruit5x7);

    //setup all possible Chip Selects 
    for (int n=0; n < maxDisplays; n++){
      pinMode(OLED_CS[n], OUTPUT);
      digitalWrite(OLED_CS[n], HIGH);
    }

    for (int i = 0; i < 1; i++){              //refresh multiple does nothing...it's something when the inital calls to SPI are sent that causes corruption...
      for (int n=0; n < maxDisplays-1; n++){
        digitalWrite(OLED_CS[n], LOW);

        //oled.setLetterSpacing(2);
        oled.clear();
        oled.set1X();
        oled.print(F("Screen ")); oled.print(n+1); oled.print(F(" (A")); oled.print(n); oled.println(F(")"));
        oled.println(F("Initializing..."));
        oled.println();
        oled.setCursor(29,30);      
        oled.set2X(); oled.println(F("Please"));
        oled.setCursor(40,60);
        oled.set2X(); oled.println(F("Wait"));

        digitalWrite(OLED_CS[n], HIGH);
        delay(1);
      }
      delay(250);
    }
greiman commented 11 months ago

I think you need an instance for each display.

There is a bit of state in the instance and each instance thinks it controls CS and DC.

Edit: You probably need a separate pin for reset on each display. I think one DC pin might work.

You could connect all displays to a reset line and pull it low for 10 ms before calling begin(&Adafruit128x64, OLED_CS[n], DC_PIN)

for each instance.

treyus30 commented 11 months ago

I think you need an instance for each display.

There is a bit of state in the instance and each instance thinks it controls CS and DC.

Edit: You probably need a separate pin for reset on each display. I think one DC pin might work.

You could connect all displays to a reset line and pull it low for 10 ms before calling begin(&Adafruit128x64, OLED_CS[n], DC_PIN)

for each instance.

Thanks, I'll try that. :) Multiple instances is out of the question due to memory restrictions of the overall program. I'm barely running with the one.

treyus30 commented 11 months ago

So ultimately the suggestions didn't work, and I found that since I was using begin() with the reset pin defined, it was already delaying 10ms (x2). However, they gave me the motivation to start strategically experimenting with placing delays and focusing on the RESET function itself. The initialization seems to be a lot more stable now, and fails maybe 1 in 10 times instead of 8 in 10. I think the remaining issues could be stemming from the high impedance of my breadboard and/or less than ideal power supply rail.

Additional perspective came from the SSD1306 datasheet: image

image

More stable code:

//SETUP
void setup() {

  pinMode(RST_PIN, OUTPUT);     //attempt to stabilize the reset pin immediately
  digitalWrite(RST_PIN, HIGH);

  delay(500);   //give time to stabilize initial voltages

///bunch of unrelated stuff...

//SPI display
    //digitalWrite(RST_PIN, LOW); //added these two at the recommendation of the library creator, but they didn't seem to do anything. Using the reset pin in the declaration below does this anyway..
    delay(10);

    oled.begin(&Adafruit128x64, OLED_CS_0, DC_PIN, RST_PIN);  //start primary instance
    oled.setFont(Adafruit5x7);

    //setup all possible Chip Selects 
    for (int n=0; n < maxDisplays; n++){
      pinMode(OLED_CS[n], OUTPUT);
      digitalWrite(OLED_CS[n], HIGH); 
      delay(1);   //seemed to stabilize display startup  
    }

    for (int n=0; n < maxDisplays-1; n++){
      digitalWrite(OLED_CS[n], LOW);
      delay(5);   //seemed to stabilize display startup @ >=1ms

      oled.clear();  
      oled.setContrast(64);   //64 = 25uA, 160 = 69uA, 255 = 100uA

      oled.setCursor(0,0);
      oled.set1X();
      oled.print(F("Screen ")); oled.print(n+1); oled.print(F(" (A")); oled.print(n); oled.println(F(")"));
      oled.println(F("Initializing..."));

      oled.setCursor(29,3);      
      oled.set2X(); 
      oled.print(F("Please"));
      oled.setCursor(40,5);
      oled.print(F("Wait"));

      digitalWrite(OLED_CS[n], HIGH);
      delay(5);
    }
    delay(250);   //brief pause after startups

Notably, there is a approximately 0.1V drop on the RES pin (2) referenced to VCC from having 4 displays. Not sure if that is an additional problem, or telling of the real problem, but the drop goes up with more displays.

treyus30 commented 10 months ago

Closing because this seems to be a physical issue. Thanks for the help!