Thread: Writing to Devantech digital compass over I2C

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    117

    Writing to Devantech digital compass over I2C

    I am trying to interface with a Devantech digital compass found here -

    Devantech Compass

    I am using a i2c-usb converter to plug it into my laptop -

    USB-I2C Communications Module

    First of all, I do not know much about electrical engineering. I have a good idea of the bare basics, but after that I get lost.

    I am trying to follow this tutorial -

    https://xgoat.com/wp/2007/11/11/usin...pace-in-linux/

    The problem is that I cannot write to the device.

    The code right now is -

    Code:
    #define ADDRESS 0x55
    int fd = open("/dev/i2c-0", O_RDWR);
    
    if (fd < 0) {
        printf("\n<0, %m", errno);
        return -1;
    }
    
    if( ioctl( fd, I2C_SLAVE, ADDRESS ) < 0 ) {
        fprintf( stderr, "Failed to set slave address: %m\n" );
        return 2;
    }
    
    if( i2c_smbus_write_byte( fd, 0xAA ) < 0 )
        fprintf( stderr, "Failed to write 0xAA to I2C device: %m\n" );
    Whenever I run the code, it just returns
    "Failed to write 0xAA to I2C device: No such device or address"

    I just have the compass connected to the usb converter, which is connected to my pc using Debian.

    I had the address at 0xC0 at first, but that would not work. I used that because in the compass manual it says the module address is 0xC0. I changed it 0x55 because on the converter website, there is a box with commands and I thought 0x55 fit best. I'm not sure if that is correct or not, but it got me past the first step of setting the address. If I'm doing that wrong, please let me know.

    I didn't choose 0xAA for any specific reason - I am just trying to write anything.

    I don't understand why there is no device found. Is it something to do with the address being set wrong? If anyone has any ideas, I would be very grateful.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well according to this -> i2c_smbus_write_byte
    The first parmeter is NOT a file descriptor.

    Further, since this is documented on kernel.org, it would seem this is a kernel-space function, not a user-space function.

    Since it appears to be expecting a pointer, did you get any warning messages when you tried to pass just an integer to it? That should have been a dead giveaway.

    As you're in user space, perhaps you should do
    unsigned char value = 0xAA;
    write( fd, &value, 1 );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    117
    That didn't work - same error message. Also, I got no warnings about a pointer. What I don't understand is why I am opening and sending /dev/i2c-0 instead of /dev/ttyUSB0 whenever it is connected through USB. But whenever I change it to open ttyUSB0, it won't set the slave address.
    Last edited by SterlingM; 11-16-2011 at 03:26 PM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    First you should be reading and writing to the USB port where your USB-I2C Communications Module is connected. You will not need the ioctl calls or be able to follow the tutorial you posted, as they are using an I2C bus on a PC motherboard. You will probably want to get the datasheet for your USB-I2C Communications Module and the documentation for your sensor: Devantech Compass. You will need to construct the proper command to send to your sensor and then send this command to your sensor through the USB port. You will then read the data through this same USB port.

    Jim

  5. #5
    Registered User
    Join Date
    Oct 2009
    Posts
    117
    Okay thanks, that was very useful. I found on the USB-I2C Communications Module link a string of bytes that is supposed to read from the compass. If you want to look at it, its about 40% down on the page under "Reading from I2C devices with a 1 byte internal address register". However, the program still gets stuck when I try to read. My code looks like this now -

    Code:
    //55 for command to read for 1 byte addressed devices
        //C1 for device i2c addr with r/w bit high
        //bearing register
        //number to read
        unsigned char cmd[4] = {0x55, 0xC1, 0x02, 0x02};
        unsigned char receive[2];
    
        int num_sent;
        int num_read;
        while(1) {
    
            num_sent = write(fd, cmd, 4);
            if(num_sent < 0) {
                printf("\nError sending: %m", errno);
                exit(1);
            }
    
            printf("\nbefore read, num_sent: %i\n", num_sent);
    
            num_read = read(fd, receive, sizeof(unsigned char)*2);
            printf("\n%i %i\n", (int)receive[0], (int)receive[1]);
        }
    It appears to send the command okay...num_sent is always 4. But it can't read anything...it just hangs even when I tell it to only read one byte. It says -
    "The USB-I2C will perform the read operation on the I2C bus and send two bytes back to the PC - high byte first. The PC should wait for both bytes to be returned (timing out after 500mS) before proceeding with the next transaction."

    So it happens as soon as I write? I feel like this a dumb question, but is there another way to get the bytes sent back without calling read? Also, 500 milliseconds seems like a really fast timeout time...maybe it times out before I can read it? The link also says that "The USB-I2C module takes care of all the I2C bus requirements such as start/restart/stop sequencing and handles the acknowledge cycles". Is there a way to check that this is actually happening?

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    You need to show how you have opened and configured the USB port. You must also state which driver you are trying to use, D2XX Direct drivers or the VCP driver and what operating system you are using. You will need to configure the serial port before you can use it to communicate with your device.

    Jim

  7. #7
    Registered User
    Join Date
    Oct 2009
    Posts
    117
    Okay I am able to read from it. The main problem was that I had not loaded the driver's module. Thanks for the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 02-21-2009, 03:12 PM
  2. Digital art
    By Carlos in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 07-31-2003, 05:32 AM
  3. What do you think of this digital clock?
    By Shadow in forum C Programming
    Replies: 4
    Last Post: 05-08-2002, 07:56 PM
  4. A "Compass" for text RPG
    By cpp4ever in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2001, 10:40 AM
  5. A "Compass" for text RPG
    By cpp4ever in forum Game Programming
    Replies: 5
    Last Post: 11-29-2001, 10:05 AM