I2C from machine vs I2C from pyb

Besides their API syntax being different, is there any reason when I should favor one over the other.

“from machine import I2C” seems to be often used on boards equipped with an ESP module though.

Use pyb.I2C. I’ve never tested the machine variant.

The general direction that MicroPython is moving is to eventually phase out the pyb module and replace it with machine module.

The machine module on the pyboard allows both HW and bit banged I2C to be used.

So right now, its really just a question of which API you want to use.


That machine.I2C is actually the one that I would like to use, but I’m having trouble figuring out how to call its constructor.

It seems that there is a new machine.I2C interface currently available on Micropython for the ESP8266; which is not the one available in the OpenMV firmware (2017-01-13). Therefore, I get a “TypeError: can’t convert ‘int’ object to str implicitly” error when I try this:

import machine
i2c = machine.I2C(machine.Pin(5), machine.Pin(4))

And, I cannot figure out how to assemble this constructor either:


Have you used the latter before with the Pyboard or OpenMV board?

Hi, any reason you need the machine module? We’re about to update the docs and no effort was put in to document that since we’re using pyb.I2C.

Hi Kwabena,

I’m trying to adapt the code below for the VL53L0X sensor and if I use the pyb.I2C, then I’ll have to change calls like writeto() and readto() with the counterpart mem_write() and mem_read() methods in the pyb.I2C module; which they behave different (i.e. the former sends an ack / nack of the last byte). If I don’t have any other option, then I’ll do that. However, as Dave indicated; MicroPython will eventually replace the pyb module with machine module so I prefer to use the machine.I2C version.


Well, I believe the machine.i2C module is compiled into the binary right now but I can’t say we support it. I’m not going to press Ibrahim to update MP right now since everything breaks when we do that. However, it would be nice to have the time available to do the update.

I’m working on getting our release we’ve been talking about out soon.

Thanks Kwabena!

Just let me know if you release it internally like you and Ibrahim did for the one that supports the QRCode so I can help testing it before it’s officially released. Cheers!

It looks like the machine.I2C module included in the current OpenMV (my camera shows v1.8-4348-g62d6127) is SW only machine.I2C which follows the esp8266 documentation:
which requires you to provide sda and scl pins.

Newer MicroPython (my board version 1.8.6) you can use:

i2c = machine.I2C(1)

and it will use the HW I2C. If you pass -1 as the first argument then it needs the sda and scl arguments and becomes a SW I2C.

I was able to do this on my OpenMV:

>>> import machine
>>> import pyb
>>> i2c = machine.I2C(sda=pyb.Pin('P5'), scl=pyb.Pin('P4'))
>>> i2c.scan()

0x27 (39) is the i2c device I had plugged into the bus. In 1.8.6.

Once OpenMV gets to 1.8.6 you can change machine.I2C(sda=pyb.Pin(‘P5’), scl=pyb.Pin(‘P4’)) to be machine.I2C(2) and then it will use HW I2C rather than bitbanged (SW) I2C.

Thanks Dave. It works!

>>> from machine import I2C, Pin
>>> i2c = I2C(sda=Pin('P5'), scl=Pin('P4'))
>>> print(i2c.scan())

Wow, the machine.i2c module is poorly documented for the Pyboard. It actually indicates that the first argument is scl, and the second is sda.

Anyhow, thank again!


After the function below is called several times, I get this message “OSError: I2C bus error”. Do I need to set the freq value in the constructor?

def _set_reg8(self, address, value):
        data = ustruct.pack('>HB', address, value)
        self.i2c.writeto(self._address, data)
def init(self):
        self._set_reg8(0xFF, 0x01);   #OK
        self._set_reg8(0x00, 0x00);  #OK
        self._set_reg8(0xFF, 0x00);   #OK
        self._set_reg8(0x09, 0x00);  #OK
        self._set_reg8(0x10, 0x00);  #OK
        self._set_reg8(0x11, 0x00);  #OK
        self._set_reg8(0x24, 0x01);  #OK
        self._set_reg8(0x25, 0xFF);  #OK
        self._set_reg8(0x75, 0x00);  #OK
        self._set_reg8(0xFF, 0x01);  #OK
        self._set_reg8(0x4E, 0x2C);  #FAIL with "OSError: I2C bus error"

I’ll make sure to include the machine doc in the doc release I’m about to do.

cagiva - check if the packet was acked… if you have a protocol analyzer that would be good to use. Otherwise, use the exception mechanism and try the command again.

The docs for pyboard’s machine.I2C is here: http://docs.micropython.org/en/latest/pyboard/library/machine.I2C.html (so I’m not sure which docs you were looking at).

I seem to recall that there may have been some bugs related to clock stretching that were fixed recently. Its possible that OpenMV still has the buggy version. Running at a slower frequency might work around the problem.

I’ll have to wait until Kwabena and Ibrahim update their firmware with MP version 1.8 or later. Until then, I’ll have to use bitbanged (SW) I2C.

>>> import machine
>>> i2c=machine.I2C(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'sda' argument required

We’re at version 1.8. But, we’re not likely to update to the newest version until after the M7 ships. Every time we update a lot of things break. So, that would be done when more or less everything is working to make fixing everything easy.

Oh, note that we’ve finished prototyping the M7 and have gone ahead and ordered 40 units to build 2 panels to test mass production.

I meant v1.8.7 or later. I thought you offer to upgrade and do an internal release before M7 is shipped. However, if that is not going to be the case, then our project will have to drop M4 and look for another option. Thanks for clarifying this though.

Well, I’d rather not have you dropping the project.

But, from reading the above you found a workable solution in the mean-time right?

We might be also able to just patch that one file.

No really since I can only use bitbanged SW I2C; which seems to be too slow for us. We would like to try the hardware I2C so it’ll be greatly appreciated if you could just patch/upgrade the machine module.

BTW, congratulations on reaching the goal for M7!

Okay, I should just be able to generate a patched version of the firmware for you. Not an official release or anything. I’ll do this after we do this release we’ve been gearing up for. Note: I’m just going to patch the machine.I2C file.