Do you use a pycom board? Then add some wait. You have to wait until the *Py and the board is initialized. Sadly there is no flag or event which tells you that init is ready. So you have to find the right time for your system by your own. It will depend on firmware version and the hardware you added - especially your display.
Give 1.20 rc4 a try. This version solved my problems with i2c and pytrack
This doesn't work in Pycom's MicroPython release 1.18 (current stable) but the fix from the above linked issue has been incorporated into the development release 1.20 (currently at rc4).
Additionally, the Pycom MicroPython flavor has a different I2C API than the official MicroPython, lacking the I2C methods start(), stop() and write(). There you need to apply the changes outlined in this old thread as well:
If you get noisy display you might have an SH1106 display. I'm using the below piece of code successfully with random eBay 0.96" and 1.3" I2C OLED displays. It's been a few years since I looked into this but IIRC the SH1106 module's internal memory layout is for 132 pixel strides but the screen only supports 128. So the noise in the form of random black pixels come from the fact that those extra two pixels on the left and on the right side are not accounted for (the display is centered somehow).
from ssd1306 import 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)
# Parent does show() but is using the SSD1306 implementation..
def write_cmd(self, cmd):
self.temp = 0x80 # Co=1, D/C#=0
self.temp = cmd
def write_data(self, buf):
self.i2c.writeto(self.addr, bytearray([0x40]) + buf)
for page in range(8):
self.write_cmd(0xb0 | page)
self.write_cmd(0x02) # Start addr low column
self.write_cmd(0x10) # Start addr high column
mv = memoryview(self.buffer)
self.write_data(mv[128*page: 128 + 128*page])
from sh1106 import SH1106_I2C
i2c = I2C(0, I2C.MASTER, baudrate=400000)
d = SH1106_I2C(128, 64, i2c)
d.text('ping', 1, 2)