Has anybody managed to use this sensor board with arduino?

  • 3 Axis Magnetometer from Honeywell (HMC5883L)
  • 3 Axis Accelerometer from Kionix (KXTF9)
  • 3 Axis Gyroscope from InvenSense (IMU-3000)
  • All sensors interface via I2C Port

It seems that the Invensense's MotionApps is pretty hard to implement for another platform than Atmel UC3-A3 Xplained. Also the MotionApps does not support 9-dof filtering, so that is pretty useless at the moment.

So is it possible to read the sensor values with Arduino and filter the data? Has anybody used that Atmel's board instead of Spark fun's IMU fusion board?


Here is the example code how to read sensor values from Spark Fun's board: http://www.hobbytronics.co.uk/arduino-adxl345-imu3000 (IMU-3000)

And how to read the mag sensor: http://sfecdn.s3.amazonaws.com/datasheets/Sensors/Magneto/HMC5883.pde (HMC5883L, direct link!)

Also the KXTF9 was somewhere.. but I prefer to use it like in Spark Fun's example (through the IMU-3000).


Also I would like to use FreeIMU (or similiar) for filtering the results. All I want is a quaternion output of current attitude. So how to add ATAVRSBIN2 for arduino?

Views: 5097

Reply to This

Replies to This Discussion

If you look at the code for the IMU fusion board, it's pretty easy to understand how the accelerometer is handled. It should be pretty straight forward to change that code to support the Kionix accelerometer. Just change the initialization to match the one needed by that accelerometer then push everything into my FreeIMU library...

Thanks! I will give it a try with Arduino Nano V3.0.

The board seems to have 2v5 requlator and 2k2 iic pull-ups to it. Schema: http://atmel.com/dyn/resources/prod_documents/doc8369.pdf (page 4).

So do I need a level converter or can I easilly disable the internal pull-ups in arduino code? And how about other pins (RXD, TXD, SS). Sorry about silly question (actually I am physicist and working as HW designer, but Iv been playing mainly with rf / power electronics / analogue signals and got the iic specs from SW guys)... I dont know what happens in startup of arduino. In some cases the internal pull-ups are high at start/boot. Prolly that is not a problem because iic is open collector and the output impedance is pretty high from digital pins.

I took another look on atavrsbin2. The wiring is pretty simple. There is i2c and power test points (holes) on the board. Power test points are regulated 2v5 and gnd. So the wiring goes like this:

Arduino 5 V -> Logic level converter HV
Arduino ground -> Logic level converter GND
Arduino I2C to both TX0 (high level tx)
Converters both TX1's to atavrsbin I2C
Converters LV to atavrsbin2 power test pin (regulated 2,5 V) and gnd to gnd
Arduino 3V3 to atavrsbin2 power in pin (socket)

So only one pin is needed in the socket and the sockets can be then used for mounting like in sensors xplained.

I will take some pics when the logic level converter arrives and I have tested it. I bought also a I/O shield for nano V3.0, so the connection should be plug and pray.

Thanks again! It was pretty simple to solder that level converter directly to Inertial Two board. I will take a pic later. Here is the code for reading the sensors (gyro, acc, mag). The orientation should be corrected for FreeImu, but it seems to print some values out...

