robert-hh / SH1106

MicroPython driver for the SH1106 OLED controller
Other
157 stars 38 forks source link

OSError: I2C bus error (-1) #7

Closed jasonblewis closed 5 years ago

jasonblewis commented 5 years ago

When I try and run this on the ESP32 with the loboris micropython version, I get the following error:

>>> from machine import Pin, I2C
>>> import sh1106
>>> i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
>>> display = sh1106.SH1106_I2C(128, 64, i2c, None, 0x3c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "sh1106.py", line 173, in __init__
  File "sh1106.py", line 109, in __init__
  File "sh1106.py", line 114, in init_display
  File "sh1106.py", line 121, in poweron
  File "sh1106.py", line 178, in write_cmd
OSError: I2C bus error (-1)
>>> 
jasonblewis commented 5 years ago

sorry, the above paste was with the wrong pins for SCL and SDA. corrected below.

from machine import Pin, I2C
import sh1106

i2c = I2C(scl=Pin(22), sda=Pin(21), freq=400000)
display = sh1106.SH1106_I2C(128, 64, i2c, None, 0x3c)
display.sleep(False)
display.fill(0)
display.text('Testing 1', 0, 0, 1)
display.show()

gives

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 18, in <module>
  File "sh1106.py", line 173, in __init__
  File "sh1106.py", line 109, in __init__
  File "sh1106.py", line 115, in init_display
  File "sh1106.py", line 149, in show
  File "sh1106.py", line 186, in sw_write_data
OSError: I2C: command before begin!
robert-hh commented 5 years ago

I never tried that driver with the loboris port, and I have no display available for testing. I have to get one first.

robert-hh commented 5 years ago

May I ask you to try with the following simplification of the SH1106_I2C class:

class SH1106_I2C(SH1106):
    def __init__(self, width, height, i2c, res=None, addr=0x3c, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.res = res
        self.temp = bytearray(2)
        if res is not None:
            res.init(res.OUT, value=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.i2c.writeto(self.addr, b'\x40'+buf)

    def reset(self):
        super().reset(self.res)
jasonblewis commented 5 years ago

I’m afk for a few days. I’ll give this a go next week

bonnom commented 5 years ago

I had the same error, and simplifying the i2c did help but now I get the error: Anything I did wrong?

>>> from machine import Pin, I2C
>>> import sh1106
>>> i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
>>> display = sh1106.SH1106_I2C(128, 64, i2c, Pin(33), 0x3c)
>>> display.sleep(False)
>>> display.fill(0)
>>> display.text('Testing 1', 0, 0, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function takes 1 positional arguments but 5 were given
>>> 
robert-hh commented 5 years ago

I have no I2C connected display available at the moment for testing. So It will take a day or so before I can verify that. Besides that, it's strange. The text method is the one from the framebuf module. Which Python version and module are you using?

bonnom commented 5 years ago

I found my problem, I build the Loboris ESP32 micropython without framebuf library what had to be enabled in the config. I didn't know that so I installed the adafruit framebuf library. I think that caused the problem!

robert-hh commented 5 years ago

Ok. Thanks.

elpenno82 commented 4 years ago

I had the same problem. Forcing the class to use HW_write fixes the issue. In my case this was done by replacing: if hasattr(self.i2c, "start"): to if False:

in line 171. I guess this is because esp32 has a hardware builtin i2c driver, but due to (compatability?) i2c does have the method start(), but you cannot actually use it.