Main Site Documentation

ADXL345 Accelorometer via I2C on FEZmini


#1

Hi,
I’m runninginto a wall and not getting any further with my project and I was hoping someone here could assist.

I am trying to read from an ADXL345 triple axis accelorometer board from Cool Component (Sparkfun) via I2C. (I have version 10 board)
http://www.coolcomponents.co.uk/catalog/product_info.php?cPath=36_58&products_id=427
http://www.sparkfun.com/products/9836

On Sparkfun’s website, I’m using the example code written for the Arduino in C and trying to translate this into .Net for the FEZmini.
http://www.sparkfun.com/datasheets/Sensors/Accelerometer/adxl345-i2c.zip

My code is below: The only value I ever get out of x, y znd z is the value I write to the 0x2D register (1 << 3 or 8 in the example code below).

public class ADXL345I2C
    {
        private I2CDevice ADXL345;
        private I2CDevice.I2CTransaction[] xActions;

        byte ADXL345Write = 0xA6; //166
        byte ADXL345Read = 0xA7; //167

        public ADXL345I2C()
        {
            int x;
            int y;
            int z;

            Debug.Print("ADXL345 Example");

            InitialiseADXL345();

            while (true)
            {
                x = ReadADXL345(0x32);
                y = ReadADXL345(0x34);
                z = ReadADXL345(0x36);

                Debug.Print("x=" + x.ToString() + ", y=" + y.ToString() + ", z=" + z.ToString());
                Thread.Sleep(100);
            }
        }

        private int ReadADXL345(byte RegisterAddress)
        {
            xActions = new I2CDevice.I2CTransaction[1];
            byte[] SendBytes = new byte[2] { ADXL345Write, RegisterAddress }; //Read from ADXL345
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            ADXL345.Execute(xActions, 1000);
            
            xActions = new I2CDevice.I2CTransaction[2];
            SendBytes = new byte[1] { ADXL345Read };
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            byte[] ReceiveBytes = new byte[88];
            xActions[1] = I2CDevice.CreateReadTransaction(ReceiveBytes);
            ADXL345.Execute(xActions, 1000);

            return (ReceiveBytes[1] << 8) | ReceiveBytes[0];
        }

        private void InitialiseADXL345()
        {
            I2CDevice.Configuration ADXL345Config = new I2CDevice.Configuration(0x53, 400);
            ADXL345 = new I2CDevice(ADXL345Config);

            xActions = new I2CDevice.I2CTransaction[1];
            byte[] SendByte = new byte[3] { ADXL345Write, 0x2D, (1 << 3) }; //write to ADXL345
            xActions[0] = I2CDevice.CreateWriteTransaction(SendByte);
            ADXL345.Execute(xActions, 1000);
        }
    }

#2

You are reading 88 bytes? Is this correct?


#3

The 88 bytes was a random attempt at getting something more than “8” out of the ADXL345. I think in the example they use 1 byte which is what I use when I get the value back from my post below.


#4

I2C chips usually have “registers” where you write the register number then read the register value, which is one or two bytes. I am not seeing that in your code


#5

Hi,

You are sending the chip address in your message. This is not correct as the lower layers already appends the address.

This code:

byte[] SendBytes = new byte[2] { ADXL345Write, RegisterAddress };

should be this:

byte[] SendBytes = new byte[1] { RegisterAddress };

Also, you can combine transactions.

This code:

xActions = new I2CDevice.I2CTransaction[1];
            byte[] SendBytes = new byte[2] { ADXL345Write, RegisterAddress }; //Read from ADXL345
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            ADXL345.Execute(xActions, 1000);
 
            xActions = new I2CDevice.I2CTransaction[2];
            SendBytes = new byte[1] { ADXL345Read };
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            byte[] ReceiveBytes = new byte[88];
            xActions[1] = I2CDevice.CreateReadTransaction(ReceiveBytes);
            ADXL345.Execute(xActions, 1000);

Should be this:

