cancel
Showing results for 
Search instead for 
Did you mean: 

Getting unexpected I2C Slave Address from a LSM9DS1 sensor and reading the wrong data from the register I just wrote in

ETerr.1
Associate

I am using a STM32F030R8 nucleo board and a LSM9DS1 sensor. I'm just starting out learning about this stuff and I am having troubles reading from the sensor. Here are all the details about the problem I am having.

I initialized the peripherals and the I2C protocol using the STM32CUBEMX automatic code generation so that should'nt be a part of the problem. I use Keil IDE. For starters, the datasheet didn't make it clear what the Slave Adress of the Accel+Gyro and Magnetometer but gave a list of possible values (pg. 30 of the datasheet). For the Accel+Gyro, I found online that it must be either 0x6A or 0x6B, depending on the SA0 and it's connection. The problem is that I do not have a SA0 connector on the board of the sensor. So i decided to find out the address by going through all the possibilities and expecting an acnowledge signal.

uint8_t buf[12];
	HAL_StatusTypeDef result;
 	uint8_t i;
	
	//Trying to find out the address of the i2c slave (accelerometer and gyro hopefully)
 	for (i=1; i<128; i++)
 	{
 	  /*
 	   * the HAL wants a left aligned i2c address
 	   * &hi2c1 is the handle
 	   * (uint16_t)(i<<1) is the i2c address left aligned
 	   * retries 2
 	   * timeout 2
 	   */
 	  result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i<<1), 2, 2);
 	  if (result != HAL_OK) // HAL_ERROR or HAL_BUSY or HAL_TIMEOUT
 	  {
 		  strcpy((char*) buf, ".");
			HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY); // No ACK received at that address
 	  }
 	  if (result == HAL_OK)
 	  {
 		  strcpy((char*) buf, "(");
			HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
			sprintf((char*)buf, "%X h", i);
			HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY); // Received an ACK at that address
			strcpy((char*) buf, ")");
			HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
 	  }
 	}

Suprisingly, only the address 0x69 gives back the ackowledge as you can see in the picture below. Every adress but this is ignored.0693W000001qf6cQAA.png

So I decided to use this address even though I don't understand how it could possibly be different than what everybody else is saying on the internet. Next was writing to the control register CTRL_REG6_XL so I can turn on the accel and try reading some data (as explained in the datasheet pg. 19). I wrote 0xC0 to the register to activate the accel (pg. 51 - pg. 52).

uint8_t SlaveAdress = 0x69 << 1; // Accel and Gyro I2C Slave Adress that sent acknowledge
	uint8_t CTRL_REG6_XL = 0x20; // Control Register to turn on the Accel
	uint8_t sent_data = 0xC0; // Setting ODDR_XL2 = 1, ODDR_XL1 = 1, ODDR_XL0 = 0, rest is 0, accel turned on
	uint8_t received_data;
	
	buf[0] = CTRL_REG6_XL;
	buf[1] = sent_data;
	//Writing to the control register to activate the accel
	result = HAL_I2C_Master_Transmit(&hi2c1, SlaveAdress, buf, 2, HAL_MAX_DELAY);
	if ( result != HAL_OK ) {
		strcpy((char*)buf, "There was an error while writing!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	} else {
		strcpy((char*)buf, "Data sent succesfully!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	}

Everything went ok as i received no failed messages.0693W000001qf6hQAA.png

To test if i really did send the data i decided to read back from the same register and see the result.

buf[0] = CTRL_REG6_XL;
	buf[1] = 0;
	//Reading from the control register that we just wrote to
	result = HAL_I2C_Master_Transmit(&hi2c1, SlaveAdress, buf, 1, HAL_MAX_DELAY);
	if ( result != HAL_OK ) {
		strcpy((char*)buf, "There was an error while writing!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	} else {
		strcpy((char*)buf, "Data sent succesfully!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	}
	result = HAL_I2C_Master_Receive(&hi2c1, SlaveAdress, &received_data, 1, HAL_MAX_DELAY);
	if ( result != HAL_OK ) {
		strcpy((char*)buf, "There was an error while reading!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	} else {
		strcpy((char*)buf, "Data read succesfully!\r\n");
		HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	}
	
	strcpy((char*)buf, "CTRL_REG6_XL: ");
  HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);
	sprintf((char*)buf, "%X h", received_data);
	HAL_UART_Transmit(&huart2, buf, strlen((char*) buf), HAL_MAX_DELAY);

The whole process went without error but the data read is wrong. Instead of 0xC0 i get 0x00. I am stuck regarding what do to next.0693W000001qf6rQAA.png

Any insight is greatly appreciated.

LSM9DS1 Datasheet - https://www.st.com/resource/en/datasheet/lsm9ds1.pdf

2 REPLIES 2
Eleon BORLINI
ST Employee

Hi @ETerr.1​ , I'm double-checking the LSM9DS1 C drivers on Github from ST, which are working:

/** @defgroup LSM9DS1_Infos
  * @{
  *
  */
 
/** I2C Device Address 8 bit format  if SA0=0 -> 0xD5 if SA0=1 -> 0xD7 **/
#define LSM9DS1_IMU_I2C_ADD_L      0xD5U
#define LSM9DS1_IMU_I2C_ADD_H      0xD7U
 
/** I2C Device Address 8 bit format  if SA0=0 -> 0x3D if SA0=1 -> 0x39 **/
#define LSM9DS1_MAG_I2C_ADD_L      0x3DU
#define LSM9DS1_MAG_I2C_ADD_H      0x39U
 
/** Device Identification (Who am I) **/
#define LSM9DS1_IMU_ID             0x68U
 
/** Device Identification (Who am I) **/
#define LSM9DS1_MAG_ID             0x3DU
 
/**

If you were using the 7-bit I2C address format, you should get 6A or 6B as you found online, since the MSB is dropped... did you check the endianness of your processor? Btw, you believe you are correctly communicating I2C, but you are stuck when reading back the CTRL_REG6_XL register because you just wrote C0h and you get 00h, right?

Can you check the WHO_AM_I (0Fh) read-only register? This is to check if the communication is ok and if the bits are in the right order. You should get as default value 01101000 (68h).

Regards

well no sense the endianness compatibility statement, it is an STM32F0...