cancel
Showing results for 
Search instead for 
Did you mean: 

LIS3DSH x y z axis is incorrect

PChar.11
Associate

I have tried to work with LIS3DSH sensor using SPI protocol. I applied procedures on STM32L0 Discovery kit LoRa. But it didn't work. 

My problem is The LIS3DSH x-y-z-axis output value is invalid and the value is not changed. No matter which direction I rotate the device but I check ID of LIS3DSH is correct ( 0011 1111) 

Component 

- STM32L0 Discovery kit LoRa

- LIS3DSH (https://www.amazon.com/LIS3DSH-High-Resolution-Three-axis-Accelerometer-Triaxial/dp/B07QS5D9K9/ref=sr_1_4?dchild=1&keywords=LIS3DSH&qid=1615701212&sr=8-4)

----

init SPI2

void HW_SPI2_Init(void)
{
 
	  /*##-1- Configure the SPI2  peripheral */
	  /* Set the SPI parameters */
 
	  hspi2.Instance = SPI2;
 
	  hspi2.Init.BaudRatePrescaler = SpiFrequency(10000000);
	  hspi2.Init.Direction      = SPI_DIRECTION_2LINES;
	  hspi2.Init.Mode           = SPI_MODE_MASTER;
	  hspi2.Init.CLKPolarity    = SPI_POLARITY_LOW; // CPOL = 0
	  hspi2.Init.CLKPhase       = SPI_PHASE_2EDGE;  // CPHA = 1
	 // hspi2.Init.CLKPhase       = SPI_PHASE_1EDGE;  // CPHA = 0
	  hspi2.Init.DataSize       = SPI_DATASIZE_8BIT;
	 // hspi2.Init.DataSize       = SPI_DATASIZE_16BIT;
	  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	  hspi2.Init.FirstBit       = SPI_FIRSTBIT_MSB;
	  hspi2.Init.NSS            = SPI_NSS_SOFT;
	  hspi2.Init.TIMode         = SPI_TIMODE_DISABLE;
	  hspi2.Init.CRCPolynomial = 10;
 
	  SPI2_CLK_ENABLE();  // Enable clock for SPI 2
 
	  if (HAL_SPI_Init(&hspi2) != HAL_OK)
	  {
	    /* Initialization Error */
	    Error_Handler();
	  }
 
	  /*##-2- Configure the SPI GPIOs */
	  HW_SPI2_IoInit();
}

Set PIN

void HW_SPI2_IoInit(void)
{
  GPIO_InitTypeDef initStruct = {0};
 
 
  initStruct.Mode = GPIO_MODE_AF_PP;
  initStruct.Pull = GPIO_PULLUP  ;
  initStruct.Speed = GPIO_SPEED_FAST;
  initStruct.Alternate = SPI2_AF;
 
  HW_GPIO_Init(LIS3DH_SCLK_PORT, LIS3DH_SCLK_PIN, &initStruct);
  HW_GPIO_Init(LIS3DH_MISO_PORT, LIS3DH_MISO_PIN, &initStruct);
  HW_GPIO_Init(LIS3DH_MOSI_PORT, LIS3DH_MOSI_PIN, &initStruct);
 
  initStruct.Mode = GPIO_MODE_OUTPUT_PP;
  initStruct.Pull = GPIO_NOPULL;
 
  HW_GPIO_Init(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, &initStruct);
 
  HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}

initialization LIS3DSH

void LIS3DSH_DH_initialization (void)
{
	 uint8_t au8LISConfig[2];
 
	#if defined(IC_LIS3DH)
 
	#elif defined(IC_LIS3DSH)
	 /********************************************
	  *  Config CTRL_REG4
	  ********************************************/
 
	 au8LISConfig[0] = LIS3Dx_CTRL_REG4_ADDR;
	 au8LISConfig[1] = 0x67;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_2byte_Write(au8LISConfig);
	 HW_SPI2_CS_OFF();
 
 
	 /********************************************
	  *  Config CTRL_REG3
	  ********************************************/
 
	 au8LISConfig[0] = LIS3Dx_CTRL_REG3_ADDR;
	 au8LISConfig[1] = 0xC8;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_2byte_Write(au8LISConfig);
	 HW_SPI2_CS_OFF();
 
 
	 /********************************************
	  *  Config OFFSET X
	  ********************************************/
 
	 au8LISConfig[0] = LIS3DSH_OFF_X_ADDR;
	 au8LISConfig[1] = 0x00;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_2byte_Write(au8LISConfig);
	 HW_SPI2_CS_OFF();
 
 
	 /********************************************
	  *  Config OFFSET Y
	  ********************************************/
 
	 au8LISConfig[0] = LIS3DSH_OFF_Y_ADDR;
	 au8LISConfig[1] = 0x00;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_2byte_Write(au8LISConfig);
	 HW_SPI2_CS_OFF();
 
 
	 /********************************************
	  *  Config OFFSET Z
	  ********************************************/
 
	 au8LISConfig[0] = LIS3DSH_OFF_Z_ADDR;
	 au8LISConfig[1] = 0x00;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_2byte_Write(au8LISConfig);
	 HW_SPI2_CS_OFF();
	#endif
}

CS ON or OFF

void HW_SPI2_CS_ON (void)
{
	 HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 0);
}
 
