MinIMU-9 accelerometer horizontal readings

Hi all,

I have a MinIMU-9 and I’m trying to understand what I need to do with regards to offsets for the accelerometer.

When any of the Axis are pointed up (or down), the reading is close to 1g, as you would expect. However, when an Axis is horizontal, the reading is ~4g when I would have thought it would be around 0. When I take these readings the board is stationary.

According to the documentation, the zero-g level offset is supposed to be factory calibrated so I thought what that meant was that I don’t have to perform a calibration routine myself.

Does anyone have any ideas?

thanks

Hello.

As you said, it is factory calibrated and seeing 4g is unexpected.

How are you communicating with the MinIMU-9? How are you calculating the 4g value? Can you post your code?

- Ryan

Hi Ryan,

Previously, when I was getting ~4g at horizontal, I was holding the board horizontal with an alligator clip on one corner, while on the other side, I had four female jumper wires attached to the header pins. When I inserted the header pins into a breadboard instead, I could get a reading of ~0 for horizontal. Do you think that the way it was being held could have caused the problem?

I’ve got another question now though. If I point an axis up (arrow up), then I get ~1g. If I point it down (arrow down), I get ~3g. That’s still a difference of 2g which is the same difference as for +1 and -1g but does it make any sense for it to be 3g?

thanks

The results you are reporting are unexpected. It does not make sense for it to be 3g when the axis is pointed downward. It sounds like something is wrong with your code. If you post it, we might be able to notice something.

- Ryan

Hi Ryan,

Sorry for the delay, computer hardware failure. I’m using c# (netduino) but I don’t imagine the relevant code looks much different:

        private class Register
        {
            public const byte CTRL_REG1_A = 0x20;
            public const byte CTRL_REG4_A = 0x23;
            public const byte OUT_X_L_A = 0x28;
            public const byte OUT_X_H_A = 0x29;
            public const byte OUT_Y_L_A = 0x2a;
            public const byte OUT_Y_H_A = 0x2b;
            public const byte OUT_Z_L_A = 0x2c;
            public const byte OUT_Z_H_A = 0x2d;
        }

        protected byte Read(byte address)
        {
            Byte[] data = new Byte[1];
            I2CDevice.I2CWriteTransaction write = I2CDevice.CreateWriteTransaction(new Byte[] { address });
            I2CDevice.I2CReadTransaction read = I2CDevice.CreateReadTransaction(data);
            I2CDevice.I2CTransaction[] readTransaction = new I2CDevice.I2CTransaction[] { write, read };

            var result = I2CBus.Execute(Config, readTransaction, 1000);

            return data[0];
        }

        private double GetAccelerationInGs(byte high, byte low)
        {
            // 12 bit - left justified

            var data = (Int16)(((Read(high) << 8) | Read(low)) >> 4);

            return (((double)(data)) / _scale);
        }

        public double GetX()
        {
            return GetAccelerationInGs(Register.OUT_X_H_A, Register.OUT_X_L_A);
        }

        public double GetY()
        {
            return GetAccelerationInGs(Register.OUT_Y_H_A, Register.OUT_Y_L_A);
        }

        public double GetZ()
        {
            return GetAccelerationInGs(Register.OUT_Z_H_A, Register.OUT_Z_L_A);
        }

where _scale = 1000

The thing is, if the code is wrong then it’s weird that it can read 0 and 1g correctly.

thanks

Sorry for the delay. A couple of us looked at your code and don’t see anything wrong with it. But it is not your complete code so we can’t be so sure about your whole program. For example, you don’t have the code for turning on the accelerometer here. Could you post all of the code of the simplest program that does not do what you expect it to? Also, what processor are you using?

- Ryan

Hi Ryan,

I have attached a zip of a minimal project.

I tested it with the x axis and the results are the same as for the full project:

  • at horizontal it reads ~0
  • arrow pointing up it reads ~1
  • arrow pointing down it reads ~3

Thanks for your help
AccelerometerTest.zip (3.94 KB)

Sorry, forgot to include that the processor is an Atmel 32bit ARM7:

atmel.com/dyn/resources/prod … /6120s.pdf

thanks

Hi,

Thanks for posting a minimal example. It’s very helpful! I noticed your clock speed is set to 400kHz. Can you try reducing it to something like 100kHz, to see if that helps? Another thing to try would be to insert the literal values for the bytes you expect to receive and verify that your program’s math works correctly for negative numbers. Also, can you try decreasing your sensitivity, to see if that helps?

- Ryan

Hi Ryan,

I changed the speed from 400kHz to 100kHz and that didn’t seem to do anything.

Changing the sensitivity seems to create more questions than answers but maybe you might know what’s happening.

        // 0x20 = 00100000 (+/- 4g)
        Write(Register.CTRL_REG4_A, 0x20);

or

        // 0x30 = 00110000 (+/- 8g)
        Write(Register.CTRL_REG4_A, 0x30);

where CTRL_REG4_A = 0x23

When I change the sensitivity to ±4g (2mg/digit):

Pointed up: ~250 => 250 * 2 / 1000 = 0.5g
Pointed down: ~3800 => 3800 * 2 / 1000 = 7g

When I change the sensitivity to ±8g (3.9mg/digit):

Pointed up: ~250 => 250 * 3.9 / 1000 = ~1g
Pointed down: ~3800 => 3800 * 3.9 / 1000 = ~15g

So the only reading that seems correct out of the 4 is pointed up @3.9mg/digit.

Any ideas?

thanks

I figured out what is wrong, here is a C# program that describes the problem:

using System;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void your_math()
        {
            byte high = 0xC1;
            byte low = 0x80;

            var data = (Int16)(((high << 8) | low) >> 4);

            System.Console.WriteLine("your result: " + (double)data);
        }

        static void correct_math()
        {
            byte high = 0xC1;
            byte low = 0x80;

            var data = (Int16)((high << 8) | low) >> 4;

            System.Console.WriteLine("correct result: " + (double)data);
        }

        static void Main(string[] args)
        {
            your_math();
            correct_math();
            while (true) ;
        }
    }
}

The problem is that by shifting to the right before turning your number from an unsigned number to a signed one, you are basically putting a bunch of 0’s on the left side of the number, which messes up the 2’s complement form. By the way, I made this program by following my suggestion to you of simplifying your program by inserting literal values for the bytes you expect to receive.

- Ryan

Hi Ryan,

Thanks very much for your help. I’m sorry for not taking your advice regarding checking the math. Probably should have explored that first, given that it was not producing the expected negative values. Doh.

Anyhow thanks again.