Printing to OLED display

Here’s a pic of the OpenMV M7 connected to the SPI OLED display. Thanks again!

1 Like

Ibrahim, can you add this to the examples?

done.

Can we add the I2C code for this module back into the driver as well?

Do you want the example shipped with the IDE?

that would be nice, but i am referencing the ssd1306 driver you added to the libraries.

The code only supports SPI communication. since it is not pulled from the main micropython branch, or was but was heavily modified to remove the I2C portion and modify some of the initialization for the SPI from the main branch, my request to to either change it to the master, or add the I2C support.

https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py

you’ll find this code missing from the library added to the openmv github.

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)
        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.temp[0] = self.addr << 1
        self.temp[1] = 0x40 # Co=0, D/C#=1
        self.i2c.start()
        self.i2c.write(self.temp)
        self.i2c.write(buf)
        self.i2c.stop()

Thanks!

I’m using this 128x64 OLED display: link

I tried to use the code above with this display and OpenMV. It is not working but it doesn’t give me any error message.

Do you know what modifications should be made in this code in order to connect this display?

Thank you!

That code isn’t written by use. Someone just sent us a PR and we added it. Can you send a PR for the fixes you need?

Now, I am using the same display than you but I have trouble with the connections.

Please could you send me the schematics of the pin connections?

Thank you!

Attached below is the code I am attempting to use. I have an SSD1306 128x32 OLED wired for I2C4, and I’m having some trouble understanding how to print text. I did some research on classes/objects, but I’m still having some trouble understanding what “self” is and how to call functions from inside classes. Do you know how to call the function to print simple text to the OLED? I’m specifically looking at what I need to include in this part of the code to make it work:

SSD1306.__init__(SSD1306,width=128,height=32, external_vcc=3.3)

SSD1306.text("HelloWorld!", 0,0,1)
SSD1306.show()

When this portion of the code is ran, I get an error stating “AttributeError: type object ‘SSD1306’ has no attribute ‘poweron’”

Thanks so much, and sorry if there are any issues with this post; this is my first post on the forums.

import time
import framebuf


from pyb import I2C

i2c = I2C(4, I2C.MASTER) # The i2c bus must always be 2.
mem = i2c.mem_read(256, 0x3C, 0) # The eeprom slave address is 0x50.


# 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)





class SSD1306:
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        # Note the subclass must initialize self.framebuf to a framebuffer.
        # This is necessary because the underlying data buffer is different
        # between I2C and SPI implementations (I2C needs an extra byte).
        self.poweron()
        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.height == 32 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 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_framebuf()

    def fill(self, col):
        self.framebuf.fill(col)

    def pixel(self, x, y, col):
        self.framebuf.pixel(x, y, col)

    def scroll(self, dx, dy):
        self.framebuf.scroll(dx, dy)

    def text(self, string, x, y, col=1):
        self.framebuf.text(string, x, y, col)



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)
        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.temp[0] = self.addr << 1
        self.temp[1] = 0x40 # Co=0, D/C#=1
        self.i2c.start()
        self.i2c.write(self.temp)
        self.i2c.write(buf)
        self.i2c.stop()

SSD1306.__init__(SSD1306,width=128,height=32, external_vcc=3.3)

SSD1306.text(1,"HelloWorld!", 0,0,1)
SSD1306.show()




Hi, this is not really a piece of hardware we support. We enabled the driver but did not test. Please check the source code for the driver in MicroPython and see what methods are there.