wokwi/rp2040js

MicroPython i2c `writeto()` fails for unknown reason

Closed this issue · 1 comments

Hi,

I'm trying to use MicroPython's i2c in the emulator (docs) through direct use of the rp2040js library

The following code fails when executed in the emulator:

import machine
sda = machine.Pin(16)
scl = machine.Pin(17)
i2c = machine.I2C(0, sda=sda, scl=scl, freq=1000000)
packet = bytearray(2)
addr = 0x3C
packet[0] = 0x80
packet[1] = 0x10
i2c.writeto(addr, packet)

Output (including lines entered and echoed from REPL):

>>> import machine
>>> sda=machine.Pin(16)
>>> scl=machine.Pin(17)
>>> i2c = machine.I2C(0, sda=sda, scl=scl, freq=1000000)
>>> packet = bytearray(2)
>>> addr = 0x3C
>>> packet[0] = 0x80
>>> packet[1] = 0x10
>>> i2c.writeto(addr, packet)
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
OSError: [Errno 5] EIO

However, writevto() seems to work without error but I can't find a way to receive/intercept the data transmitted from i2c, for example:

mcu.i2c[0].onStart = () => {
  console.log("I2C Start");
}

mcu.i2c[0].onStop = () => {
  console.log("I2C Stop");
}

mcu.i2c[0].onConnect = () => {
  console.log("I2C Connect");
}

mcu.i2c[0].onReadByte = () => {
  console.log("R");
}

mcu.i2c[0].onWriteByte = () => {
  console.log("W");
}

The above only shows that i2c starts but none of the other callbacks fire, in any case, it doesn't look like I would be able to intercept the data in JS using the above callbacks, is there any way?

urish commented

The thing is, you need to tell the i2c peripheral to complete each operation, e.g.:

const i2c = mcu.i2c[0];
i2c.onStart = () => {
  console.log("I2C Start");
  // now tell I2C that we're done:
  i2c.completeStart();
}

You can find the complete list of "complete" methods in the i2c peripheral's source code.