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.

Hi, i have a question, how can i make an image like the raspberry logo, but with my own image? I’m experimenting with my new Pico, but i don’t know how can i make another picture in hex array, also, if someone can explain, what is a byte array? thanks in advance!

A byte array is a list of bytes (8 bits) - an array of one dimension. The values , in the range 0 to 255, in denary can be expressed in hexadecimal, 00 to FF, The same method can be used to store a string of characters with their ASCII code values in some systems.
Each hex number in the list represents a single byte with each bit representing a single pixel.

I’ve done something like this before with an Arduino and a Nokia display. I wrote it up and you can find it here:
Nokia 5110 Arduino Project From Start to Hero - Tutorial45

The tools for producing the ‘STAR’ image may help you on your way. If I have time I will may try to give it a go with Pico and SSD1306. You need to find out if the bytes are used vertically or horizontally (trial and error?)

Hope this helps - best of luck

1 Like

I’ve just posted how to make your own icons here in Tutorial Discussions.

Pico and SSD1306 - bounce your own Icons - Discussion / Learning Resources - Pimoroni Buccaneers

I’ve done it for SSD1306 but it should give you more ideas. Best of luck.

1 Like

¡Hi Tony! thank you so much for your kindly help, with the help of your tutorial i be able to put my custom character in the oled display, i faced some problems like the LCDAssistant doesn’t work, it only gives me values like 0x00, but i used this online tool instead of the LCDAssistant http://tomeko.net/online_tools/file_to_hex.php , the image contained some rare random pixels on the top, but i moved the picture at the -15 coordinate. in the display to make it invisible, also i delete all the “0x00” cause i think they are useless, and this action don’t do anything in the image or in the random pixels, i will keep investigating about the random pixels, but in theory, the thing that i wanted to do is done, again, thank you so much for your help, i know that your tutorial will help so many people!

Your file converter gives all the data in the file including the header. It is far too long.
See here for BMP format which starts with a header block which is not needed in the program.

BMP - Image File Format
You only need 128 bytes (32 lines of 4 bytes per line.)

Glad you are making progress.

Hi Tonygo2
You may have already sorted this - but I was hacking together a Sh1106 driver in C for the Pico (basically copying the python in sh1106.py but without the fancy Framebuf bits). I came across the same problem. However in the python function show() it sets the _LOW_COLUMN_ADDRESS to 2. Now this may well be for a reason I don’t understand but… if I set it to 0 my overlap problems go away.
Cheers,
John