What's wrong with my I2C code?



  • I hacked together some I2C code based on some things I found on the Interweb. I keep getting I2C read errors despite the fact I can see the I2C device with i2ctools.

    root@Omega-1041:/# ./i2c 
    HTU21D Test
    error reading i2c device
    : No such device or address
    error reading i2c device
    : No such device or address
    eror reading i2c device
    : No such device or address
    eror reading i2c device
    : No such device or address
    Temperature 0x66 0xfc 0x6c\nHumidity 0x3f 0xfc 0x6c
    

    But the values that are returned for temperature seem legit. Anyone got any ideas where I'm going wrong here?

    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <linux/i2c-dev.h>
    
    
    int main( int argc, char **argv )
    {
            int i;
            int r;
            int fd;
            unsigned char command[2];
            unsigned char value[3];
            useconds_t delay = 5000;
    
            char *dev = "/dev/i2c-0";
            int addr = 0x40;
    
            printf("HTU21D Test\n");
    
            fd = open(dev, O_RDWR );
            if(fd < 0)
            {
                    perror("Opening i2c device node\n");
                    return 1;
            }
    
            r = ioctl(fd, I2C_SLAVE, addr);
            if(r < 0)
            {
                    perror("Selecting i2c device\n");
            }
    
    
            command[0] = 0xe3;
            r = write(fd, &command, 1);
    
            if(r != 1)
            {
                    perror("error writing to i2c device\n");
            }
            usleep(delay);
    
                    for(i = 0; i < 3; i++)
                    {
                           
                            // the read is always one step behind the selected input
                            r = read(fd, &value[i], 1);
                            if(r != 1)
                            {
                                    perror("error reading i2c device\n");
                            }
                            usleep(delay);
                    }
                    printf("Temperature 0x%02x 0x%02x 0x%02x\\n", value[0], value[1], value[2]);
    
                    usleep(delay);
    
    
            command[0] = 0xe5;
            r = write(fd, &command, 1);
            usleep(delay);
    
                    for(i = 0; i < 3; i++)
                    {
                            // the read is always one step behind the selected input
                            r = read(fd, &value[i], 1);
                            if(r != 1)
                            {
                                    perror("eror reading i2c device\n");
                            }
                            usleep(delay);
                    }
                    printf("Humidity 0x%02x 0x%02x 0x%02x\n", value[0], value[1], value[2]);
            
    
            close(fd);
            return(0);
    }
    


  • I busted out the logic analyzer and see the address (0x80 for write) and the byte (0xf3) for start conversion both get an ACK.

    Reads get a NAK, however.



  • @Marc-Nicholas Did you run HTU21d?



  • @Przemyslaw-Downar I did. Although it doesn't seem 100% reliable on the Onion.



  • @Marc-Nicholas said in What's wrong with my I2C code?:

    I busted out the logic analyzer and see the address (0x80 for write) and the byte (0xf3) for start conversion both get an ACK.

    Reads get a NAK, however.

    Is the direction bit being correctly set for a read, ie is 0x81 going down the wire?

    Does the peripheral attempt to clock stretch?



  • May not have anything to do with your problem but I noticed this: unsigned char command[2]; but later you only set the first command byte: command[0] = 0xe3;

    Just thought I would point it out in case it helps.



  • @Doug-Petican said in What's wrong with my I2C code?:

    May not have anything to do with your problem but I noticed this: unsigned char command[2]; but later you only set the first command byte: command[0] = 0xe3;

    Not an issue. The only use of that array is write() calls with a count of 1.


Log in to reply
 

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