G measurement – uncorrect values

Forums Technical Support for BerryIMU G measurement – uncorrect values

This topic contains 2 replies, has 2 voices, and was last updated by  Mark Williams 1 month ago.

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #5872

    Sten-Helge
    Participant

    Hi there,
    According to the datasheet and your tutorials – when the accelerometer is horizontal and at rest, the value for Z should hover around 1 G.
    When using a sensitive level of ±8g, the raw value for Z should hover around 4,475.
    My readings from the below code snippet gives;

    ….
    Loop 20 Xraw = -588 Yraw = -34 Zraw = 5304
    Loop 20 Xraw = -520 Yraw = -67 Zraw = 5374
    Loop 20 Xraw = -599 Yraw = -84 Zraw = 5460
    Loop 20 Xraw = -549 Yraw = -70 Zraw = 5441
    Loop 20 Xraw = -549 Yraw = -92 Zraw = 5341
    Loop 20 Xraw = -517 Yraw = -91 Zraw = 5406
    Loop 20 Xraw = -527 Yraw = -70 Zraw = 5281
    Loop 20 Xraw = -538 Yraw = -73 Zraw = 5382
    ….

    which gives – converted to G;

    ….
    Loop 20 X = -0.139 G Y = -0.029 G Z = 1.184 G
    Loop 20 X = -0.128 G Y = -0.020 G Z = 1.197 G
    Loop 20 X = -0.136 G Y = -0.027 G Z = 1.228 G
    Loop 20 X = -0.137 G Y = -0.028 G Z = 1.225 G
    Loop 20 X = -0.118 G Y = -0.025 G Z = 1.190 G
    Loop 20 X = -0.126 G Y = -0.024 G Z = 1.214 G
    Loop 20 X = -0.137 G Y = -0.026 G Z = 1.210 G
    Loop 20 X = -0.128 G Y = -0.024 G Z = 1.216 G
    ….

    See below the used code for this test;

    
    int mymillis()
    {
    	struct timeval tv;
    	gettimeofday(&tv, NULL);
    	return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
    }
    
    void  readBlock(uint8_t command, uint8_t size, uint8_t *data)
    {
        int result = i2c_smbus_read_i2c_block_data(file, command, size, data);
        if (result != size)
        {
            printf("Failed to read block from I2C.");
            exit(1);
        }
    }
    
    void selectDevice(int file, int addr)
    {
            if (ioctl(file, I2C_SLAVE, addr) < 0) {
    		 printf("Failed to select I2C device.");
            }
    }
    
    void writeAccReg(uint8_t reg, uint8_t value)
    {
        selectDevice(file,ACC_ADDRESS);
      int result = i2c_smbus_write_byte_data(file, reg, value);
        if (result == -1)
        {
            printf ("Failed to write byte to I2C Acc.");
            exit(1);
        }
    }
    
    void enableIMU()
    {
    
            char filename[20];
            sprintf(filename, "/dev/i2c-%d", 1);
            file = open(filename, O_RDWR);
            if (file<0) {
    			printf("Unable to open I2C bus!");
                    exit(1);
            }
    
            // Enable accelerometer.
            writeAccReg(CTRL_REG1_XM, 0b01100111); //  z,y,x axis enabled, continuos update,  100Hz data rate
    		//writeAccReg(CTRL_REG2_XM, 0b00100000); // +/- 16G full scale
    		writeAccReg(CTRL_REG2_XM, 0b00010000); // +/- 8G full scale
            //writeAccReg(CTRL_REG2_XM, 0b00000000); //+/- 2G full scale
    
    }
    
    void readACC(int  *a)
    {
            uint8_t block[6];
            selectDevice(file,ACC_ADDRESS);
            readBlock(0x80 | OUT_X_L_A, sizeof(block), block);
    
            *a = (int16_t)(block[0] | block[1] << 8);
            *(a+1) = (int16_t)(block[2] | block[3] << 8);
            *(a+2) = (int16_t)(block[4] | block[5] << 8);
    
    }
    
    int main(int argc, char *argv[])
    {
    	int  accRaw[3];
    
    	int startInt  = mymillis();
    	struct  timeval tvBegin;
    
        signal(SIGINT, INThandler);
    
    	enableIMU();
    
    	gettimeofday(&tvBegin, NULL);
    
    	while(1)
    	{
    	startInt = mymillis();
    
    	//read ACC and GYR data
    	readACC(accRaw);
    	
    	// +/- 2G full scale
    	//printf("X = %7.3f G\t" , ((accRaw[0] * 0.061)/1000));
    	//printf(" Y =   %7.3f G\t" , ((accRaw[1] * 0.061)/1000));
    	//printf(" Z =  %7.3f G\n" , ((accRaw[2] * 0.061)/1000));
    	
    	// +/- 8G full scale
    	printf("X = %7.3f G\t" , ((accRaw[0] * 0.224)/1000));
    	printf(" Y =   %7.3f G\t" , ((accRaw[1] * 0.224)/1000));
    	printf(" Z =  %7.3f G\n" , ((accRaw[2] * 0.224)/1000));	
    	
    	//printf("Xraw = %d \t" , accRaw[0]);
    	//printf(" Yraw =   %d \t" , accRaw[1]);
    	//printf(" Zraw =  %d \n" , accRaw[2]);			
    
    	//Loop time
            while(mymillis() - startInt < (DT*1000))
            {
                usleep(100);
                //printf(".");
            }
    
    	printf("Loop %d\t", mymillis()- startInt);
        }
    }
    

    May I kindly ask for your advice on how to proceed in order to get the proper values.

    Thanks

    • This topic was modified 1 month ago by  Sten-Helge.
    • This topic was modified 1 month ago by  Sten-Helge.
    • This topic was modified 1 month ago by  Sten-Helge.
    #5882

    Sten-Helge
    Participant

    According to the datasheet the settings for CTRL_REG2_XM register should be as follows for the different scales;

    ....
            // Enable accelerometer.
            writeAccReg(CTRL_REG1_XM, 0b01100111); //  z,y,x axis enabled, continuos update,  100Hz data rate
    		
            //writeAccReg(CTRL_REG2_XM, 0b00000000); //+/- 2G full scale
            //writeAccReg(CTRL_REG2_XM, 0b00001000); //+/- 4G full scale
            //writeAccReg(CTRL_REG2_XM, 0b00010000); // +/- 6G full scale
            //writeAccReg(CTRL_REG2_XM, 0b00011000); // +/- 8G full scale
            writeAccReg(CTRL_REG2_XM, 0b00100000); // +/- 16G full scale
    ....
    
    ....
    	//read ACC values
    	readACC(accRaw);
    	
    	// +/- 2G full scale
    	//printf("X = %7.2f G\t" , ((accRaw[0] * 0.061)/1000));
    	//printf(" Y =   %7.2f G\t" , ((accRaw[1] * 0.061)/1000));
    	//printf(" Z =  %7.2f G\n" , ((accRaw[2] * 0.061)/1000));
    	
    	// +/- 4G full scale
    	//printf("X = %7.2f G\t" , ((accRaw[0] * 0.122)/1000));
    	//printf(" Y =   %7.2f G\t" , ((accRaw[1] * 0.122)/1000));
    	//printf(" Z =  %7.2f G\n" , ((accRaw[2] * 0.122)/1000));
    	
    	// +/- 6G full scale
    	//printf("X = %7.2f G\t" , ((accRaw[0] * 0.183)/1000));
    	//printf(" Y =   %7.2f G\t" , ((accRaw[1] * 0.183)/1000));
    	//printf(" Z =  %7.2f G\n" , ((accRaw[2] * 0.183)/1000));	
    	
    	// +/- 8G full scale
    	//printf("X = %7.3f G\t" , ((accRaw[0] * 0.244)/1000));
    	//printf(" Y =   %7.3f G\t" , ((accRaw[1] * 0.244)/1000));
    	//printf(" Z =  %7.3f G\n" , ((accRaw[2] * 0.244)/1000));	
    	
    	// +/- 12G full scale
    	printf("X = %7.2f G\t" , ((accRaw[0] * 0.732)/1000));
    	printf(" Y =   %7.2f G\t" , ((accRaw[1] * 0.732)/1000));
    	printf(" Z =  %7.2f G\n" , ((accRaw[2] * 0.732)/1000));	
    	
    	//printf("Xraw = %d \t" , accRaw[0]);
    	//printf(" Yraw =   %d \t" , accRaw[1]);
    	//printf(" Zraw =  %d \n" , accRaw[2]);		
    ....
    

    Please advice if not correct.

    Thanks

    #5883

    Mark Williams
    Keymaster

    You are correct.. there is a typo in the code.

    This;
    writeACC(CTRL_REG2_XM, 0b00010000) #+/- 8G full scale
    should be
    writeACC(CTRL_REG2_XM, 0b00011000) #+/- 8G full scale

    I have updated the page.

    And your scales in CTRL_REG2_XM above are correct.

    Mark --OzzMaker.com --
    BerryIMU --
    PiScreen - 3.5" TFT for the Rasspberry Pi

Viewing 3 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.

Blip, blop, bloop…