Help... Very frustrated with MinIMU / LSM303 from Pololu

Has anybody got any experience of the LSM303 3-axis accelerometer and 3-axis magnetometer?

I’m getting nowhere with this, partly this is my own fault since this is my first time trying to use I2C.

Here’s a subset of my code so far:


public enum WriteAction { AccWrite, MagWrite }
public enum ReadAction { AccRead, MagRead }

I2CDevice.Configuration ConfAccWrite = new I2CDevice.Configuration(0x30, 400);
I2CDevice.Configuration ConfAccRead = new I2CDevice.Configuration(0x31, 400);
I2CDevice.Configuration ConfMagWrite = new I2CDevice.Configuration(0x3C, 400);
I2CDevice.Configuration ConfMagRead = new I2CDevice.Configuration(0x3D, 400);

//Setup the device with a default config, we'll set this later
I2CDevice Device = new I2CDevice(new I2CDevice.Configuration(0x30, 400));

  public void Write(WriteAction Action, byte register, byte value)
        {
            if (Action == WriteAction.AccWrite) { Device.Config = ConfAccWrite; }
            else if (Action == WriteAction.MagWrite) { Device.Config = ConfMagWrite; }

            I2CDevice.I2CTransaction[] Transactions = new I2CDevice.I2CTransaction[2];

            Transactions[0] = I2CDevice.CreateWriteTransaction(new byte[] { register });
            Transactions[1] = I2CDevice.CreateWriteTransaction(new byte[] { value });

            if (Device.Execute(Transactions, 1000) == 0) { new Exception("Failed to exec WriteMag"); }
        }


        public byte[] Read(ReadAction Action, byte register)
        {
            byte[] ReturnedArray = new byte[7];

            if (Action == ReadAction.AccRead) { Device.Config = ConfAccRead; }
            else if (Action == ReadAction.MagRead) { Device.Config = ConfMagRead; }

            I2CDevice.I2CTransaction[] Transactions = new I2CDevice.I2CTransaction[2];

            Transactions[0] = I2CDevice.CreateReadTransaction(new byte[] { register });
            Transactions[1] = I2CDevice.CreateReadTransaction(ReturnedArray);

            if (Device.Execute(Transactions, 1000) == 0) { new Exception("Failed to exec ReadMag"); }

            return ReturnedArray;
        }


  //INITIALISE HERE
        public LSM303()
        {

 // Turns on the LSM303's accelerometer and magnetometers and places them in normal mode.
             
  // Enable Accelerometer
            // 0x27 = 0b00100111
            // Normal power mode, all axes enabled
            Write(WriteAction.AccWrite, LSM303_CTRL_REG1_A, 0x27); //turn on Acc, normal power, 100hz, all axis enabled

            // Enable Magnetometer
            // 0x00 = 0b00000000
            // Continuous conversion mode
            Write(WriteAction.MagWrite, LSM303_MR_REG_M, 0x00);


        byte[] returnedval;
        returnedval = Read(ReadAction.MagRead, LSM303_OUT_X_L_M);

        Debug.Print(returnedval[0].ToString() + returnedval[1].ToString() + returnedval[2].ToString() + returnedval[3].ToString() + returnedval[4].ToString() + returnedval[5].ToString() + returnedval[6].ToString());

        }

I get nothing back… (zero for all the byte in the array).

For reading data, the documentation for the hardware says you have to send a:

ST - Start command which it describes thus:

“The transaction on the bus is started through a START (ST) signal. A START condition is
defined as a HIGH to LOW transition on the data line while the SCL line is held HIGH.”

I don’t understand what this means…“a HIGH to LOW transition on the data line while the SCL line is held HIGH”???

After this it gets simpler and says I should send:

SAD - The slave address (7bit address with a write or read bit making up the 8th bit)

SAK - The device should then send back an acknowledgement

SUB - Then I should send a sub address (address relating to the register on the device to read from)

SAK - The device should then send back another acknowledgement

