Comments on: Raspberry Pi Pico: SSD1306 OLED Display (MicroPython) https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/ Learn ESP8266, ESP32, Arduino, and Raspberry Pi Wed, 25 Dec 2024 22:58:56 +0000 hourly 1 https://wordpress.org/?v=6.8.2 By: Jerry https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-994494 Wed, 25 Dec 2024 22:58:56 +0000 https://randomnerdtutorials.com/?p=132900#comment-994494 I believe the ‘oled.invert(True)’ and ‘oled.invert(False)’ commands are in error.

For me, ‘oled.invert(1)’ gives me inverted text/background colors.
‘oled.invert(0)’ returns the display to normal (light text/dark background)

Jerry

]]>
By: Luis https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-981313 Thu, 07 Nov 2024 13:05:54 +0000 https://randomnerdtutorials.com/?p=132900#comment-981313 Hi Sara:
I have got some problems with the library , SoFtI2c, it seems it has problems to accept commands like blit when you want to show the Raspberry icon , i have found the solution. first use this:
copy and rename as ssd1306.py load with thonny to the rpi pico, then run then run the second program , you will enjoy , Best Regards from Spain

MicroPython SSD1306 OLED driver, I2C and SPI interfaces

from micropython import const
import framebuf

register definitions

SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)

Subclassing FrameBuffer provides support for graphics primitives

http://docs.micropython.org/en/latest/pyboard/library/framebuf.html

class SSD1306(framebuf.FrameBuffer):
def init(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
super().init(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
self.init_display()

def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO,
self.height - 1,
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
SET_DISP_OFFSET,
0x00,
SET_COM_PIN_CFG,
0x02 if self.width > 2 * self.height else 0x12,
# timing and driving scheme
SET_DISP_CLK_DIV,
0x80,
SET_PRECHARGE,
0x22 if self.external_vcc else 0xF1,
SET_VCOM_DESEL,
0x30, # 0.83*Vcc
# display
SET_CONTRAST,
0xFF, # maximum
SET_ENTIRE_ON, # output follows RAM contents
SET_NORM_INV, # not inverted
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01,
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()

def poweroff(self):
self.write_cmd(SET_DISP | 0x00)

def poweron(self):
self.write_cmd(SET_DISP | 0x01)

def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)

def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))

def show(self):
x0 = 0
x1 = self.width - 1
if self.width == 64:
# displays with width of 64 pixels are shifted by 32
x0 += 32
x1 += 32
self.write_cmd(SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)

class SSD1306_I2C(SSD1306):
def init(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
self.write_list = [b”\x40″, None] # Co=0, D/C#=1
super().init(width, height, external_vcc)

def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)

def write_data(self, buf):
self.write_list[1] = buf
self.i2c.writevto(self.addr, self.write_list)

class SSD1306_SPI(SSD1306):
def init(self, width, height, spi, dc, res, cs, external_vcc=False):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time

self.res(1)
time.sleep_ms(1)
self.res(0)
time.sleep_ms(10)
self.res(1)
super().__init__(width, height, external_vcc)

def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)

def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buf)
self.cs(1)

program to load with Thonny:

Display Image & text on I2C driven ssd1306 OLED display

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import framebuf

WIDTH = 128 # oled display width
HEIGHT = 64 # oled display height

i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=200000) # Init I2C using pins GP4& GP5 (default I2C0 pins)
print(“I2C Address : “+hex(i2c.scan()[0]).upper()) # Display device address
print(“I2C Configuration: “+str(i2c)) # Display I2C config

oled = SSD1306_I2C(WIDTH, HEIGHT, i2c) # Init oled display

Raspberry Pi logo as 32×32 bytearray

buffer = bytearray(b”\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L’\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00”)

Load the raspberry pi logo into the framebuffer (the image is 32×32)

fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)

Clear the oled display in case it has junk on it.

oled.fill(0)

Blit the image from the framebuffer to the oled display

oled.blit(fb, 96, 0)

Add some text

oled.text(“Raspberry Pi”,5,5)
oled.text(“Pico”,5,15)

Finally update the oled display so the image & text is displayed

oled.show()

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-906432 Tue, 16 Apr 2024 09:13:38 +0000 https://randomnerdtutorials.com/?p=132900#comment-906432 In reply to Emily.

Hi.
Are you sure you have an SSD1306? Some OLED displays come with a different driver..
Regards,
Sara

]]>
By: Emily https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-906366 Mon, 15 Apr 2024 23:21:34 +0000 https://randomnerdtutorials.com/?p=132900#comment-906366 In reply to Judson Belmont.

My I2C scanner keeps reporting that its on 60 (0x3c), but this address doesn’t work, and returns the “OSError: [Errno 5] EIO”. I even set up a script to try to initialize the oled object with every hex address from 0 to 5000 (arbitrary number, I have no idea how many addresses are even capable of supporting the oled), but none worked. I’m combing through the ssd1306 module to see if something’s misconfigured in it now.

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-894326 Sat, 24 Feb 2024 10:53:57 +0000 https://randomnerdtutorials.com/?p=132900#comment-894326 In reply to Judson Belmont.

Hi.
I’ll add a note about that.
My display works well with 3.3V, but other models might require 5V.
Thanks for your contribution.
Regards,
Sara

]]>
By: Judson Belmont https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-894045 Fri, 23 Feb 2024 22:57:13 +0000 https://randomnerdtutorials.com/?p=132900#comment-894045 In reply to Sara Santos.

Sara, I have an additional tip. I have been using a 128 X64 OLED display by Adafruit. After much frustration, I discovered that the only way to get consistent response is to use the 5 volt VBus on the pico. I have read about 25 tutorials, stackover threads, MicroPython threads and none of them mentioned that. I was receiving both errno 15, errno 8 and the no device error aa well as a wide range of errors messages referring to the ssd1306 library. 5 Volts fixed them all !!

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-877762 Thu, 14 Dec 2023 15:44:26 +0000 https://randomnerdtutorials.com/?p=132900#comment-877762 In reply to Jim Walker.

Hi.
Check your I2C connections.
Additionally, double-check your OLED I2C address.
I’ve just added a section about it after realizing some people were having issues with it.
Regards,
Sara

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-877730 Thu, 14 Dec 2023 12:39:12 +0000 https://randomnerdtutorials.com/?p=132900#comment-877730 In reply to Alberto.

Hi.
Please send me an email with your issue.
Make sure to be specific.
https://randomnerdtutorials.com/contact/
Regards,
Sara

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-877720 Thu, 14 Dec 2023 11:22:36 +0000 https://randomnerdtutorials.com/?p=132900#comment-877720 In reply to Judson Belmont.

Thanks for sharing the solution. I’ll add a note on the tutorial about finding the I2C address of the OLED.
Regards,
Sara

]]>
By: Sara Santos https://randomnerdtutorials.com/raspberry-pi-pico-ssd1306-oled-micropython/#comment-877719 Thu, 14 Dec 2023 11:19:58 +0000 https://randomnerdtutorials.com/?p=132900#comment-877719 In reply to Judson Belmont.

Hi.
I found two similar issues.
Take a look to see if any of the suggestions help:
forums.raspberrypi.com/viewtopic.php?t=343639
forums.raspberrypi.com/viewtopic.php?p=2046466&hilit=1306#p2046466

Regards,
Sara

]]>