11 years, 8 months ago.

Problem with IMU3000

Hi,

Im trying to measure angular rate with IMU3000. In other time, Ive been done the same thing with Arduino + IMU3000. So I tried to port my Arduino code to mbed, but it doesnt work.

I refer to :http://mbed.org/users/murabito/notebook/3%E8%BB%B8%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AD-itg-3200/

#include "mbed.h"

I2C i2c(p9, p10);
Serial pc(USBTX, USBRX);

Ticker tick; //Timer
double interval = 10; //[ms]
    
const int adrIMU3000 = 0x68; //7-bit
const int adrIMU3000_R = 0xD1;//8-bit read
const int adrIMU3000_W = 0xD0;//8-bit write


void measure();

int main() {
    
    i2c.frequency(4000000); //set 400kHz
    
    pc.baud(115200);
    
    char PWR_M[2] = {0x3E, 0x80};
    i2c.write(adrIMU3000_W, PWR_M, 2);
    char SMPL[2] = {0x15, 0x00};
    i2c.write(adrIMU3000_W, SMPL, 2);
    char DLPF[2] = {0x16, 0x18};
    i2c.write(adrIMU3000_W, DLPF, 2);
    char INT_C[2] = {0x17, 0x05};
    i2c.write(adrIMU3000_W, INT_C, 2);
    char PWR_M2[2] = {0x3E, 0x00};
    i2c.write(adrIMU3000_W, PWR_M2, 2);
    
    tick.attach_us(&measure, interval);
    
    return 0;
}

void measure()
{
    char adrIMU3000_y[1];
    char readIMU3000[8];
    
    short int read_x_2byte = 0;
    short int read_y_2byte = 0;
    short int read_z_2byte = 0;
    
    adrIMU3000_y[0] = 0x1D; //register GYRO_XOUT_H
    
    i2c.write(adrIMU3000_W, adrIMU3000_y , 1);
    i2c.read(adrIMU3000_R, readIMU3000, 8);

    read_x_2byte = ((readIMU3000[0] << 8) + readIMU3000[1]);
    read_y_2byte = ((readIMU3000[2] << 8) + readIMU3000[3]);
    read_z_2byte = ((readIMU3000[4] << 8) + readIMU3000[5]);

    pc.printf("¥n");
    pc.printf("%d, %d, %d\n", read_x_2byte, read_y_2byte, read_z_2byte);
    
}


I tried I2CU and i2c device found in 0xD0 correctly.But output values are completely garbage.

Please Help me.

3 Answers

11 years, 8 months ago.

When you say the output is complete garbage, is it random, or the same everytime?

Some small notes: The i2c.write before using i2c.read it is generally a good idea to add ',true' at the end, to prevent it from sending a stop condition. Although I don't know if it is relevant for this IC. Also there is no reason to use different read and write addresses, the mbed library handles it for you.

Anyway what your problem probably is, is a small typo. Officially the mbeds i2c busses can only handle 100kHz (LPC1768s limitation for the I2C modules used by the mbed). Now 100kHz is really slow for ICs, and in practise I haven't had any issues going to 400kHz. 1MHz also seemed to work for me. However you made a little typo in your frequency set for i2c, so you set it at 4MHz. That might be kinda overdoing it, a factor 40 above the official limit ;)

In other words, just try 100kHz i2c frequency first.

(Btw since it does something I guess the return 0 doesnt stop the program, generally in such situations I add an infinite while loop with blinking LEDs, then you are sure the mbed runs).

Accepted Answer

Hi Erik.

I'm grateful for your commitment to solve this problem (I mean my silly TYPO.) I tried in 100kHz, it works perfectly! And also 400kHz.

Other advices that you gave me were also useful reference!

Thanks!

posted by Lysenko Mami 29 Oct 2012
11 years, 8 months ago.

I dont know the IMU device and have not checked how it should be operated, but I see several issues with your code:

You dont need to define different I2C addresses for Read and Write. Just use the baseaddress, the i2c.read or i2c.write will set the lsb to the correct value. This is just an easier solution, but should not be a problem with your code as such.

Current:

const int adrIMU3000_R = 0xD1;//8-bit read
const int adrIMU3000_W = 0xD0;//8-bit write

New:

const int adrIMU3000_B = 0xD0;//8-bit base address

i2c.write(adrIMU3000_B, adrIMU3000_y , 1);
i2c.read(adrIMU3000_B, readIMU3000, 8);

You set the i2c frequency to a wrong value (4 mbit/s instead of 400 kbit/s)

Current:

i2c.frequency(4 000 000); //set 400kHz

New:

i2c.frequency(400 000); //set 400kHz

You set ticker attach to 10 us. That is rather high. Your comment seems to indicate you are aiming for 10 ms. Make sure that ticker rate is feasible with the i2c bitrate at 400k (address+1byte+address+8bytes = 11 bytes, takes 220 us) and the calculations. It will definitely not work with a slow printf as part of the attached function.

double interval = 10; //[ms]

...

tick.attach_us(&measure, interval);  //Note: attach_us  

It is probably better not to exit your main as long as the ticker is still running.

Current:

return 0;

New:

while (true){};

Hi Wim. Thanks a lot! Shamefulness I couldnt notice the error that I confised MicroSecond with MiliSecond in my code before you pointed it out.

posted by Lysenko Mami 29 Oct 2012
11 years, 8 months ago.

Hi Erik, we seem to agree (again)... :)

Indeed, pretty close to the same time we posted it.

But I missed the interval being 10us :)

posted by Erik - 29 Oct 2012