SR - I should then send back another start command… again, I don’t get how to do this (see above).

Anybody got any ideas? I’m really frustrated, it must be easy… so I’m feeling a bit dim at the moment.

This is the device: http://www.hobbytronics.co.uk/minimu-9?keyword=imu

Thanks to everyone in advance!

Tim

your addresses are WRONG.

read the “7-bit vs 8-bit” text in the I2C tutorial http://wiki.tinyclr.com/index.php?title=I2C_-_EEPROM

You only ever create your configuration for the DEVICE not for the read and write addresses. So in your case you have two too many configurations.

Ok, thanks for that, i’ll go and investigate as you suggest. It’s a steep old learning curve, thank goodness for helpful forum people!

Hi,

I [italic]think[/italic] I’m making progress, but now I’m struggling to actually set the sub address and for it to stick… I’m going to need to throw this open to the floor again, sorry guys!

As I understand it, the LSM303 has the main i2c device address, and then you need to call the sub address that you want to read/write, and then either send it data or read data. I think I am doing this (setting the value to 00101111), but fundamentally it doesn’t seem to stick. I set the value, then read the address back in and it has remained at it’s default value (00000111):

Any Ideas??? Here is my code so far:


        const byte LSM303_CTRL_REG1_A = 0x20;
        const byte LSM303_STATUS_REG_A = 0x27;

        //create I2C Device object
        static I2CDevice.Configuration confAcc = new I2CDevice.Configuration(0x18, 100); //0x18
        static I2CDevice IMU = new I2CDevice(confAcc);

        // Turns on the LSM303's accelerometer and magnetometers and places them in normal mode.
        public void enableDefault()
        {
            //create transactions (We need 2, one is the sub address, one is the value we send to it to turn on the device)
            I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];

            // Enable Accelerometer: Call sub register LSM303_CTRL_REG1_A = 0x20 
            byte[] RegisterNum = new byte[1] { LSM303_CTRL_REG1_A };    // SUB ADDRESS - DEFAULTS TO 00000111 = 7
            xActions[0] = I2CDevice.CreateWriteTransaction(RegisterNum);

            //SEND NEW MODE VALUE = 0x2F = 00101111 = Normal power mode, all axes enabled
            byte[] SendData = new byte[1] { 0x2F };                     
            xActions[1] = I2CDevice.CreateWriteTransaction(SendData);

            //REITTERATE THIS IS ACCELEROMETER CONFIG
            IMU.Config = confAcc;

            //EXECUTE TRANSACTION
            if (IMU.Execute(xActions, 1000) == 0)
            {
                Debug.Print("Failed to perform Acc I2C transaction");
            }
            else
            {
                Debug.Print("Execute Acc completed within 1 second limit");
            }
        }

        public byte[] ReadVal(byte RegisterNum)
        {
            I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];

            byte[] RegisterArray = new byte[1] { RegisterNum };
            xActions[0] = I2CDevice.CreateWriteTransaction(RegisterArray);

            byte[] ReturnedByte = new byte[1];
            xActions[1] = I2CDevice.CreateReadTransaction(ReturnedByte);

            IMU.Config = confAcc;

            if (IMU.Execute(xActions, 1000) == 0)
            {
                Debug.Print("Failed to perform ACC I2C transaction");
            }
           
            return ReturnedByte;
        }


        //INITIALISE HERE
        public LSM303()
        {
            enableDefault();

            byte[] RetVal;
            RetVal = ReadVal(LSM303_CTRL_REG1_A);
            Debug.Print("Read Reg A: " + RetVal[0].ToString());

            RetVal = ReadVal(LSM303_STATUS_REG_A);
            Debug.Print("Read Status  A: " + RetVal[0].ToString());
        }

The values returned to the debug window are this:
Execute Acc completed within 1 second limit
Read Reg A: 7

So 7 is the default, meaning I’ve not managed to set anything.

Thanks again in advance!
Tim

