10 years, 6 months ago.

Random values from gyro (L3G4200D)

hi am having a problem with my gyro, i am getting random values. from my understanding i have set it up correctly but still facing problems. i am using the code below:

Gyro Code

#include "mbed.h"


// L3G4200D I2C address
const int GYRO_ADDRESS = 0x68 << 1;
// L3G4200D register addresses
const int WHO_AM_I = 0x0f;
const int CTRL_REG1 = 0x20;
const int CTRL_REG2 = 0x21;
const int CTRL_REG4 = 0x23;
const int CTRL_REG5 = 0x24;
const int OUT_X_L = 0x28;
const int OUT_X_H = 0x29;
const int OUT_Y_L = 0x2a;
const int OUT_Y_H = 0x2b;
const int OUT_Z_L = 0x2c;
const int OUT_Z_H = 0x2d;

Serial pc(USBTX, USBRX);
I2C gyro(p28, p27); //sda, scl

char ctrl1_bits[2] = {0x20,0x0C}; //00001100
char ctrl2_bits[2] = {0x21,0x20}; //--100000
//char ctrl3_bits[2] = {0x22,};
//char ctrl4_bits[2] = {0x23,};
//char ctrl5_bits[2] = {0x24,};

int main() {
    gyro.frequency(400000);
     
    //testing for any errors in communication with the gyro
    char whoami_reg[1] = {WHO_AM_I};
    gyro.write(GYRO_ADDRESS, whoami_reg, 1, true);
    char whoami_data[1] = {0};
    gyro.read(GYRO_ADDRESS, whoami_data, 1, false);
    if (whoami_data[0] == 0xd3){
        pc.printf("Gyro (0x%x) functioning correctly\n\r",whoami_data[0]);    //id should be d3
    }
    else if (whoami_data[0] != 0xd3){
        pc.printf("Gyro Error (0x%x)\n\r",whoami_data[0]);    //id should be d3
    }
    
    //configuring CTRL_REG1
    gyro.write(GYRO_ADDRESS, ctrl1_bits, 2, false);
    
    //configuring CTRL_REG2, turn highpass filter on
    gyro.write(GYRO_ADDRESS, ctrl2_bits, 2, false);
    
    
    while(1){
        //reading gyro's z-axis register
        char outz_l_reg[1] = {OUT_Z_L};
        gyro.write(GYRO_ADDRESS, outz_l_reg, 1, true);
        char outz_l_data[1] = {0};
        gyro.read(GYRO_ADDRESS, outz_l_data, 1, false);  
        
        char outz_h_reg[1] = {OUT_Z_H};
        gyro.write(GYRO_ADDRESS, outz_h_reg, 1, true);
        char outz_h_data[1] = {0};
        gyro.read(GYRO_ADDRESS, outz_h_data, 1, false);  
        
        int OUT_Z = (((int) outz_h_data[0]) << 8 | outz_l_data[0]);
        pc.printf("Z-Axis: %d \n\r", OUT_Z);
        
        wait(1);
    }
}

i get the values below: Z-Axis: 65409 Z-Axis: 65402 Z-Axis: 65376 Z-Axis: 65381 Z-Axis: 65395 Z-Axis: 65371 Z-Axis: 65407 Z-Axis: 65381 Z-Axis: 65407 Z-Axis: 65419 Z-Axis: 65341 Z-Axis: 65387 Z-Axis: 65402 Z-Axis: 65384 Z-Axis: 65370 Z-Axis: 65352 Z-Axis: 65380 Z-Axis: 65364 Z-Axis: 65401 Z-Axis: 65408 Z-Axis: 65411 Z-Axis: 65406 Z-Axis: 65359 Z-Axis: 65378 Z-Axis: 65372 Z-Axis: 65371 Z-Axis: 65379 Z-Axis: 65356 Z-Axis: 65364 Z-Axis: 65337 Z-Axis: 65369 Z-Axis: 65368 Z-Axis: 65390 Z-Axis: 65362 Z-Axis: 65368 Z-Axis: 65380 Z-Axis: 65376 Z-Axis: 65390 Z-Axis: 65373 Z-Axis: 65419 Z-Axis: 65374 Z-Axis: 65378 Z-Axis: 65359 Z-Axis: 65380

1 Answer

10 years, 6 months ago.

That is not random data, it is a 16-bit unsigned integer max value -> If it was 16-bit signed it would be slightly negative, something you would expect when it is just lying around (they always have an offset, can be quite significant). So apparantly your conversion at line 62 is going wrong, I think because outz_h_data is a char, which by default is unsigned, when casting it to a signed integer it does not add the sign bits.

One option would be to make it a signed char, I think that would do the trick. Or if you define OUT_Z has int16_t (same as 'short'), it will be forced to set the sign correctly since you only look at it as 16-bit value, not as 32-bit value what you got currently.

hi thanks a lot for that .. that worked perfectly... i just have a lot of fluctuations in the raw data now, with a offset which are both expected.. but before i carry on programming for this gyro, i need to know if its possible to remove the gyro offset error and drifting error without the use of an accelerometer ?... if so how would i go about this. i have looked around and only really found how to remove these errors with the use of an accelerometer which was hoping to avoid.

code edited 1

#include "mbed.h"


