Read I2C 16-bit addresses



  • Hi everyone,

    I have a thermal sensor mlx90640, which works with I2C 16-bit register addresses. As I understood the i2c library available by onion works only with 8-bit/10-bit addresses.

    Is already there any available implementation to overcome this question?

    Thanks in advance,
    Pedro Moura



  • I'm having a related problem. Using Python to access a pressure sensor, Adafruit MPRLS, takes a single byte address (fixed at 0x18), but to read its register, requres a direct 4-byte read with no address register or instruction register on the chip. The Onion i2c implementation doesn't seem to have a routine for this register-less read function. There was some discussion of this problem in the forum earlier and people used an SMBus implementation, but it was not described well enough for me to follow. Has anyone solved this problem and can explain the solution? Or else an updated official PyOnionI2C package that can read a slave just using its bus address (e.g. 0x18) without specifying a register? Thanks.



  • You can find the earlier thread by searching for "I2C: how to read a single byte without register address?"


  • administrators

    There is a function in the Onion I2C library that does a read of n-bytes without writing: i2c_readRaw()

    It looks like it wasn't added to the I2C C Library documentation though. If anybody is inspired to update the documentation, here it is on GitHub, we accept PRs: https://github.com/OnionIoT/Onion-Docs/blob/master/Omega2/Documentation/Reference/Libraries/I2C-C-Library.md

    See the function declaration here: https://github.com/OnionIoT/i2c-exp-driver/blob/master/include/onion-i2c.h#L63

    @Pedro-Moura
    For your 16-bit address use, you can try using i2c_writeBufferRaw() to write the 2 address bytes and then i2c_readRaw() to read the data.

    @Yale-E-Goldman
    i2c_readRaw() should work for what you need.

    Let me know how it goes!



  • @Lazar-Demin said in Read I2C 16-bit addresses:

    i2c_readRaw()

    Hi Lazar,

    Thanks for the reply. But it looks like i2c_readRaw() is a C subroutine, not a python command. For instance in the code here:

    from OmegaExpansion import onionI2C
    import time
    i2c = onionI2C.OnionI2C()
    while (1):

    x = i2c.readBytes(0x20, 0x03, 1)
    time.sleep(0.1)	
    y = i2c.i2c_readRaw(0x20)
    print x, y	
    time.sleep(1)
    

    the line defining 'x' works fine, but the one trying to read without a register
    returns the message "Attribute error: 'OnionI2C' object has not attribute 'i2c_readRaw' "
    Can I access the readRaw function from Python?

    All the best.


  • administrators

    @Yale-E-Goldman Yes, you can access the readRaw function in python:

    From https://github.com/OnionIoT/i2c-exp-driver/blob/master/src/python/onion-i2c-module.c#L170 :

    PyDoc_STRVAR(onionI2C_read_doc,
    	"read(deviceAddr, numBytes) -> [values]\n\n"
    	"Read 'numBytes' bytes on I2C device with 'deviceAddr' address.\n");
    

    So in your program it would look like this if you want to read 2 bytes:

    y = i2c.read(0x20, 2)
    


  • Hi Lazar,

    Thanks so much. The command i2c.read(0x18, 4) no longer issues an error and it does read 4 bytes from my sensor. I am still having trouble with it, though. Not sure if you or anyone can help with this, but here goes: I am trying to access an Adafruit MPRLS pressure sensor. It works fine with an Arduino voltage-shifted to 3V with a Quiic shield. But not through the Quiic expansion header on the Omega2. A read command is [0xAA, 0x00, 0x00]. The two code snippet are here: Arduino:

    byte raw[3];
    Wire.beginTransmission(0x18);
    Wire.write(0xAA); // command to read pressure
    Wire.write((byte)0x0);
    Wire.write((byte)0x0);
    Wire.endTransmission();
    
    delay(10);
    
    Wire.requestFrom(0x18, 4);
    uint8_t stat = Wire.read();
    

    // Serial.println("Reading");

    raw[0] = Wire.read();
    raw[1] = Wire.read();
    raw[2] = Wire.read();

    That works fine and gives appropirate pressure reading in a 24-bit word in raw[0] thru raw[2].

    The Python code on the Onion is supposed to be equivalent:

    try:
    	i2c.write(0x18, bytes)
    except:
    	print "write failed 1"
    '''
    i2c.write(0x18, [0xAA])
    time.sleep(0.01)
    i2c.write(0x18, [0])
    time.sleep(0.01)
    i2c.write(0x18, [0])
    '''
    time.sleep(0.01)
    
    '''
    y0 = i2c.read(0x18, 1)
    print y0
    

    i2c.write(0x18, bytes)

    time.sleep(0.01)
    '''
    

    time.sleep(0.005)

    y0 = i2c.read(0x18,4)
    print y0
    

    i2c.write(0x18, bytes)

    time.sleep(0.05)



  • I hadn't finished and it submitted somehow.
    The Python code is:

    bytes = [0xAA, 0, 0]
    
    try:
    	i2c.write(0x18, bytes)
    except:
    	print "write failed"
    
     time.sleep(0.01)
    
     y0 = i2c.read(0x18,4)
     print y0
    

    This returns a status byte, but zeros for the pressure data. The i2c waveforms which I captured from an oscilloscope look different enough to matter. Can I upload them here somehow?

    The command bytes to read the pressure [0xAA, 0x00, 0x00} for Arduino and Onion:

    474431ce-b86b-47b2-a931-6682e2152d84-image.png

    And the two responses showing that the sensor only returns zeros on the Onion

    9dd17c19-1c7b-419b-a0eb-1ab3cab6fb44-image.png

    The oscilloscope interprets all of the i2c bus traffic correctly, but it appears that the sensoe is never getting triggered by the [0xAA...] command to start digitizing. So it only sends back zeros. Does anybody know why the i2c waveforms are different and how to make the Onion i2c library behave as the Arduino does which works properly. I am not having any trouble with other i2c communication from the Onion, only this sensor.

    Thanks to anyone who is up on this.

    Stay safe!

                        Y.


Looks like your connection to Community was lost, please wait while we try to reconnect.