step 1.
linearise your code. Get rid of these subroutines until you can show you are or are not working. Too hard to go through your code as-is and expect to understand it; it also isn’t the complete code, and a simple linear example will make it easy to see the complete picture.

Ok, sorry about that, personally I find it easier to break things in to blocks, however, you’re absolutely right, people trying to help don’t want to have to have to crawl over code to see what I’m doing :). So, here is the same code but streamlined as requested. I’ve cut out reading the second register for simplicity:


using System;
using System.IO;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace imu
{
    public class Program
    {
        public static void Main()
        {
            //SET UP SOME COMMON STUFF TO USE IN A MOMENT
            I2CDevice.Configuration confAcc = new I2CDevice.Configuration(0x18, 100); 
            I2CDevice IMU = new I2CDevice(confAcc);        
            I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];

            /////////////////////////////////////////////////////
            // THE ACCELEROMETER IS OFF BY DEFAULT. WE NEED TO //
            // SEND IT A "MODE" IN ORDER FOR IT TO INITIALISE  //
            /////////////////////////////////////////////////////

            // ENABLE Accelerometer: 
            // Call sub address = 0x20 (DEFAULTS TO 00000111)
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[1] {0x20});

            // SEND NEW MODE VALUE = 0x2F = 00101111 = Normal power mode, all axes enabled
            xActions[1] = I2CDevice.CreateWriteTransaction( new byte[1] {0x2F});

            // EXECUTE TRANSACTION
            if (IMU.Execute(xActions, 1000) == 0)
            {
                Debug.Print("Failed to perform Acc I2C transaction");
            }
            else
            {
                Debug.Print("Execute Acc completed within 1 second limit");
            }


            //READ BACK THE SAME REGISTER TO SEE IF THE MODE GOT SET

            byte[] ReturnedByte = new byte[1];

            // READING FROM SUB ADDRESS = 0x20 AS ABOVE (DEFAULTS TO 00000111)            
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[1] {0x20});
            xActions[1] = I2CDevice.CreateReadTransaction(ReturnedByte);  //<--- READ TRANSACTION THIS TIME

            if (IMU.Execute(xActions, 1000) == 0)
            {
                Debug.Print("Failed to perform ACC I2C transaction");
            }
            else
            {
                Debug.Print("Read Reg A: " + ReturnedByte[0].ToString());
            }

            Thread.Sleep(5000);
        }
    }
}


The values returned to the debug window are still this:


Execute Acc completed within 1 second limit
Read Reg A: 7

Thanks
Tim

yes, for testing purposes that makes much more sense.The rule of simplicity for testing should be looked at first - once you get the fundamentals working feel free to rearrange as you like :slight_smile:

Can you confirm what you have done with SA0_G and SA0_A? Pulled high, low, or unconnected?

Untested code warning… I haven’t tried compiling this and I don’t have this device to test with anyhow. But here’s what I would try instead. One write transaction with the two bytes, not two write transactions.

           I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[1];
           // ENABLE Accelerometer: 
            // Call sub address = 0x20 (DEFAULTS TO 00000111)
            // SEND NEW MODE VALUE = 0x2F = 00101111 = Normal power mode, all axes enabled
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[] {0x20,0x2F});

Then you’re going to need a two-transaction xActions object for your read.

I’d also try reading the WHO_AM_I register 0x0f to prove that you’re talking to the device (although the 7 redurned is pretty good evidence already but you never can have too many pieces of evidence :slight_smile: )

The suggestion of passing the two bytes in one CreateWriteTransaction, rather than two CreateWriteTransactions in one I2CTransaction worked! Thanks so much Brett!

I have to confess I don’t really know for sure how that was different to two writes (except for the fact that your method worked). I now get 47 returned (00101111) which is what I sent in the first place. [italic]Maybe [/italic]this is the NETMF framework sending start and complete commands around each of my two writes which was confusing things? The documentation says you only need an acknowledgement between call to the sub register and sending it data.