void HW_SPI2_CS_OFF (void)
{
	 HW_GPIO_Write(LIS3DH_NSS_PORT, LIS3DH_NSS_PIN, 1);
}

Read ID

uint8_t LIS3DSH_DH_CHECK_ID (void)
{
	uint8_t addr = LIS3Dx_WHO_AM_I_ADDR | LIS3Dx_READ;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_SPI_1byte_Write_and_Read(addr);
 
	 HW_SPI2_CS_OFF();
 
	 UsingTypeint_LIS3DSH_DH.ID = au8BufferRead_SPI2[0];
	 return UsingTypeint_LIS3DSH_DH.ID;
}

Read X axis ( only)

void LIS3DSH_DH_GET_XYZ (void)
{
	uint8_t addr = LIS3Dx_OUT_X_L_ADDR | LIS3Dx_READ ;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_SPI_1byte_Write_and_Read(addr);
	 HW_SPI2_CS_OFF();
 
	 addr = LIS3Dx_OUT_X_H_ADDR | LIS3Dx_READ ;
 
	 HW_SPI2_CS_ON();
	 HW_SPI2_SPI_1byte_Write_and_Read(addr);
	 HW_SPI2_CS_OFF();
}

HW_SPI2_1byte_Write_and_Read

bool HW_SPI2_SPI_1byte_Write_and_Read(uint8_t u8Address)
{
	if(HAL_SPI_Transmit(&hspi2,  (uint8_t *)&u8Address, 1, HAL_MAX_DELAY) == HAL_OK){
		if(HAL_SPI_Receive(&hspi2,  (uint8_t *)&au8BufferRead_SPI2[0], 1, HAL_MAX_DELAY) == HAL_OK){
			return true;
		}
	}
 
	return false;
}

LIS3DSH and STM

X L axis (adress 0x28)

0693W000008wqGOQAY.png 

0693W000008wqGTQAY.pngX H axis (adress 0x29)

0693W000008wqGdQAI.png 

LIS3DSH Header

//List of Defines
/* ****************************************************
 *
 * L - I - S - 3 - D - S - H
 *
 * registers addresses
 **************************************************** */
 
#define LIS3Dx_READ						 	0x80
#define LIS3Dx_WRITE						0x00
 
#define LIS3Dx_WHO_AM_I_ADDR                0x0F
#define LIS3Dx_ID							0x3F
 
/* LIS3DSH ONLY [0x0C] */
#define LIS3DSH_CTRL_REG0_ADDR              0x0C	 // Read
 
/* LIS3DSH ONLY [0x0D-0x0E] */
#define LIS3DSH_INFO1_ADDR              	0x0D	 // Read | Default 0010 0001
#define LIS3DSH_INFO2_ADDR              	0x0E     // Read | Default 0000 0000
 
/* LIS3DSH ONLY [0x10-0x12] */
#define LIS3DSH_OFF_X_ADDR              	0x10     // Read/Write | Default 0000 0000
#define LIS3DSH_OFF_Y_ADDR              	0x11     // Read/Write | Default 0000 0000
#define LIS3DSH_OFF_Z_ADDR              	0x12     // Read/Write | Default 0000 0000
 
/* LIS3DSH ONLY [0x10-0x12] */
#define LIS3DSH_CS_X_ADDR              		0x13     // Read/Write | Default 0000 0000
#define LIS3DSH_CS_Y_ADDR              		0x14     // Read/Write | Default 0000 0000
#define LIS3DSH_CS_Z_ADDR              		0x15     // Read/Write | Default 0000 0000
 
