Blank Screen on SSD1309 OLED using Arduino UNO - First Timer

Hello,

(Intro) I am a mechanical engineer with an automotive background and I'm comfortable working with basic AC or DC circuits and some programming, but I'm a newbie when it comes to circuit design and microcontrollers, and I would like to grow my knowledge in this area for some projects I've been thinking about. A couple months ago I purchased an Arduino UNO R3 with the Seeeduino sensor kit, so I could start playing around with various components I'm interested in. I was able to go through all the tutorials and eventually wrote my own sketch to display temperature and humidity from the DHT11 on the included OLED, and also made a bar graph type display of the output from the included potentiometer, using U8X8 from the U8g2 library.

Once I was comfortable with that I decided to take the next step so I searched for some OLEDs and ended up buying 2x of these SSD1309-driven 128x64 monochrome displays: 128x64 White Graphic OLED from Crystalfontz

I chose these displays for their size and brightness, and because they were offered with a breakout board: SSD1309 OLED Breakout Board from Crystalfontz

Upon arrival I realized that I had overlooked that the displays required a logic voltage of 3.3V so I ordered a bidirectional level shifter from Adafruit so it would play nice with the 5V logic from the UNO R3: 8-channel Bi-directional Logic Level Converter [TXB0108] : ID 395 : $7.95 : Adafruit Industries, Unique & fun DIY electronics and kits

I originally tried using the 4-wire SPI wiring scheme and sample code offered by the screen vendor (https://www.crystalfontz.com/products/document/4270/CFA10105GettingStarted.pdf), powering the "A" side of the level shifter from the Arduino 3.3V output, and the "B" side from the 5V output, all referenced to the Arduino GND pin. I ran the CS, D/C, RST, SCK, and MOSI through the level shifter. This resulted in a blank screen, so I verified my connections and tried swapping to the second screen and breakout board and had the same result.

After that I dug into the code to try and understand if there was a pin-assignment discrepancy between my Uno R3 and the Seeeduino clone they were using in the example. I decided to step back and make it as simple as possible by using the hardwire SPI pins and the HelloWorld demo sketch that's included with the u8g2 library. Now I have the following connections (image of breadboard setup attached):

Pin Name - Arduino Pin - Level Shifter Pin - OLED Pin - Wire Color
SCK - 13 - B1/A1 - D0 - Green
MOSI - 11 - B2/A2 - D1 - Blue
CS - 10 - B3/A3 - CS - Purple
D/C - 9 - B4/A4 - D/C - Brown
RST - 8 - B5/A5 - RST - Grey

I still have the 3.3V and 5V feeds from the Arduino to the level shifter VCCA and VCCB respectively, and I'm also powering the OLED controller from the 3.3V feed. The ground is still shared by all three devices. I've used my meter to verify voltages at the feeds and I checked the logic high voltage on the CS pin at the breakout board and it was >2.4V.

I've tried using the constructors for both hardware and software SPI, for both the U8g2 and U8X8 "HelloWorld" demo sketches. I've tried each constructor starting with "SSD1309_128X64_NONAME" - all compile and upload fine but result in a blank OLED screen, and I've tried it on both units that I purchased to minimize the chance of a bad display. I'm hitting a character limit when I try to include the code so I will add that on the next post.

I feel like I must be missing something very basic and would very much appreciate any help. Thanks!

Here is one example of code that I have used. I had to trim out all the commented constructor options to work within the character limit.

/*

  HelloWorld.ino
  
  "Hello World" version for U8x8 API

  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

  Copyright (c) 2016, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

*/

#include <Arduino.h>
#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif

// Please UNCOMMENT one of the contructor lines below
// U8x8 Contructor List 
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
U8X8_SSD1309_128X64_NONAME0_4W_SW_SPI u8x8(/* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);


void setup(void)
{
  u8x8.begin();
  u8x8.setPowerSave(0);  
}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.drawString(0,1,"Hello World!");
  u8x8.refreshDisplay();		// only required for SSD1606/7  
  delay(2000);
}

Personally, I find life easier with ready-built modules e.g. https://www.aliexpress.com/item/1921225194.html

Saves all the messing about with Adapters etc.
I also use 3.3V boards. So there is no need to worry about level shifters either.

Your first link shows display + adapter + Seeeduino board. i.e. everything should work out of the box.

However you should be able to run your display + adapter + level shifter + Uno

Just wire everything meticulously.
Most OLED applications are fast enough with I2C. Animations are faster with SPI.
Your Adapter board has solder-bridges to select SPI or I2C.

David.

Bummer. I've redone the connections several times and still no luck.

I would have purchased the screen vendor's Seeeduino clone had I not already purchased the Uno.

I purchased the screen because the form factor works in the spot I'm trying to place it. I can solder a jumper to make it work with I2C, but it ships configured for 4W SPI so that's what I decided to try first. Maybe I'll try I2C next.

Okay I bit the bullet and switched over to I2C. This involved putting solder jumpers on the pads "BS1=1" (to enable I2C) and "SDA=SDA" (ties the D1 and D2 pins together for I2C). Then I also put a solder jumper on the "SA0=1" pad on one of the displays, to change the I2C address for that screen.

I also switched the level shifter to this one, which has the appropriate pullup resistors to work nicely with I2C: 4-channel I2C-safe Bi-directional Logic Level Converter [BSS138] : ID 757 : $3.95 : Adafruit Industries, Unique & fun DIY electronics and kits

After changing the constructor I performed an initial test of the HelloWorld sketch in the u8g2 library and it worked. I then added the second screen by tapping into the VCC/GND/SDA/SCL that I ran to the first screen, and after some research and trial and error I arrived at this solution which results in the screens displaying independently as shown in the attached picture.

Now that things are operational I will start playing with the code and adding sensors/signals to manipulate and display. I also have to learn about page buffering do/while loops, and especially since the UNO doesn't have enough RAM to do full frame buffering for both screens simultaneously (which also would have been new to me anyways).

#include <Wire.h>
#include <U8g2lib.h>
//#include <U8x8lib.h>

U8G2_SSD1309_128X64_NONAME0_1_HW_I2C oled1(U8G2_R0, U8X8_PIN_NONE);
U8G2_SSD1309_128X64_NONAME0_1_HW_I2C oled2(U8G2_R0, U8X8_PIN_NONE);

void setup() {
  oled1.setI2CAddress(0x3C * 2);
  oled2.setI2CAddress(0x3D * 2);
  oled1.begin();
  oled2.begin();
  oled1.setFont(u8g2_font_7x14_mf);
  oled2.setFont(u8g2_font_7x14_mf);
}

void loop() {
  oled1.firstPage();
  do {
    oled1.drawStr(36,32,"SCREEN 1");
  } while ( oled1.nextPage() );
  
  oled2.firstPage();
  do {
    oled2.drawStr(36,32,"SCREEN 2");
  } while ( oled2.nextPage() );
  
}

This topic was automatically closed after 120 days. New replies are no longer allowed.