0
\$\begingroup\$

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.

Found Address

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.

Sent Data

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.

Wrong Data

Any insight is greatly appreciated.

LSM9DS1 Datasheet - Datasheet

\$\endgroup\$
0
\$\begingroup\$

That is not the correct way to read I2C registers. According to the datasheet the write of registet address and read of register data must not be separate transactions like you now have separate transmit for register address and separate read of data. It may work for some other chips but it won't work for all chips. Just use I2C Mem Read and I2C Mem Write.

Because the IsDeviceReady does not complete the transaction in the correct way either, the chip may be left in an unknown state and it might give a false result with nearby address. The 0x69 should not be a valid default address. Just try to do a complete write or read with the correct protocol to see if it succeeds or not.

\$\endgroup\$
9
  • \$\begingroup\$ And what about the address 0x69 of the sensor? Everywhere else it says it should be 0x6A or 0x6B, even in the datasheet. Why do I only get ACK signal on that adress? \$\endgroup\$
    – edward_d
    Jun 14 '20 at 19:42
  • \$\begingroup\$ Sorry I forgot that part and was editing the answer. \$\endgroup\$
    – Justme
    Jun 14 '20 at 19:44
  • \$\begingroup\$ I tried HAL_I2C_Mem_Write(&hi2c1, SlaveAdress, CTRL_REG6_XL, I2C_MEMADD_SIZE_8BIT, buf, 1, HAL_MAX_DELAY), where i put the 0xC0 in buf[0] and neither of the SlaveAddress (0x6B<<1) or (0x6A<<1) result in HAL_OK but (0x69<<1) still does even though it makes no sense for the address to be 0x69. \$\endgroup\$
    – edward_d
    Jun 14 '20 at 20:42
  • \$\begingroup\$ What sensor board is it? Can you add a link? \$\endgroup\$
    – Justme
    Jun 14 '20 at 21:28
  • \$\begingroup\$ Of course, here it is: mikroe.com/9dof-click \$\endgroup\$
    – edward_d
    Jun 14 '20 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.