Anyway, time to go check out some actual dynamic data from this thing.

For completeness, and in case anybody else comes along behind me and reads this, SA0_G and SA0_A were both left unconnected (so default settings).

And again, just in case anybody else is struggling with the basics and is reading this, here’s my test code after Brett’s input:


public static void Main()
        {
            //SET UP SOME COMMON STUFF TO USE IN A MOMENT
            I2CDevice.Configuration confAcc = new I2CDevice.Configuration(0x18, 100); //0x18
            I2CDevice IMU = new I2CDevice(confAcc);
            
            /////////////////////////////////////////////////////
            // THE ACCELEROMETER IS OFF BY DEFAULT. WE NEED TO //
            // SEND IT A "MODE" IN ORDER FOR IT TO INITIALISE  //
            /////////////////////////////////////////////////////

            // ENABLE Accelerometer: 
            // Call sub address = 0x20 (DEFAULTS TO 00000111)
            I2CDevice.I2CTransaction[] WriteTransaction = new I2CDevice.I2CTransaction[1];
            WriteTransaction[0] = I2CDevice.CreateWriteTransaction(new byte[] { 0x20, 0x2f });

            // EXECUTE TRANSACTION
            if (IMU.Execute(WriteTransaction, 1000) == 0)
            {
                Debug.Print("Failed to perform Acc I2C transaction");
            }
            else
            {
                Debug.Print("Execute Acc completed within 1 second limit");
            }


            //READ BACK THE SAME REGISTER TO SEE IF THE MODE GOT SET
            I2CDevice.I2CTransaction[] ReadTransaction = new I2CDevice.I2CTransaction[2];
            byte[] ReturnedByte = new byte[1];

            // READING FROM SUB ADDRESS = 0x20 AS ABOVE (DEFAULTS TO 00000111)            
            ReadTransaction[0] = I2CDevice.CreateWriteTransaction(new byte[1] { 0x20 }); // <--WHAT REGISTER TO READ FROM
            ReadTransaction[1] = I2CDevice.CreateReadTransaction(ReturnedByte);  //<--- READ TRANSACTION TO BYTE ARRAY

            if (IMU.Execute(ReadTransaction, 1000) == 0)
            {
                Debug.Print("Failed to perform ACC I2C transaction");
            }
            else
            {
                Debug.Print("Read Reg A: " + ReturnedByte[0].ToString());
            }

            Thread.Sleep(5000); //LAZY ME, PAUSE IT A BIT HERE SO I DONT HAVE TO STEP THE CODE (JUST RUN IT AND READ THE DEUBG WINDOW)
        }

Thanks again Brett.

no problems mate.

The I2C command structure is meant to give the ability to create the write then the read in one pass. I have never put a scope on the I2C command lines but suspect that the timing of the way you originally did the test was not how the chip wanted to react.

I have the same board from Pololu. I was stuck with the exact same problem, until I found this thread.
I can now read and write individual registers without problems, and I have a routine that appears to be reading
the Acc registers. My problem is that the values are all over the place.
I initialize the LSM303 with this


       // Enable Accelerometer
       // 0x27 = 0b00100111
       // Normal power mode, all axes enabled
       writeAccReg(Register.LSM303_CTRL_REG1_A, 0x27);

