cancel
Showing results for 
Search instead for 
Did you mean: 

LIS3DH sensor is giving me huge offset when just resting on a table.

PNamg.1295
Associate

While flashing the LIS3DH I accidentally commented out a block of code causing read/writes of unintended registers. Below is the code which caused it.

static void read_accel(void){

uint16_t MOSI = 0xA9;

uint32_t MISO;

int8_t dataRec;

uint8_t i = 0;

float accel_data[3];

while(1){

USART1->CMD = USART_CMD_RXBLOCKDIS; // disable block

USART1->CMD = USART_CMD_CLEARRX;

while (!(USART1->STATUS & USART_STATUS_TXBL));

USART1->TXDOUBLE = (uint32_t)MOSI;

while(!(USART1->STATUS & USART_STATUS_TXC));

MISO = USART1->RXDOUBLE;

printf("%x\n", MISO);

dataRec = MISO>>8;

USART1->CMD = USART_CMD_RXBLOCKEN;

accel_data[i] = ((float)dataRec*4/256);

// if(MOSI==0xAD)

// break;

MOSI=MOSI+2;

i=i+1;

}

float noGravAndDirAccelData = sqrt(accel_data[0]*accel_data[0]*9.8*9.8 + accel_data[1]*accel_data[1]*9.8*9.8+accel_data[2]*accel_data[2]*9.8*9.8);

noGravAndDirAccelData = (noGravAndDirAccelData - 9.8)/9.8;

printf("accel data x, y, z: %fg, %fg, %fg\n", accel_data[0], accel_data[1], accel_data[2]);

printf("accel data magnitude w/o gravity: %fg\n\n", noGravAndDirAccelData);

}

In my while loop which cycles through OUT registers, I had these lines:

// if(MOSI==0xAD)

// break;

commented out. When included in the code, I also use read_accel() to read the OUT X, Y, and Z registers. However, when resting the accelerometer on a table, I am getting these as my numbers:

89ff //bits received from x, y, and z in hex.

80ff

7fff

accel data x, y, z: -1.859375g, -2.000000g, 1.984375g

accel data magnitude w/o gravity: 2.375651g

Below is what I use to set ctrl registers 1 and 4 to get Low power mode and set the max and min to +2 and -2 g.

static void initG(USART_TypeDef *usart){

uint32_t reg1;

uint32_t reg4;

reg1 = 0x3f20;

reg4=0x0023;

usart->CMD = USART_CMD_RXBLOCKDIS; // disable block

 usart->CMD = USART_CMD_CLEARRX;

 while (!(usart->STATUS & USART_STATUS_TXBL));

 usart->TXDOUBLE = reg1;

 printf("SENDING: %x\n", usart->TXDATA);

 while (!(usart->STATUS & USART_STATUS_TXC));

 usart->CMD = USART_CMD_RXBLOCKEN; // enable block

  usart->CMD = USART_CMD_RXBLOCKDIS; // disable block

 usart->CMD = USART_CMD_CLEARRX;

 while (!(usart->STATUS & USART_STATUS_TXBL));

 usart->TXDOUBLE = reg4;

 printf("SENDING: %x\n", usart->TXDATA);

 while (!(usart->STATUS & USART_STATUS_TXC));

 usart->CMD = USART_CMD_RXBLOCKEN; // enable block

}

Is there any way to recalibrate the offset, anything I can try outside of buying a new chip?

Also, after powercycling, ctrl register 0 reads as 0x80 instead of 0x10 which should be the default as stated by the datasheet.

1 REPLY 1
Eleon BORLINI
ST Employee

Hi @PNamg.1295​ , how many mg (or LSB with the proper full scale) are you measuring when your device is flat on your table (and on which axes)? Is your device soldered flat? If the issue is a related to the sensor, for LIS3DH you have two possibilities to remove this offset (if this is a constant offset like an high zero-G level and not and rms high noise):

  • Mode 1: Offset can be eliminated by enabling the built-in high-pass filter (in CTRL_REG2 (21h));
  • Mode 2: Offset can be stored at SW level and subtracted same way.

Unfortunately for LIS3DH there is no embedded register, which is however present on more recent devices like the LIS3DSH (REGs 10h to 12h).

Regards