xActions = new I2CDevice.I2CTransaction[2];
            byte[] SendBytes = new byte[1] { RegisterAddress }; //Read from ADXL345
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            byte[] ReceiveBytes = new byte[88];
            xActions[1] = I2CDevice.CreateReadTransaction(ReceiveBytes);
            ADXL345.Execute(xActions, 1000);

Thanks,
Errol


#6

I have now refined the code to the follow and now just get zero’s back for x, y and z:

public class ADXL345I2C
    {
        private I2CDevice ADXL345;
        private I2CDevice.I2CTransaction[] xActions;

        public ADXL345I2C()
        {
            int x;
            int y;
            int z;

            Debug.Print("ADXL345 Example");

            InitialiseADXL345();

            while (true)
            {
                x = ReadADXL345(0x32);
                y = ReadADXL345(0x34);
                z = ReadADXL345(0x36);

                Debug.Print("x=" + x.ToString() + ", y=" + y.ToString() + ", z=" + z.ToString());
                Thread.Sleep(100);
            }
        }

        private int ReadADXL345(byte RegisterAddress)
        {
            xActions = new I2CDevice.I2CTransaction[2];
            byte[] SendBytes = new byte[1] { RegisterAddress };
            xActions[0] = I2CDevice.CreateWriteTransaction(SendBytes);
            byte[] ReceiveBytes = new byte[2];
            xActions[1] = I2CDevice.CreateReadTransaction(ReceiveBytes);
            int response = ADXL345.Execute(xActions, 1000);

            return (ReceiveBytes[0] << 8) | ReceiveBytes[1];
        }

        private void InitialiseADXL345()
        {
            I2CDevice.Configuration ADXL345Config = new I2CDevice.Configuration(0x53, 400);
            ADXL345 = new I2CDevice(ADXL345Config);

            xActions = new I2CDevice.I2CTransaction[2];
            byte[] SendByte = new byte[1] { 0x2D };
            xActions[0] = I2CDevice.CreateWriteTransaction(SendByte);
            SendByte = new byte[1] { 1 << 3 };
            xActions[1] = I2CDevice.CreateWriteTransaction(SendByte);
            int response = ADXL345.Execute(xActions, 1000);
        }
    }

#7

Getting closer. :slight_smile:

I don’t think the chip is happy with the write that is broken up into two writes.

Switch back to your original InitialiseADXL345 function with only one transaction.

Thanks,
Errol


#8

Excellent. Thanks guys and especially to Errol. I have it working perfectly. See my final code on my site at:
http://sites.google.com/site/gineer/trirot/trirot-progress/adxl345andfezminiviai2c

Now I just need to change this prototype code into something that can run outside the debugger.

I might be back soon since I need to now get my ITG-3200 Gyroscope to talk via the I2C port as well.

Again: Thanks a bunch.

Gineer


#9

Glad I could help.

What I suggest is that you rewrite your code a bit.

Most I2C devices follow the same protocol, they look like an I2C EEPROM.

Thus, if I where you, I would write a class that talks to an EEPROM. They use the following protocol:
Write: (Start)(Chip_Address+W_bit),(Register Address),(Data),(…)(Stop)
Read: (Start)(Chip_Address+W_bit),(Register Address),(Restart),(Chip_Address+R_bit),(Data),(…)(Stop)

This you have now all done with this code. You just need to make it more generic… :slight_smile:

For my I2C drivers I started with an EEPROM class that takes the chip address as part of the inirialiser. When I try to write to the device it first creates the I2CDevice, writes to the device, then destroys the I2CDevice object. All my other I2C drivers use this class.

BTW, you can only have one I2CDevice created at any time as it locks the I2C bus… :slight_smile:

Thanks,
Errol


#10

Hi Errol,
Thanks for that, You actually warned me about the fact that I can not open I2C channels to both devices at the same time just before I was about to try it.

I’ve created initialisation methods to reset the hardware etc, rather than performing this sequence in the Constructor of the class.

I also implimented IDisposable, and everything seems to work fine now.

Now I just need to make sence of all this data I get back from The accelorometer and the Gyroscope.

See http://sites.google.com/site/gineer/trirot

Thanks again.
Gineer