/* IMU Fusion Board ATAVRSBIN2 - Atmel Inertial Two
   Original code by www.hobbytronics.co.uk (Gyro & ACC) and SparkFun Electronics (Magnetometer)
   I2C address changed for Kionix KXTF9
   Only for demonstartion! Orientation as in original code and not correct for this board!

#define GYRO 0x68         // gyro I2C address
#define REG_GYRO_X 0x1D   // IMU-3000 Register address for GYRO_XOUT_H
#define ACCEL 0x0F        // Accel I2c Address
#define KXTF9_POWER_CTL 0x1B
#define magnetometer 0x1E //0011110b, I2C 7bit address of HMC5883

byte buffer[12];   // Array to store ADC values
int gyro_x;
int gyro_y;
int gyro_z;
int accel_x;
int accel_y;
int accel_z;
int mag_x;
int mag_y;
int mag_z;
int i;
#include <Wire.h>

void setup()
    // Set Gyro settings
    // Sample Rate 1kHz, Filter Bandwidth 42Hz, Gyro Range 500 d/s
    writeTo(GYRO, 0x16, 0x0B);       
    //set accel register data address
    writeTo(GYRO, 0x18, 0x06);     
    // set accel i2c slave address
    writeTo(GYRO, 0x14, ACCEL);     
    // Set passthrough mode to Accel so we can turn it on
    writeTo(GYRO, 0x3D, 0x08);     
    // set accel power control to 'measure'
    writeTo(ACCEL, KXTF9_POWER_CTL, 0x80);     
    //cancel pass through to accel, gyro will now read accel for us   
    writeTo(GYRO, 0x3D, 0x28);    
    Wire.beginTransmission(magnetometer); //open communication with HMC5883
    Wire.send(0x02); //select mode register
    Wire.send(0x00); //continuous measurement mode - is this ok for this app?


// Write a value to address register on device
void writeTo(int device, byte address, byte val) {
  Wire.beginTransmission(device); // start transmission to device
  Wire.send(address);             // send register address
  Wire.send(val);                 // send value to write
  Wire.endTransmission();         // end transmission

void loop()
    // Read the Gyro X, Y and Z and Accel X, Y and Z all through the gyro
    // First set the register start address for X on Gyro  
    Wire.send(REG_GYRO_X); //Register Address GYRO_XOUT_H

    // New read the 12 data bytes
    Wire.requestFrom(GYRO,12); // Read 12 bytes
    i = 0;
        buffer[i] = Wire.receive();
    Wire.send(0x03); //select register 3, X MSB register
    Wire.requestFrom(magnetometer, 6);
    mag_x = Wire.receive()8; //X msb
    mag_x |= Wire.receive(); //X lsb
    mag_z = Wire.receive()8; //Z msb
    mag_z |= Wire.receive(); //Z lsb
    mag_y = Wire.receive()8; //Y msb
    mag_y |= Wire.receive(); //Y lsb

    //Combine bytes into integers
    // Gyro format is MSB first
    gyro_x = buffer[0] 8 | buffer[1];
    gyro_y = buffer[2] 8 | buffer[3];
    gyro_z = buffer[4] 8 | buffer[5];
    // Accel is LSB first. Also because of orientation of chips
    // accel y output is in same orientation as gyro x
    // and accel x is gyro -y
    accel_y = buffer[7] 8 | buffer[6];
    accel_x = buffer[9] 8 | buffer[8];
    accel_z = buffer[11] 8 | buffer[10];

    // Print out what we have
    Serial.print("GY X: ");
    Serial.print(gyro_x);  // echo the number received to screen
    Serial.print("\t GY Y: ");
    Serial.print(gyro_y);  // echo the number received to screen
    Serial.print("\t GY Z: ");
    Serial.print(gyro_z);  // echo the number received to screen
    Serial.print("\t ACC X: ");
    Serial.print(accel_x);  // echo the number received to screen
    Serial.print("\t ACC Y: ");
    Serial.print(accel_y);  // echo the number received to screen
    Serial.print("\t ACC Z: ");
    Serial.print(accel_z);  // echo the number received to screen    
    Serial.print("\t MAG X: ");
    Serial.print(mag_x);  // echo the number received to screen
    Serial.print("\t MAG Y: ");
    Serial.print(mag_y);  // echo the number received to screen
    Serial.print("\t MAG Z: ");  
    Serial.print(mag_z);  // echo the number received to screen    
    Serial.println("");     // prints carriage return

Nice, keep us posted!

This is how I connected the converter board to Inertial Two.

Only 3V3 is connected to socket. GND and I2C goes through the converter board. I used the other RX hole for jumper wire so I took off the voltage divider resistor. I guess it is not needed to be ripped off (removed resistor was 10 k to gnd and pull-ups something like 2-3 k to 2V5).

Ps. Arduino Nano 3.0 does not have the same pinmap as that DFRduino shield. I2C goes in that board like this: SLC to pin labeled "2" in the shield and SDA to "3". More about the problem: http://appiphania.com/2011/07/23/update-minor-problem-with-the-rfro...


Thanks for the posting Markus.  I got mine today but haven't gotten the level converter (hmmm, shipped faster from Malaysia than Colorado...).  The only place where it seems you can get 2.5V is at the test point labeled PWR.  I was hoping to steal one of the pins on J2 but they all seem to be connected somewhere even if the schematic doesn't show any connections.  I guess I can use J1 for that or at worst case put another 2.5V regulator on the shield.  The idea is to create a shield that will hold the IMU more securely and do the level conversions as well as a few other functions.  

How to import the values to FreeIMU? I quess I am doing it wrong :)

Is there any basic info about the orientation of the sensors? And how about the values?

For example I have the IMU3000 at 500 deg/s and it is 16 bits.. I guess the output should be divided by approx 3755 (500 deg/s so with 16 bit signed the sensor value is from -32767 to +32767 and 500 deg/s = 8,72638 rad/s so 1 LSB = 2,6631611 * 10^-4 rad/s  -> 1/LSB = 3 754,93)

When trying to convert the quaternion to angles the result just rotates around. I tried to use lpf with acc sensor without success. So how is the orientation defined? Could that be the problem or is it just me?

Hi, I am playing with your code.  Thanks for posting.   it looks like the forum SW dropped a bunch of left shift operators (I can't even post them, they just go away).  Pretty obvious what to do though.

Also, I'm using arduino 1.0 and the wire lib forced a number of changes:

  • receive changed to read
  • send changed to write
  • passing a constant to write needed to be typed.  I used (byte), that appears to be correct. 
Have to say - these lib changes are kind of annoying.

There might be also a better way to read the sensors. That was just a quick test for proper registers.I think at least the accel axises should be changed.

Somehow I managed to get the DCM to work, but not properly. Heavy drifting and one axis does not work on full scale when converting to euler. I will try some filtering and clean the code before sharing it. I took only the DCM part of FreeIMU for it.

Ps. What is the easiest way to visualize sensor values or quaternion output?

Thanks for the quick reply.  It seems like pretty straightforward code.  I just got my level shifter from SFE today so haven't had much time with it so far.

Yeah, I noticed your comment about the acc being wrong on the atavrsbin2. 

By the way, I seem to not get any values from the HPF registers of the KXTF9 - all zeros.  I tried changing the filter bits (reg 0x21) but nothing seems to work. I couldn't find any errata on the kionix site.  Filtering isn't that hard but I'd still like to play with it.  I found some one else that posted about the same problem about a month ago but no response.

For visualization I've been using Processing with another accelerometer - derived from a 3d cube example I found on the web.  Use the acc to control the position of the cube.  It's easy enough to plug the this program's data stream into it.  I was thinking of doing something similar for the gyro output.  Mag output would control a sphere - not very compelling.  Not sure when I'll get to that, though.  I'll give you what I've got once I get it together.

I've been looking at the data stream from the kionix accelerometer and it seems really noisy.  It could be the way I hooked up the ATAVRSBIN2 (60 cm ribbon cable to solderless breadboard to arduino) but I suspect that's not the problem.  I have it weighted down on a solid desk and it shows a lot of noise.  I haven't done a rigorous experiment but it looks like around 6-7 LSBs of noise.  Given that it is a 12 bit acc, that seems kind of high to me.  other accs I've played with haven't been nearly this noisy even with a breadboard environment.  I checked the 'SBIN2 VCC with my scope and it looked pretty solid.

The IMU 3000 output shows about 3-4 LSBs of noise (on a 16 bit result).  Significantly solid.   I can only conclude that the Kionix acc isn't that good.

Reply to Discussion


© 2018   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service