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:
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?