Pico SDK appendix sh1106 display example problem

I’m using the suggested library from:
GitHub - robert-hh/SH1106: MicroPython driver for the SH1106 OLED controller

To drive my Pimoroni 1.12” sh1106 display

Unfortunately, there appears to be a slight problem. I have routines to draw lines, boxes, circles etc, which work properly on other displays, including the ssd1306, which I have tried successfully on my Pico. The display on the sh1106 overflows from the right edge of the screen to the start of the next line on left side.

Here is my code.

# Display Image & text on I2C driven ssd1306 OLED display 
from machine import Pin, I2C
from sh1106 import SH1106_I2C
import framebuf
from time import sleep
import math
WIDTH  = 128                                            # oled display width
HEIGHT = 128                                            # oled display height

i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000)       # Init I2C using pins GP8 & GP9 (default I2C0 pins)
print("I2C Address      : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c))                   # Display I2C config


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

# Raspberry Pi logo as 32x32 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 32x32)
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)

def horiz(l,t,r,c):  # left, top, right colour
    n = r-l+1        # Horizontal line
    for i in range(n):
        oled.pixel(l + i, t , c)

def vert(l,t,b,c):   # left, top, bottom, colour
    n = b-t+1        # Vertical line
    for i in range(n):
        oled.pixel(l, t+i, c)

def box(l,t,r,b,c):  # left, top, right, bottom, colour
    horiz(l,t,r,c)   # Hollow rectangle
    horiz(l,r,b,c)
    vert(l,t,b,c)
    vert(r,t,b,c)

def block(l,t,r,b,c):  # left, right, top, bottom, colour
    n = b-t+1          # Solid rectangle
    for i in range(n):
        horiz(l,t+i,r-1,c)  # One line at a time

def line(x,y,xx,yy,c): # (x,y) to (xx,yy)
    if x > xx:
        t = x  # Swap co-ordinates if necessary
        x = xx
        xx = t
        t = y
        y = yy
        yy = t
    if xx-x == 0:  # Avoid div by zero if vertical
        vert(x,min(y,yy),max(y,yy),c)
    else:          # Draw line one dot at a time L to R
        n=xx-x+1
        grad = float((yy-y)/(xx-x))  # Calculate gradient
        for i in range(n):
            y3 = y + int(grad * i)
            oled.pixel(x+i,y3,c)  # One dot at a time

def display(t):  # Time in seconds
    oled.show()  # Show new screen and wait
    sleep(t)

def circle(cx,cy,r,c):   # Centre (x,y), radius, colour
    for angle in range(0, 90, 2):  # 0 to 90 degrees in 2s
        y3=int(r*math.sin(math.radians(angle)))
        x3=int(r*math.cos(math.radians(angle)))
        oled.pixel(cx-x3,cy+y3,c)  # 4 quadrants
        oled.pixel(cx-x3,cy-y3,c)
        oled.pixel(cx+x3,cy+y3,c)
        oled.pixel(cx+x3,cy-y3,c)

oled.fill(0)  # Clear screen BLACK
oled.show()

box(1,1,125,125,1) # OK
oled.text("OK",50,60,1)
circle(64,64,50,1)
oled.show()
sleep(4)

oled.fill(0)  # Clear screen BLACK
oled.show()

box(0,0,127,127,1)
oled.text("Problem",40,60,1)
circle(64,64,50,1)
oled.show()
sleep(5)

It is a first batch 1.12" display and I had a similar problem with it on the Pi - only recently solved with a Pimoroni package update.

I could do with some help as I’m sure others will hit the same snag.

Temporary solution: Keep away from the edges!

I was getting that as well, at a guess it’s part of the underlying code for the screen starting to write at the wrong position and rolling over.

I would take a poke and see if I could fix it (unlikely) but I was playing around with the framebuffer module and seem to have gotten my Pico stuck in a boot loop, any time it loads main.py it’s unresponsive. Ugh.

Again, if we could access the filesystem over USB, this would be trivial to fix…

Would nuking the Pico help to break out and then put the uf2 file back in? You could then start again. I’m not putting main.py on the Pico but running from Thonny with the files on the PC.

No, I uploaded a C++ .uf2 file, but that doesn’t seem to wipe the python files off the file system so as soon as I went back to MicroPython it got stuck on main.py again.

I was about to go and read up on using the SWD debugging interface, but the loop seemed to be after trying one of the framebuffer methods. It occurred to me that just unplugging the OLED would mean the I2C bus connection would fail and the framebuffer call wouldn’t run, and that sorted it.

Refreshing flash memory.
You can download flash_nuke.uf2 here
Getting Started with Raspberry Pi Pico – Raspberry Pi
it takes out ALL the files leaving a clean Pico ready to load a new .uf2 file.

1 Like

Oh, I’d totally missed that somehow. Thanks, I’ll bear that in mind in case I ever hit the same thing again.