cancel
Showing results for 
Search instead for 
Did you mean: 

LSM9DS1 not responding to 4-wire SPI.

Aaronium
Associate III

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.

7 REPLIES 7
KnarfB
Principal III

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.

Eleon BORLINI
ST Employee

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

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);

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

Thank you!

The CTRL_REG1 and CTRL_REG6 are configured now to set both the output data rates to 476 Hz, etc.. In trying to write to said registers, the system does not seem to be receiving the "write." As in I can read from the WHO_AM_I register, meaning that it is receiving the data, but when reading from the CTRL registers after writing to them, they still output 0, as well as CTRL_REG8, which should have a default value of 0b00000100. Unfortunately I do not have a scope I can use, but when looping-back the SPI send to receive, I do know that the messages are being sent. It is my understanding that by default 3-Wire SPI is disabled, and in writing 0b00000100 to CTRL_REG9_G, that I2C is disabled.

const uint8_t WHO_AM_I_AG = 0x0F+0x80;
 
const uint8_t CTRL_REG1_Gw = 0x10;
const uint8_t CTRL_REG6_XLw = 0x20;
const uint8_t CTRL_REG8w = 0x22;
const uint8_t CTRL_REG9w = 0x23;
 
const uint8_t CTRL_REG1_Gr = 0x10+0x80;
const uint8_t CTRL_REG6_XLr = 0x20+0x80;
const uint8_t CTRL_REG8r = 0x22+0x80;
const uint8_t CTRL_REG9r = 0x23+0x80;
 
{
// Writing CS Pin Low
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 0);
HAL_Delay(50);
 
// Reading from WHO_AM_I
HAL_SPI_Transmit(&hspi1, (uint8_t *) &WHO_AM_I_AG, 1, 50);
HAL_SPI_Receive(&hspi1, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("WHO_AM_I: %x\n", storeVal);
 
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 1);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 0);
HAL_Delay(10);
 
// Reading from registers
HAL_SPI_Transmit(&hspi1, (uint8_t *) &CTRL_REG1_Gr, 1, 50);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &CTRL_REG6_XLr, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG1_G: %x\n", storeVal);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &CTRL_REG9r, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG6_XL: %x\n", storeVal);
HAL_SPI_Receive(&hspi1, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG9: %x\n", storeVal);
 
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 1);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 0);
HAL_Delay(10);
 
// Attempting to write to registers
uint8_t hold;
hold = 0b101010101;
HAL_SPI_Transmit(&hspi1, (uint8_t *) &CTRL_REG1_Gw, 1, 50);
HAL_SPI_Transmit(&hspi1, (uint8_t *) &hold, 1, 50);
hold = 0b10110000;
HAL_SPI_Transmit(&hspi1, (uint8_t *) &CTRL_REG6_XLw, 1, 50);
HAL_SPI_Transmit(&hspi1, (uint8_t *) &hold, 1, 50);
hold = 0b00000100;
HAL_SPI_Transmit(&hspi1, (uint8_t *) &CTRL_REG9w, 1, 50);
HAL_SPI_Transmit(&hspi1, (uint8_t *) &hold, 1, 50);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 1);
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 0);
HAL_Delay(10);
 
// Again reading registers.
HAL_SPI_Transmit(&hspi1, (uint8_t *) &CTRL_REG1_Gr, 1, 50);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &CTRL_REG6_XLr, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG1_G: %x\n", storeVal);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &CTRL_REG8r, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG6_XL: %x\n", storeVal);
HAL_SPI_TransmitReceive(&hspi1, (uint8_t *) &CTRL_REG9r, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG9: %x\n", storeVal);
HAL_SPI_Receive(&hspi1, (uint8_t *) &receive, 1, 50);
storeVal = receive;
printf("CTRL_REG8: %x\n", storeVal);
 
// Writing CS Pin High
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, 15, 1);
HAL_Delay(10);
}

Hi @Aaronium​ ,

sorry for the delay in my answer.

You say that you are able to write in the registers in SPI 4-wires but when you read back the registers it seems they are always 00h, right? the Are the Vdd/VddIO always connected? Are you correctly implementing the 8-bit SPI Mode 3 as described above? (I'm afraid an oscilloscope is mandatory...)

-Eleon