Then I read the acc with this…



        // Reads the 3 accelerometer channels and stores them in vector a
        public void readAcc()
        {
            MyI2C.Config = Accelerometer; //defined above.. Address is ACC_ADDRESS_SA0_A_LOW = (0x30 >> 1) = 0x18 = 24, Speed is 100kHz
            I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];
            byte[] RegisterValue = new byte[6];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)((byte)Register.LSM303_OUT_X_L_A | (byte)(1 << 7)) }); // LSM303_OUT_X_L_A = 0x28, MSB is set to 1 to enablle out address increment.
            xActions[1] = I2CDevice.CreateReadTransaction(RegisterValue);
            int bytes = MyI2C.Execute(xActions, 1000);
            if ( bytes == 0)
            {
                Debug.Print("Failed to perform I2C readAcc transaction");
                return;
            }

            byte xla = RegisterValue[0];
            byte xha = RegisterValue[1];
            byte yla = RegisterValue[2];
            byte yha = RegisterValue[3];
            byte zla = RegisterValue[4];
            byte zha = RegisterValue[5];
            Debug.Print("Register 0:" + RegisterValue[0] + " Register 1:" + RegisterValue[1] + " Register 2:" + RegisterValue[2] + " Register 3:" + RegisterValue[3] + " Register 4:" + RegisterValue[4] + " Register 5:" + RegisterValue[5]);

            a.x = (float)((xha << 8 | xla) >> 4);
            a.y = (float)((yha << 8 | yla) >> 4);
            a.z = (float)((zha << 8 | zla) >> 4);

            pitch = 57.2957795F * MathEx.Atan(a.x / MathEx.Sqrt((a.y*a.y) + (a.z*a.z)));
            roll = 57.2957795F * MathEx.Atan(a.y / MathEx.Sqrt((a.x*a.x) + (a.z*a.z)));
            Debug.Print("raw  a.x=" + a.x.ToString("F4") + ", a.y=" + a.y.ToString("F4") + ", a.z=" + a.z.ToString("F4") + " roll=" + roll.ToString("F4") + " pitch=" + pitch.ToString("F4"));
            vector_normalize(ref a);
            pitch = 57.2957795F * MathEx.Atan(a.x / MathEx.Sqrt((a.y * a.y) + (a.z * a.z)));
            roll = 57.2957795F * MathEx.Atan(a.y / MathEx.Sqrt((a.x * a.x) + (a.z * a.z)));
            Debug.Print("norm a.x=" + a.x.ToString("F4") + ", a.y=" + a.y.ToString("F4") + ", a.z=" + a.z.ToString("F4") + " roll=" + roll.ToString("F4") + " pitch=" + pitch.ToString("F4"));
            Debug.Print("");
        } 

Sample Output:


Register 0:255 Register 1:0 Register 2:255 Register 3:192 Register 4:195 Register 5:112
raw  a.x=15.0000, a.y=3087.0000, a.z=1804.0000 roll=59.6977 pitch=0.2404
norm a.x=0.0042, a.y=0.8634, a.z=0.5045 roll=59.6977 pitch=0.2404

Register 0:255 Register 1:32 Register 2:255 Register 3:192 Register 4:194 Register 5:32
raw  a.x=527.0000, a.y=3087.0000, a.z=524.0000 roll=76.4640 pitch=9.5538
norm a.x=0.1660, a.y=0.9722, a.z=0.1650 roll=76.4640 pitch=9.5538

Register 0:255 Register 1:32 Register 2:255 Register 3:240 Register 4:194 Register 5:48
raw  a.x=527.0000, a.y=3855.0000, a.z=780.0000 roll=76.2776 pitch=7.6316
norm a.x=0.1328, a.y=0.9715, a.z=0.1966 roll=76.2776 pitch=7.6316

Register 0:255 Register 1:192 Register 2:0 Register 3:208 Register 4:195 Register 5:32
raw  a.x=3087.0000, a.y=3328.0000, a.z=524.0000 roll=46.7455 pitch=42.4989
norm a.x=0.6756, a.y=0.7283, a.z=0.1147 roll=46.7455 pitch=42.4989

Register 0:255 Register 1:16 Register 2:255 Register 3:16 Register 4:194 Register 5:144
raw  a.x=271.0000, a.y=271.0000, a.z=2316.0000 roll=6.6291 pitch=6.6291
norm a.x=0.1154, a.y=0.1154, a.z=0.9866 roll=6.6291 pitch=6.6291

