1

This is my first post on this forum. I'm fairly new to all things Raspberry Pi. I've been playing with some newly bought RP kit over the past 6 weeks or so. I've not been doing too badly so far in my own opinion, but I think i'm starting to get to that point now where I'm clearly needing to seek support from others in a place like this.

Please go gentle.

Ok, lets start with the subject matter to get us going.

For my Raspberry Pi 4B (RP4B) I have bought the following little OLED screen:

https://thepihut.com/collections/adafruit-lcds-displays/products/0-91-oled-display-module

I've followed all the instructions as linked here to get everything installed ready for first test usage:

https://www.waveshare.com/wiki/0.91inch_OLED_Module

I get to the point where I'm instructed to run "sudo python OLED_0in91_test.py" to test the little thing out, but instead of it doing something interesting, I just get the following:

    = RESTART: /home/chrispi/OLED_Module_Code/RaspberryPi/python/example/OLED_0in91_test.py
INFO:root:
 0.91inch OLED Module 
Only Device_I2C, Please revise config.py !!!

I simply do not know what this means to be honest and the instructions make no account of this possibility, and as such, do not offer any advice on what I need to do to fix this. I'll be honest, I'm not even sure I've got the thing wired into my RP4B correctly for the I2C interfacing!

I have the wires all plugged into the top left pins on the RP4B 3.3v, SDA, SCL, GAP, GND. So that's Pin 1, 3, 5 and 9 when referring to this pinout illustration:

https://www.google.co.uk/search?q=raspberry+pi+4b+pinout&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjHseiQyPr5AhWMYcAKHW6MD_UQ_AUoAXoECAEQAw&biw=1920&bih=906#imgrc=mWWuykwg0jWouM

Do i have the correct pins?

If anyone else has had any joy with this little display, I'd be most appreciative to receive any help you can offer me. This is my first outing with attempting to use any sort of display with a RP. Thanks!

ADDITIONAL info:

The test file I'm supposed to run (and gives me this error), lives here on my RP4B:

/home/chrispi/OLED_Module_Code/RaspberryPi/python/example

It looks like this:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import sys
import os
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)

import logging    
import time
import traceback
from waveshare_OLED import OLED_0in91
from PIL import Image,ImageDraw,ImageFont
logging.basicConfig(level=logging.DEBUG)

try:
    disp = OLED_0in91.OLED_0in91()
    logging.info("\r 0.91inch OLED Module ")
    # Initialize library.
    disp.Init()
        
    # Clear display.
    logging.info("clear display")
    disp.clear()

    # Create blank image for drawing.
    image1 = Image.new('1', (disp.width, disp.height), "WHITE")
    draw = ImageDraw.Draw(image1)
   
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    OLED_0in91.config.module_exit()
    exit() font1 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 12)
    font2 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 18)
    logging.info ("***draw line")
    draw.line([(0,0),(127,0)], fill = 0)
    draw.line([(0,0),(0,31)], fill = 0)
    draw.line([(0,31),(127,31)], fill = 0)
    draw.line([(127,0),(127,31)], fill = 0)
    logging.info ("***draw text")
    draw.text((20,0), 'Waveshare ', font = font1, fill = 0)
    draw.text((20,12), u'微雪电子 ', font = font2, fill = 0)
    image1=image1.rotate(0) 
    disp.ShowImage(disp.getbuffer(image1))
    time.sleep(3)
   
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    OLED_0in91.config.module_exit()
    exit() logging.info ("***draw image")
    Himage2 = Image.new('1', (disp.width, disp.height), 255)  # 255: clear the frame
    bmp = Image.open(os.path.join(picdir, '0in91.bmp'))
    Himage2.paste(bmp, (0,0))
    Himage2=Himage2.rotate(0)   
    disp.ShowImage(disp.getbuffer(Himage2))  
    time.sleep(3)
    disp.clear()

except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    OLED_0in91.config.module_exit()
    exit()

At this location: /home/chrispi/OLED_Module_Code/RaspberryPi/python/lib/waveshare_OLED

I see various pieces of coding. I think the ones of interest to me are:

config.py and OLED_0in91.py

config.py looks like this inside:

# /*****************************************************************************
# * | File        :   config.py
# * | Author      :   Waveshare team
# * | Function    :   Hardware underlying interface,for Raspberry pi
# * | Info        :
# *----------------
# * | This version:   V1.0
# * | Date        :   2020-06-17
# * | Info        :   
# ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to  whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

import RPi.GPIO as GPIO
import time
from smbus import SMBus
import spidev
import ctypes

# Pin definition
RST_PIN         = 27
DC_PIN          = 25
CS_PIN          = 8

Device_SPI = 1
Device_I2C = 0

if(Device_SPI == 1):
    Device = Device_SPI
    spi = spidev.SpiDev(0, 0)
else :
    Device = Device_I2C
    address = 0x3c
    bus = SMBus(1)

def delay_ms(delaytime):
    time.sleep(delaytime / 1000.0)

def spi_writebyte(data):
    spi.writebytes([data[0]])

def i2c_writebyte(reg, value):
    bus.write_byte_data(address, reg, value)
   
def module_init():
    #print("module_init")
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(RST_PIN, GPIO.OUT)
    GPIO.setup(DC_PIN, GPIO.OUT)
    GPIO.setup(CS_PIN, GPIO.OUT)  
    GPIO.output(RST_PIN, 0)
    if(Device == Device_SPI):
        spi.max_speed_hz = 10000000
        spi.mode = 0b11  
    GPIO.output(CS_PIN, 0)
    GPIO.output(DC_PIN, 0)
    return 0