/* LIS3DSH ONLY [0x16-0x17] */
#define LIS3DSH_LC_L_ADDR              		0x16     // Read/Write | Default 0000 0001
#define LIS3DSH_LC_L_ADDR              		0x17     // Read/Write | Default 0000 0000
 
/* LIS3DSH ONLY [0x18] */
#define LIS3DSH_STAT_ADDR              		0x18     // Read
 
/* LIS3DSH ONLY [0x19-0x1A] */
#define LIS3DSH_PEAK1_ADDR              	0x19     // Read
#define LIS3DSH_PEAK1_ADDR              	0x1A     // Read
 
/* LIS3DSH ONLY [0x1B-0x1E] */
#define LIS3DSH_VFC_1_ADDR              	0x1B     // Read/Write
#define LIS3DSH_VFC_2_ADDR              	0x1C     // Read/Write
#define LIS3DSH_VFC_3_ADDR              	0x1D     // Read/Write
#define LIS3DSH_VFC_4_ADDR              	0x1E     // Read/Write
 
/* LIS3DSH ONLY [0x1F] */
#define LIS3DSH_THRS3_ADDR              	0x1F     // Read/Write
 
#define LIS3Dx_CTRL_REG1_ADDR               0x21	 // Read/Write | Default 0000 0111
#define LIS3Dx_CTRL_REG2_ADDR               0x22	 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG3_ADDR               0x23	 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG4_ADDR               0x20	 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG5_ADDR               0x24	 // Read/Write | Default 0000 0000
#define LIS3Dx_CTRL_REG6_ADDR               0x25	 // Read/Write | Default 0001 0000
 
#define LIS3Dx_STATUS_ADDR                  0x27
 
#define LIS3Dx_OUT_X_L_ADDR                 0x28	 // Read/Write | Default 0000 0000
#define LIS3Dx_OUT_X_H_ADDR                 0x29
#define LIS3Dx_OUT_Y_L_ADDR                 0x2A
#define LIS3Dx_OUT_Y_H_ADDR                 0x2B
#define LIS3Dx_OUT_Z_L_ADDR                 0x2C
#define LIS3Dx_OUT_Z_H_ADDR                 0x2D
 
#define LIS3Dx_FIFO_CTRL_REG_ADDR           0x2E	 // Read/Write | Default 0000 0000
#define LIS3Dx_FIFO_SRC_REG_ADDR            0x2F	 // Read

Global

typedef struct
{
	uint8_t dataRate;
	uint8_t fullScale;
	uint8_t antiAliasingBW;
	uint8_t enableAxes;
	bool interruptEnable;
}LIS3DSH_InitTypeDef;
 
//2. Accelerometer raw data
typedef struct
{
	int16_t x;
	int16_t y;
	int16_t z;
}LIS3DSH_DataRaw;
 
//3. Accelerometer mg data (scaled data)
typedef struct
{
	float x;
	float y;
	float z;
}LIS3DSH_DataScaled;
 
extern LIS3DSH_InitTypeDef myAccConfigDef;

2 REPLIES 2
Eleon BORLINI
ST Employee

Hi @PChar.1​ ,

If you are able to correctly read the WHO_AM_I value, but the data out are all 00h (or FFh? or fixed to a certain value), there might be an issue related to the configuration of the device, especially in the initialization procedure.

You correctly used the LIS3DSH initialization in the application note AN3393, so I would suggest you to check if these registers have been correctly written by reading them after their setting.

You can also check the C drivers on Github repository, for example the lis3dsh_read_data_polling.c. In particular, here the ADD_INC bit of register CTRL_REG6 (25h) and the BDU bit of CTRL_REG4 (20h) registers (so, 6Fh instead of 67h) have ben set.

  /* Set bdu and if_inc recommended for driver usage */
  lis3dsh_init_set(&dev_ctx, LIS3DSH_DRV_RDY);
  /* Set Output Data Rate */
  lis3dsh_mode_get(&dev_ctx, &md);
  md.fs =  LIS3DSH_4g;
  md.odr = LIS3DSH_25Hz;
  lis3dsh_mode_set(&dev_ctx, &md);

By the way, are you performing multiple or single SPI reading?

-Eleon

bmak
Senior

Hi!

Polarity of SPI clock is actually HIGH. Set CPOL = 1 in your SPI configuration, then it should work :).

Also word size is 16 bit, look at datasheet figure 7.

Correct config for SPI is:

CPOL = 1

CPHA = 1

Word size = 16 bit