OLED problems

Status
Not open for further replies.

M4ngu

Well-known member
Hi there, I'm having some issues with a cheap OLED display, SH1106 128 x 64 pixels,
I thought that it was a faulty part but I tested with another one and got the same result.
I've try with several OLED libraries, some of them work on the upper row of the display and the rest shows snow,
the only one that can draw the whole display is <U8g2lib.h> but it takes a very long time (about 37 ms) to send the buffer.
Please any advice about this would be much appreciated.

my pins on the Teensy are:

#define OLED_CLK 0
#define OLED_MOSI 9
#define OLED_RESET 27
#define OLED_DC 26
#define OLED_CS 1

those pins are not shared with other SPI devices
the pcb circuit is:
Captura de pantalla 2021-09-13 a las 14.27.07.png
 
Not all SH1106 libraries are created equally...did you perhaps try this one?
It seems to be working fine for forum member 'frohr' using an SH1106 display. See this thread.

Paul
 
Not all SH1106 libraries are created equally...did you perhaps try this one?
It seems to be working fine for forum member 'frohr' using an SH1106 display. See this thread.

Paul

Thx Paul,
I get some errors compiling for Teensy 4.0,
Code:
/Users/jesus/Documents/Arduino/libraries/Adafruit_SH1106-master/Adafruit_SH1106.cpp: In member function 'void Adafruit_SH1106::begin(uint8_t, uint8_t, bool)':
/Users/jesus/Documents/Arduino/libraries/Adafruit_SH1106-master/Adafruit_SH1106.cpp:179:17: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'PortReg* {aka volatile unsigned char*}' in assignment
     csport      = portOutputRegister(digitalPinToPort(cs));
                 ^
/Users/jesus/Documents/Arduino/libraries/Adafruit_SH1106-master/Adafruit_SH1106.cpp:181:17: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'PortReg* {aka volatile unsigned char*}' in assignment
     dcport      = portOutputRegister(digitalPinToPort(dc));
                 ^
/Users/jesus/Documents/Arduino/libraries/Adafruit_SH1106-master/Adafruit_SH1106.cpp:187:19: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'PortReg* {aka volatile unsigned char*}' in assignment
       clkport     = portOutputRegister(digitalPinToPort(sclk));
                   ^
/Users/jesus/Documents/Arduino/libraries/Adafruit_SH1106-master/Adafruit_SH1106.cpp:189:19: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'PortReg* {aka volatile unsigned char*}' in assignment
       mosiport    = portOutputRegister(digitalPinToPort(sid));
                   ^
Error compiling for board Teensy 4.0.
 
Hmm, got the same compilation error when trying to compile the example sh1106_128x64_spi.ino that came with library.

Since the maker of the library stated on his Github page that his library was a modification of Adafruit's SSD1306 library, I compared the Adafruit_SSD1306.h and Adafruit_SH1106.h files.
I noticed this difference within the .h files: (it's related to the errors)
Adafruit_SH1106.h:
Code:
#ifdef __SAM3X8E__
 typedef volatile RwReg PortReg;
 typedef uint32_t PortMask;
#else
  typedef volatile uint8_t PortReg;
  typedef uint8_t PortMask;
#endif
Adafruit_SSD1306.h:
Code:
#if defined(__AVR__)
typedef volatile uint8_t PortReg;
typedef uint8_t PortMask;
#define HAVE_PORTREG
#elif defined(__SAM3X8E__)
typedef volatile RwReg PortReg;
typedef uint32_t PortMask;
#define HAVE_PORTREG
#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) &&                      \
    !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_RP2040)
typedef volatile uint32_t PortReg;
typedef uint32_t PortMask;
#define HAVE_PORTREG
#endif

So I modified Adafruit_SH1106.h to look like this:
Code:
/*********************************************************************
This is a library for our Monochrome OLEDs based on SSD1306 drivers

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

These displays use SPI to communicate, 4 or 5 pins are required to  
interface

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.  
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

/*********************************************************************
I change the adafruit SSD1306 to SH1106

SH1106 driver similar to SSD1306 so, just change the display() method.

However, SH1106 driver don't provide several functions such as scroll commands.


*********************************************************************/

