frans
frans

Reputation: 9808

In MicroPython reading memory from attached device via I2C ignores provided address

I'm trying to translate an Arduino example project for the M5 Thermal HAT (using MLX90640) (on an M5StickC) which works for me to MicroPython (1.18).

While trying to read data via I2C strange things happen.

Creating the I2C object and scanning the bus with the HAT attached works as expected:

>>> from machine import Pin, I2C
>>> i2c = I2C(0, sda=Pin(0), scl=Pin(26), freq=800000)
>>> i2c.scan()
[51]

Reading the status register at 0x8000 as described in the MLX90680 documentation also returns data which seems plausible to me:

>>> list(i2c.readfrom_mem(0x33, 0x8000, 2))
[0, 8]
>>> list(i2c.readfrom_mem(0x33, 0x8000, 2))
[0, 9]

Bit 3 indicates available data and bit 0 seems to toggle pages.

But now the magic begins.

As I try to read the "control register" at 0x800D as demonstrated in an Adafruit example (and all other examples) it seems to behave exactly like the status register (with a toggling first bit, which should not happen on a control register):

>>> list(i2c.readfrom_mem(0x33, 0x800D, 2))
[0, 9]
>>> list(i2c.readfrom_mem(0x33, 0x800D, 2))
[0, 8]

After a bit of experimenting and playing with different addresses and sizes I had to realize that the address provided with I2C.readfrom_mem() seems to be totally ignored:

>>> list(i2c.readfrom_mem(0x33, 0x0000, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x1000, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x2400, 16))
[0, 9, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]
>>> list(i2c.readfrom_mem(0x33, 0x2800, 16))
[0, 8, 0, 191, 121, 159, 0, 0, 32, 97, 0, 4, 3, 32, 3, 224]

I tried turning all devices off and on again, played with different values for addrsize and clock speeds and tried a different HAT attached to the stick (to make sure I2C is working fine in principal) but all with no insights.

Since most code examples (e.g. this or that) demonstrating how to use the MLX90640 sensor via I2C use low level access to I2C (rather than MicroPythons readfrom_mem implementation) I also tried a discrete write/read approach:

>>> i2c.writeto(0x33, bytes([0x80, 0x0D]))
2
>>> list(i2c.readfrom(0x33, 2))
[0, 9]
>>> i2c.writeto(0x33, bytes([0x0D, 0x80]))  # try swapped byte order
2
>>> list(i2c.readfrom(0x33, 2))
[0, 9]

With all the same effect.

What do I do wrong here? Since I can read data from the I2C bus I guess I don't have a problem of electrical nature.. (also the native Arduino example is fully working on the same device).

Is there some basic I2C knowledge I missed until now?

Why do all I2C read operations on this device issued by MicroPython seem to disregard the address while others are working totally fine?

Upvotes: 1

Views: 1084

Answers (1)

IAMLIUBO
IAMLIUBO

Reputation: 26

It looks like you are missing the stop parameter.

micropython I2C writeto

Try this:

i2c.writeto(0x33, bytes([mem_address>>8, mem_address&0xFF]), False)
i2c.readfrom(0x33, 2)

Accordingly to write data you'd write:

i2c.writeto(0x33, bytes([mem_address>>8, mem_address&0xFF] + [d,a,t,a]))

Upvotes: 1

Related Questions