Skip to main content
Visitor II
February 16, 2021
Question

LSM9DS1 not responding to 4-wire SPI.

  • February 16, 2021
  • 2 replies
  • 1655 views

Hello,

I have been trying for some time to get this to work. It is my understanding from the datasheet that the default values for the IC are suitable to where the acceleration and angular rates can be measured by shifting in the appropriate register values with the CS-A/G pin set to LOW and the CS-M pin set to HIGH, and that when the address is shifted in (MOSI), the byte corresponding to that address will be shifted out (MISO) during the next SPI cycle. I get the feeling that I am doing this entirely wrong. I looked at the library and example, which seemed mainly for I2C, and was hugely confused.

The code for this section of the program is below:

		HAL_GPIO_WritePin(GPIOB, 15, 0);
		HAL_Delay(10);
		HAL_SPI_Transmit(&hspi1, (uint8_t *) &ORIENT_CFG_G, 1, 50);
 
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_L_G, (uint8_t *) &receive, 1, 50);
		OrientationByte = receive;
 
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_H_G, (uint8_t *) &receive, 1, 50);
		hold = receive;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_L_G, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		pitch = hold;
 
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_H_G, (uint8_t *) &receive, 1, 50);
		hold = receive;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_L_G, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		roll = hold;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_H_G, (uint8_t *) &receive, 1, 50);
		hold = receive;
 
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_L_XL, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		yaw = hold;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_H_XL, (uint8_t *) &receive, 1, 50);
		hold = receive;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_L_XL, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		yaw = hold;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_H_XL, (uint8_t *) &receive, 1, 50);
		hold = receive;
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		x_Accel = hold;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_L_XL, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		y_Accel = hold;
		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_H_XL, (uint8_t *) &receive, 1, 50);
		hold = receive;
 
		HAL_SPI_Receive(&hspi1, (uint8_t *) &receive, 1, 50);
		hold = (hold << 8) + receive;
		if (hold > 32767)
			hold = -((~hold)+1);
		z_Accel = hold;
 
		HAL_Delay(10);
		HAL_GPIO_WritePin(GPIOB, 15, 1);
		HAL_Delay(50);

The register values I am using are below:

const uint8_t ORIENT_CFG_G = 0x13;
 
const uint8_t OUT_X_L_G = 0x18; 
const uint8_t OUT_X_H_G = 0x19;
const uint8_t OUT_Y_L_G = 0x1A;
const uint8_t OUT_Y_H_G = 0x1B;
const uint8_t OUT_Z_L_G = 0x1C; 
const uint8_t OUT_Z_H_G = 0x1D;
 
const uint8_t OUT_X_L_XL = 0x28;
const uint8_t OUT_X_H_XL = 0x29;
const uint8_t OUT_Y_L_XL = 0x2A;
const uint8_t OUT_Y_H_XL = 0x2B;
const uint8_t OUT_Z_L_XL = 0x2C;
const uint8_t OUT_Z_H_XL = 0x2D;

Thank y'all for your time.

    This topic has been closed for replies.

    2 replies

    Super User
    February 16, 2021
    AaroniumAuthor
    Visitor II
    February 16, 2021

    Thank you KnarfB, but that is the example code I mentioned in the post. I would really appreciate it if you could tell me what is wrong with my existing code.

    ST Employee
    February 16, 2021

    Hi @Aaronium​ ,

    about the 4-wire SPI issue, are you failing the whole SPI communication or are you able -for example- to correctly read the WHO_AM_I (0x0F) register, but you are wrongly acquiring / decoding the data?

    In the first case, you have to check if you are using the SPI Mode 3 (i.e. CPOL=1, CPHA=1), as stated in the datasheet, p. 31:

    0693W000008GFYCQA4.pngYou should check this configuration from your master SPI side.

    I suggest you to use a scope for signal integrity double-check.

    In the second case, please check if from the C example on Github for LSM9DS1 that @KnarfB​ suggested to you, in particular the lsm9ds1_reg.c:

    float_t lsm9ds1_from_fs2g_to_mg(int16_t lsb)
    {
     return ((float_t)lsb * 0.061f);
    }

    Let me know if I correctly understood the issue.

    -Eleon

    AaroniumAuthor
    Visitor II
    February 17, 2021

    Thank you so much.

    I tested the WHO_AM_I register by sending a "big-endian" SPI message 0x8F (0b10001111). The returned value is consistently 104 (0b01101000), so I am assuming that is working. If I spam the WHO_AM_I request, the following messages are 0, I do not know if that is supposed to happen or not. When sending the addresses with the read bit enabled for the accelerometer/gyroscope data, the returned data is either 255 or 0. Given my understanding of the default register values in the datasheet, the system should be "ready to go" at startup, but I can almost guarantee that I am mistaken in some way about that. Below is the snippet I am using to try to get data now, but it is not returning anything other than 0s or 255s at the moment. All of the register values used below are correct per the datasheet, and have 0x80 added to enable read. I know this is a big question, but what am I doing wrong?

    		HAL_GPIO_WritePin(GPIOB, 15, 0);
    		HAL_Delay(10);
    		HAL_SPI_Transmit(&hspi1, (uint8_t *) &OUT_X_L_G, 1, 50);
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_H_G, (uint8_t *) &receive, 1, 50);
    		tempByte[0] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_L_G, (uint8_t *) &receive, 1, 50);
    		tempByte[1] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_H_G, (uint8_t *) &receive, 1, 50);
    		tempByte[2] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_L_G, (uint8_t *) &receive, 1, 50);
    		tempByte[3] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_H_G, (uint8_t *) &receive, 1, 50);
    		tempByte[4] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_L_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[5] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_X_H_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[6] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_L_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[7] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Y_H_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[8] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_L_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[9] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &OUT_Z_H_XL, (uint8_t *) &receive, 1, 50);
    		tempByte[10] = receive;
    		HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &ORIENT_CFG_G, (uint8_t *) &receive, 1, 50);
    		tempByte[11] = receive;
    		HAL_SPI_Receive(&hspi1, (uint8_t *) &receive, 1, 50);
    		tempByte[12] = receive;
     
    		HAL_Delay(10);
    		HAL_GPIO_WritePin(GPIOB, 15, 1);
    		HAL_Delay(50);

    ST Employee
    February 19, 2021

    Hi @Aaronium​ ,

    well, the device is not "ready to go" just after startup in the sense that you have to set the configuration registers to set the device in a "receptive" mode (ODR setting, FS, Mode...). For a basic configuration you can refer to Github examples you might already know.

    As additional question from my side, are you correctly configuring all the 4 wires of the SPI (especially the CS line)? Could you share the screen of a scope, for completeness?

    -Eleon