#if ARDUINO >= 100
 #include "Arduino.h"
 #define WIRE_WRITE Wire.write
#else
 #include "WProgram.h"
  #define WIRE_WRITE Wire.send
#endif

[COLOR="#FF0000"]// #ifdef __SAM3X8E__
//  typedef volatile RwReg PortReg;
//  typedef uint32_t PortMask;
// #else
//   typedef volatile uint8_t PortReg;
//   typedef uint8_t PortMask;
// #endif[/COLOR]

[COLOR="#00A000"]#if defined(__AVR__)
typedef volatile uint8_t PortReg;
typedef uint8_t PortMask;
#define HAVE_PORTREG
#elif defined(__SAM3X8E__)
typedef volatile RwReg PortReg;
typedef uint32_t PortMask;
#define HAVE_PORTREG
#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) &&                      \
    !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_RP2040)
typedef volatile uint32_t PortReg;
typedef uint32_t PortMask;
#define HAVE_PORTREG
#endif[/COLOR]

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

#define BLACK 0
#define WHITE 1
#define INVERSE 2

#define SH1106_I2C_ADDRESS   0x3C // 011110+SA0+RW - 0x3C or 0x3D
// Address for 128x32 is 0x3C
// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)

/*=========================================================================
    SH1106 Displays
    -----------------------------------------------------------------------
    The driver is used in multiple displays (128x64, 128x32, etc.).
    Select the appropriate display below to create an appropriately
    sized framebuffer, etc.

    SH1106_128_64  128x64 pixel display

    SH1106_128_32  128x32 pixel display

    SH1106_96_16

    -----------------------------------------------------------------------*/
   #define SH1106_128_64
//   #define SH1106_128_32
//   #define SH1106_96_16
/*=========================================================================*/

#if defined SH1106_128_64 && defined SH1106_128_32
  #error "Only one SH1106 display can be specified at once in SH1106.h"
#endif
#if !defined SH1106_128_64 && !defined SH1106_128_32 && !defined SH1106_96_16
  #error "At least one SH1106 display must be specified in SH1106.h"
#endif

#if defined SH1106_128_64
  #define SH1106_LCDWIDTH                  128
  #define SH1106_LCDHEIGHT                 64
#endif
#if defined SH1106_128_32
  #define SH1106_LCDWIDTH                  128
  #define SH1106_LCDHEIGHT                 32
#endif
#if defined SH1106_96_16
  #define SH1106_LCDWIDTH                  96
  #define SH1106_LCDHEIGHT                 16
#endif

#define SH1106_SETCONTRAST 0x81
#define SH1106_DISPLAYALLON_RESUME 0xA4
#define SH1106_DISPLAYALLON 0xA5
#define SH1106_NORMALDISPLAY 0xA6
#define SH1106_INVERTDISPLAY 0xA7
#define SH1106_DISPLAYOFF 0xAE
#define SH1106_DISPLAYON 0xAF

#define SH1106_SETDISPLAYOFFSET 0xD3
#define SH1106_SETCOMPINS 0xDA

#define SH1106_SETVCOMDETECT 0xDB

#define SH1106_SETDISPLAYCLOCKDIV 0xD5
#define SH1106_SETPRECHARGE 0xD9

#define SH1106_SETMULTIPLEX 0xA8

#define SH1106_SETLOWCOLUMN 0x00
#define SH1106_SETHIGHCOLUMN 0x10

#define SH1106_SETSTARTLINE 0x40

#define SH1106_MEMORYMODE 0x20
#define SH1106_COLUMNADDR 0x21
#define SH1106_PAGEADDR   0x22

#define SH1106_COMSCANINC 0xC0
#define SH1106_COMSCANDEC 0xC8

#define SH1106_SEGREMAP 0xA0

#define SH1106_CHARGEPUMP 0x8D