// L3G4200D I2C address
const int GYRO_ADDRESS = 0x68 << 1;
// L3G4200D register addresses
const int WHO_AM_I = 0x0f;
const int CTRL_REG1 = 0x20;
const int CTRL_REG2 = 0x21;
const int CTRL_REG4 = 0x23;
const int CTRL_REG5 = 0x24;
const int OUT_X_L = 0x28;
const int OUT_X_H = 0x29;
const int OUT_Y_L = 0x2a;
const int OUT_Y_H = 0x2b;
const int OUT_Z_L = 0x2c;
const int OUT_Z_H = 0x2d;

Serial pc(USBTX, USBRX);
I2C gyro(p28, p27); //sda, scl

char ctrl1_bits[2] = {0x20,0x0C}; //00001100
char ctrl2_bits[2] = {0x21,0x20}; //--100000
//char ctrl3_bits[2] = {0x22,};
//char ctrl4_bits[2] = {0x23,};
//char ctrl5_bits[2] = {0x24,};


int main() {
    gyro.frequency(400000);
     
    //testing for any errors in communication with the gyro
    char whoami_reg[1] = {WHO_AM_I};
    gyro.write(GYRO_ADDRESS, whoami_reg, 1, true);
    char whoami_data[1] = {0};
    gyro.read(GYRO_ADDRESS, whoami_data, 1, false);
    if (whoami_data[0] == 0xd3){
        pc.printf("Gyro (0x%x) functioning correctly\n\r",whoami_data[0]);    //id should be d3
    }
    else if (whoami_data[0] != 0xd3){
        pc.printf("Gyro Error (0x%x)\n\r",whoami_data[0]);    //id should be d3
    }
    
    //configuring CTRL_REG1
    gyro.write(GYRO_ADDRESS, ctrl1_bits, 2, false);
    
    //configuring CTRL_REG2, turn highpass filter on
   // gyro.write(GYRO_ADDRESS, ctrl2_bits, 2, false);
    
    
    while(1){
        //reading gyro's z-axis register
        char outz_l_reg[1] = {OUT_Z_L};
        gyro.write(GYRO_ADDRESS, outz_l_reg, 1, true);
        char outz_l_data[1] = {0};
        gyro.read(GYRO_ADDRESS, outz_l_data, 1, false);  
        
        char outz_h_reg[1] = {OUT_Z_H};
        gyro.write(GYRO_ADDRESS, outz_h_reg, 1, true);
        char outz_h_data[1] = {0};
        gyro.read(GYRO_ADDRESS, outz_h_data, 1, false);  
        
        int16_t OUT_Z = (((int) outz_h_data[0]) << 8 | outz_l_data[0]);
        pc.printf("Z-Axis: %d \n\r", OUT_Z);
        
        wait_ms(10);
    }
}

Values i get now

Z-Axis: -173;
Z-Axis: -180;
Z-Axis: -193;
Z-Axis: -164;
Z-Axis: -163;
Z-Axis: -160;
Z-Axis: -167;
Z-Axis: -183;
Z-Axis: -146;
Z-Axis: -154;
Z-Axis: -147;
Z-Axis: -189;
Z-Axis: -174;
Z-Axis: -166;
Z-Axis: -171;
Z-Axis: -167;
Z-Axis: -201;
Z-Axis: -204;
Z-Axis: -187;
Z-Axis: -207;
Z-Axis: -146;
Z-Axis: -184;
Z-Axis: -209;
Z-Axis: -174;
Z-Axis: -169;
Z-Axis: -185;
Z-Axis: -192;
Z-Axis: -173;
Z-Axis: -209;
Z-Axis: -190;
Z-Axis: -212;
Z-Axis: -162;
Z-Axis: -145;
Z-Axis: -135;
Z-Axis: -191;
Z-Axis: -160;
Z-Axis: -168;
Z-Axis: -145;
Z-Axis: -161;
Z-Axis: -183;
Z-Axis: -176;
Z-Axis: -163;
Z-Axis: -165;
Z-Axis: -165;
Z-Axis: -184;
Z-Axis: -178;
Z-Axis: -168;
Z-Axis: -187;
Z-Axis: -177;
Z-Axis: -190;
Z-Axis: -189;
Z-Axis: -182;
Z-Axis: -199;
Z-Axis: -186;
Z-Axis: -141;
Z-Axis: -181;
Z-Axis: -176;
Z-Axis: -190;
Z-Axis: -160;
Z-Axis: -176;
Z-Axis: -174;
Z-Axis: -187;
Z-Axis: -166;
Z-Axis: -183;
Z-Axis: -179;
Z-Axis: -188;
Z-Axis: -147;
Z-Axis: -165;
Z-Axis: -180;
Z-Axis: -172;
posted by Mobeen Yasin 13 Feb 2015

Options I know of:

Accelerometer is the best option in general, not easiest to all write it correctly (or find good code which does it for you), but most robust solution.

Since that is out, there is the simple option of hardcoding it into your code: If you only write it for one specific gyroscoop, and hopefully it does not drift too much, you can just manually check the offset and compensate for it.

Or finally, when you know it is not moving average a couple of samples and use that as offset. Know you only need to figure out when it is not moving. Could be for example on startup, downside is that if it moves on startup it will be screwed up rest of your program.

Then it depends what you want to use the gyro for. If it is something where for significant amount of time it is not moving, you could try to detect this and then average these samples. This could for example be when the output over a longer period barely changes: In most setups it is very unlikely it rotates with a constant speed for longer period. If that does happen in your setup you cannot use this solution obviously.

posted by Erik - 13 Feb 2015