Register 0:255 Register 1:240 Register 2:0 Register 3:0 Register 4:194 Register 5:160
raw  a.x=3855.0000, a.y=0.0000, a.z=2572.0000 roll=0.0000 pitch=56.2894
norm a.x=0.8319, a.y=0.0000, a.z=0.5550 roll=0.0000 pitch=56.2894

Register 0:255 Register 1:192 Register 2:255 Register 3:208 Register 4:193 Register 5:176
raw  a.x=3087.0000, a.y=3343.0000, a.z=2828.0000 roll=38.6077 pitch=35.1838
norm a.x=0.5762, a.y=0.6240, a.z=0.5279 roll=38.6077 pitch=35.1838 

Has anybody else figured out how to read numbers properly and calculate pitch roll and heading values?

You appear to be reading radians from your Acc??? or am i missing where you are converting the output from your Acc to mG’s?

OK… I’ll plead ignorance here… :-[ You are probably right, the output is in Gs… How do I go about converting that to something more useful?
My code is basically a C# /.NETMF port of this: GitHub - pololu/lsm303-arduino: Arduino library for Pololu LSM303 boards
I just can’t seem to get any stable data out… Even if I did the conversion wrong, I don’t understand why the raw register bytes are all over the place if the board is not moving. The Magnetometer is giving me similar results… It’s almost like I’m reading random numbers.

To obtain your pitch and roll, your equation appears to be normalizing the raw data and then uses it as radians, I guess making the value <=1 works with Atan, I am not sure if the method is valid but is intresting. I must admit I didnt see that at first glance. Anyway its 3:54 am where I live and I need to sleep. If somebody else does not help you I will have a look later. I guess you have checked all the info above. Your output is not in G’s it has to be converted, by multiplying by the LSB gain, which for this device I dont know, and with the method used in my comment you may not need to use.

I ended up walking away from this board, accepting that i’m not smart enough to figure out the random/bouncy output. My lesson was to only buy hardware for which i could find a full worked example to prove it was useable and which i could rip off if i get stuck. From what you’re saying your board is behaving the same as mine, so at least you know you dont have a dud.

my second lesson was ‘buy cheap buy twice’ having come to some personal conclusions why this board is so much cheaper than others.

I’m sure someone out there can get it working, they’d not be selling them othetwise, but for me ebay and a £10 loss was the solution.

I was about to walk away too… But… I’m stubborn and I saw some video on YouTube that prove the board works… There has to be a way to get this to work in .NETMF.
I find debugging in .NETMF a bit more annoying than it should be, because of the lack of formatting/conversion for the .ToString method. I’ll get it figured out. :slight_smile: (I hope)…

Progress… The whole problem was related to getting the 2’s comeplement from the accelerometer registers converted into a float for the calculations… The sign bit got lost… with all that bit shifting and conversion from bytes to float things got messed up…
Here is the working code… roll and pitch angles are in degrees, and appear accurate to about +/- 1 deg.


        // Reads the 3 accelerometer channels and stores them in vector a
        public void readAcc()
        {
            MyI2C.Config = Accelerometer; //defined above.. Address is ACC_ADDRESS_SA0_A_LOW = (0x30 >> 1) = 0x18 = 24, Speed is 100kHz
            I2CDevice.I2CTransaction[] xActions = new I2CDevice.I2CTransaction[2];
            byte[] RegisterValue = new byte[6];
            xActions[0] = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)((byte)Register.LSM303_OUT_X_L_A | (byte)(1 << 7)) }); // LSM303_OUT_X_L_A = 0x28, MSB is set to 1 to enablle out address increment.
            xActions[1] = I2CDevice.CreateReadTransaction(RegisterValue);
            int bytes = MyI2C.Execute(xActions, 1);
            if ( bytes < 7)
            {
                Debug.Print("Failed to perform I2C readAcc transaction");
                return;
            }

            byte xla = RegisterValue[0];
            byte xha = RegisterValue[1];
            byte yla = RegisterValue[2];
            byte yha = RegisterValue[3];
            byte zla = RegisterValue[4];
            byte zha = RegisterValue[5];

            short xx = (short)((xla << 8) + xha);
            short yy = (short)((yla << 8) + yha);
            short zz = (short)((zla << 8) + zha);
            xx = (short)(xx >> 4);
            yy = (short)(yy >> 4);
            zz = (short)(zz >> 4);
            a.x = xx;
            a.y = yy;
            a.z = zz;

            Debug.Print("xx:" + Converter.ToString(xx, 2) + ", yy:" + Converter.ToString(xx, 2) + ", zz:" + Converter.ToString(xx, 2)); 
            pitch = 57.2957795F * MathEx.Atan(a.x / MathEx.Sqrt((a.y*a.y) + (a.z*a.z)));
            roll = 57.2957795F * MathEx.Atan(a.y / MathEx.Sqrt((a.x*a.x) + (a.z*a.z)));
            Debug.Print("a.x=" + a.x.ToString("F4") + ", a.y=" + a.y.ToString("F4") + ", a.z=" + a.z.ToString("F4") + " roll=" + roll.ToString("F4") + " pitch=" + pitch.ToString("F4"));
        }