#define SH1106_EXTERNALVCC 0x1
#define SH1106_SWITCHCAPVCC 0x2

// Scrolling #defines
#define SH1106_ACTIVATE_SCROLL 0x2F
#define SH1106_DEACTIVATE_SCROLL 0x2E
#define SH1106_SET_VERTICAL_SCROLL_AREA 0xA3
#define SH1106_RIGHT_HORIZONTAL_SCROLL 0x26
#define SH1106_LEFT_HORIZONTAL_SCROLL 0x27
#define SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
#define SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A

class Adafruit_SH1106 : public Adafruit_GFX {
 public:
  Adafruit_SH1106(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS);
  Adafruit_SH1106(int8_t DC, int8_t RST, int8_t CS);
  Adafruit_SH1106(int8_t RST);

  void begin(uint8_t switchvcc = SH1106_SWITCHCAPVCC, uint8_t i2caddr = SH1106_I2C_ADDRESS, bool reset=true);
  void SH1106_command(uint8_t c);
  void SH1106_data(uint8_t c);

  void clearDisplay(void);
  void invertDisplay(uint8_t i);
  void display();

  /*void startscrollright(uint8_t start, uint8_t stop);
  void startscrollleft(uint8_t start, uint8_t stop);

  void startscrolldiagright(uint8_t start, uint8_t stop);
  void startscrolldiagleft(uint8_t start, uint8_t stop);
  void stopscroll(void); */
  
  void dim(uint8_t contrast);

  void drawPixel(int16_t x, int16_t y, uint16_t color);

  virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
  virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);

 private:
  int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs;
  void fastSPIwrite(uint8_t c);

  boolean hwSPI;
  PortReg *mosiport, *clkport, *csport, *dcport;
  PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask;

  inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
  inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));

};

And now the example compiles without error! Can't verify though whether it's actually working since I don't have an SH1106 display here.
Hope you can test this.

Paul
 
Hmm, got the same compilation error when trying to compile the example sh1106_128x64_spi.ino that came with library.

Since the maker of the library stated on his Github page that his library was a modification of Adafruit's SSD1306 library, I compared the Adafruit_SSD1306.h and Adafruit_SH1106.h files.
I noticed this difference within the .h files: (it's related to the errors)

So I modified Adafruit_SH1106.h to look like this:

And now the example compiles without error! Can't verify though whether it's actually working since I don't have an SH1106 display here.
Hope you can test this.

Paul

Hi Paul,
It works, and it draws in the whole display with no glitches like the library I was using, and even better, it takes 423 microseconds in the update function instead the 26.000 it was taking with the other library
you are awesome, thanks a lot for doing this ;-)
I'm using SPI1 but looks like the library does not support it, so I think it's working as SW SPI,
Code:
#define OLED_CLK 0      // CS1
#define OLED_CS 1       // MISO1
#define OLED_MOSI 9     //
#define OLED_DC 26      // MOSI1
#define OLED_RESET 27   // SCK1
 
Hi Paul,
It works, and it draws in the whole display with no glitches like the library I was using, and even better, it takes 423 microseconds in the update function instead the 26.000 it was taking with the other library
you are awesome, thanks a lot for doing this ;-)
I'm using SPI1 but looks like the library does not support it, so I think it's working as SW SPI,
Code:
#define OLED_CLK 0      // CS1
#define OLED_CS 1       // MISO1
#define OLED_MOSI 9     //
#define OLED_DC 26      // MOSI1
#define OLED_RESET 27   // SCK1

You might look at this constructor:
Code:
Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
                                   int8_t dc_pin, int8_t rst_pin, int8_t cs_pin,
                                   uint32_t bitrate)
    : Adafruit_GFX(w, h), spi(spi ? spi : &SPI), wire(NULL), buffer(NULL),
      mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
#ifdef SPI_HAS_TRANSACTION
  spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE0);
#endif
}
Which has the opton to pass in SPI1...
 
Status
Not open for further replies.
Back
Top