def module_exit():
    if(Device == Device_SPI):
        spi.close()
    else :
        bus.close()
    GPIO.output(RST_PIN, 0)
    GPIO.output(DC_PIN, 0)

### END OF FILE ###

If i run this directly, I'm given no error, but no visible result either.

OLED_0in91.py looks like this inside:

# /*****************************************************************************
# * | File        :   OLED_0in91.py
# * | Author      :   Waveshare team
# * | Function    :   Driver for OLED_0in91
# * | Info        :
# *----------------
# * | This version:   V2.0
# * | Date        :   2020-08-18
# * | Info        :   
# ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to  whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

from . import config
import RPi.GPIO as GPIO
import time
import numpy as np

Device_SPI = config.Device_SPI
Device_I2C = config.Device_I2C

OLED_WIDTH   = 128 #OLED width
OLED_HEIGHT  = 32  #OLED height

class OLED_0in91(object):
    def __init__(self):
        self.width = OLED_WIDTH
        self.height = OLED_HEIGHT
        self.Column = OLED_WIDTH
        self.Page = int(OLED_HEIGHT//8)
        #Initialize DC RST pin
        self._dc = config.DC_PIN
        self._rst = config.RST_PIN
        self.Device = config.Device
        
    """    Write register address and data     """
    def command(self, cmd):
        config.i2c_writebyte(0x00, cmd)

    def data(self, data):
        config.i2c_writebyte(0x40, data)

    def Init(self):
        if (config.module_init() != 0):
            return -1
          
        if(self.Device == Device_SPI):
            print ("Only Device_I2C, Please revise config.py !!!")
            exit()    
            
        self.reset()
        """Initialize dispaly"""      
        #print("initialize register bgin")
        self.command(0xAE)

        self.command(0x40) # set low column address
        self.command(0xB0) # set high column address

        self.command(0xC8) # not offset

        self.command(0x81)
        self.command(0xff)

        self.command(0xa1)

        self.command(0xa6)

        self.command(0xa8)
        self.command(0x1f)

        self.command(0xd3)
        self.command(0x00)

        self.command(0xd5)
        self.command(0xf0)

        self.command(0xd9)
        self.command(0x22)

        self.command(0xda)
        self.command(0x02)

        self.command(0xdb)
        self.command(0x49)

        self.command(0x8d)
        self.command(0x14) 
        time.sleep(0.2)
        self.command(0xaf) #turn on OLED display 
        #print("initialize register over")
        
    def reset(self):
        """Reset the display"""
        GPIO.output(self._rst,GPIO.HIGH)
        time.sleep(0.1)
        GPIO.output(self._rst,GPIO.LOW)
        time.sleep(0.1)
        GPIO.output(self._rst,GPIO.HIGH)
        time.sleep(0.1)
    
    def getbuffer(self, image):
        buf = [0xff] * (self.Page * self.Column)
        image_monocolor = image.convert('1')
        imwidth, imheight = image_monocolor.size
        pixels = image_monocolor.load()
        if(imwidth == self.width and imheight == self.height):
            print ("Horizontal screen")
            for y in range(imheight):
                for x in range(imwidth):
                    # Set the bits for the column of pixels at the current position.
                    if pixels[x, y] == 0:
                        buf[x + int(y / 8) * self.width] &= ~(1 << (y % 8))
        elif(imwidth == self.height and imheight == self.width):
            print ("Vertical screen")
            for y in range(imheight):
                for x in range(imwidth):
                    newx = y
                    newy = self.height - x - 1
                    if pixels[x, y] == 0:
                        buf[(newx + int(newy / 8 )*self.width) ] &= ~(1 << (y % 8))
        for x in range(self.Page * self.Column):
            buf[x] = ~buf[x]
        return bufmage(_buffer)     
            
    def ShowImage(self, pBuf):
        for i in range(0, self.Page):            
            self.command(0xB0 + i) # set page address
            self.command(0x00) # set low column address
            self.command(0x10) # set high column address
            # write data #
            for j in range(0, self.Column):
                self.data(pBuf[j+self.width*i])
                    
    def clear(self):
        """Clear contents of image buffer"""
        _buffer = [0x00]*(self.width * self.height//8)
        self.ShowImage(_buffer)

If i run this directly, I get the following result:

Traceback (most recent call last):
  File "/home/chrispi/OLED_Module_Code/RaspberryPi/python/lib/waveshare_OLED/OLED_0in91.py", line 30, in <module>
    from . import config
ImportError: attempted relative import with no known parent package
>>> 

I've run the following with the following result (3c) which looks like it might being seeing the display ok (as well as another I2C device I have there in series with it (76)):

chrispi@raspberrypi:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- 76 -- 

Does this help anyone help me diagnose what my problem is?

1
  • What OS? Have you installed the dependencies? Do NOT expect people to read the links and guess what you may or may not have done. Explain what YOU HAVE DONE.
    – Milliways
    Sep 4, 2022 at 22:15

1 Answer 1

0

At first guess this is a programming problem.

Prior to Bullseye python2 was default but is now deprecated and no longer installed. IMO it is poor programming practice to NOT explicitly identify which python is to be used.

This appears to be python2 code.

The logic of relative imports is significantly different between versions - not easily fixed by a beginner.

You may find it works if you use "Legacy" i.e. Buster.

1
  • Thanks for taking the time to look into this. That would probably do it I guess. I did some further reading last night. I think this screen is called a "SSD1306" OLED. I then found this link, which helped me out enormously. Much easier to follow, and gave me a good working basis to get this little screen working to my own ends ok. So i'm up and running despite Waveshare not updating their code. Link: learn.adafruit.com/…
    – Rissy
    Sep 5, 2022 at 17:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.