The output looks like this, with the board at rest:
xx:(short)(-2) 1111111111111110, yy:(short)(-2) 1111111111111110, zz:(short)(-2) 1111111111111110
a.x=-2.0000, a.y=-9.0000, a.z=-979.0000 roll=-0.5267 pitch=-0.1170
xx:(short)(-15) 1111111111110001, yy:(short)(-15) 1111111111110001, zz:(short)(-15) 1111111111110001
a.x=-15.0000, a.y=-11.0000, a.z=-976.0000 roll=-0.6456 pitch=-0.8804
xx:(short)(-5) 1111111111111011, yy:(short)(-5) 1111111111111011, zz:(short)(-5) 1111111111111011
a.x=-5.0000, a.y=-2.0000, a.z=-1000.0000 roll=-0.1146 pitch=-0.2865
xx:(short)(-5) 1111111111111011, yy:(short)(-5) 1111111111111011, zz:(short)(-5) 1111111111111011
a.x=-5.0000, a.y=-13.0000, a.z=-1004.0000 roll=-0.7418 pitch=-0.2853
xx:(short)(-9) 1111111111110111, yy:(short)(-9) 1111111111110111, zz:(short)(-9) 1111111111110111
a.x=-9.0000, a.y=-2.0000, a.z=-990.0000 roll=-0.1157 pitch=-0.5209
xx:(short)(-6) 1111111111111010, yy:(short)(-6) 1111111111111010, zz:(short)(-6) 1111111111111010
a.x=-6.0000, a.y=-4.0000, a.z=-981.0000 roll=-0.2336 pitch=-0.3504
xx:(short)(-8) 1111111111111000, yy:(short)(-8) 1111111111111000, zz:(short)(-8) 1111111111111000
a.x=-8.0000, a.y=-2.0000, a.z=-998.0000 roll=-0.1148 pitch=-0.4593

The roll and pitch are nice and steady, and the raw numbers look like they are in the proper ranges… Now on to the magnetometer… ;D

I’m attempting to use a similar board from pololu - the MiniIMU9-v2 - hooked up through an Extender on a Cerberus.

The tip on using a single transaction for writing the subaddress AND the data was … well, got me past that one.

One thing I’m seeing that’s perplexing is that for every read request, the I2CBus (gadgeteer ifc) tells me that it reads back one more byte than is in the read buffer.
Is anyone else seeing that, and have an explanation?

Thanks

Ach! No sooner do I send than it occurs to me that I2CBus.WriteRead sums the total bytes transferred - so 1 byte out (subaddress), n bytes in… 1 greater…
sigh…

Does anyone have working code for this board? I am having some major difficulties with 2’s compliment as well. There is very little documentation on converting 2’s compliment to integers in .net.
Thanks,
Tom

Replied to you in the other thread. This one is very old.