Skip to main content
Visitor II
October 22, 2023
Solved

LSM6DSV FSM example with baro (LPS22XX) as external sensor?

  • October 22, 2023
  • 3 replies
  • 1638 views

I have examined the FSM example folder on github and, while there is an example for an external magnetometer, I haven't found any examples for an external barometer. Is there such an example? And if so, where can I find it?

I believe I can create my own, but it is always easier to follow a previous working example. Thanks!

    This topic has been closed for replies.
    Best answer by KWine

    Just an FYI, I got this to work. First I configured the baro registers on Emb Adv Features page 2 with the hPa/LSB sensitivity and an average of the power-on pressure as a reference:

     // set baro sensitivity and offset for FSM operations
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW, 0x40); // Enable page write
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL, 0x21); // Select page 2 (bit 0 must always be 1)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_ADDR, 0x00); // Select EXT_FORMAT register
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x04); // select 3-byte format for barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // set lower byte of baro sensitivity (1/4096 = 0x0C00 in HFP)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x0C); // set higher byte for baro sensitivity
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x000000FF)); // set XL byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x0000FF00) >> 8); // set L byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x00FF0000) >> 16); // set H byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL, 0x01); // Select page 0 (bit 0 must always be 1)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW, 0x00); // Disable page write

    Then I adapted the ST motion detect FSM program to detect a 0.1 hPa pressue drop corresponding to a ~1 meter rise in altitude (so lift detect):

     // lift detect (threshold crossing) using barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x51); // write to CONFIG_A (one threshold, one mask, one short timer)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to CONFIG_B
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10); // write to SIZE (18 byte program)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to SETTINGS
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to RESET POINTER
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to PROGRAM POINTER
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x9A); // write to THRESH1 LSB
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x01); // write to THRESH1 MSB (0x019A is 410 which means 0.1 mBar for barometer)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x40); // write to MASKA (-x axis) x-axis is pressure for barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to TMASKA
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to TC
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10); // write to TIMER3 (16 samples at 30 Hz = 0.53 seconds)
     
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x23); // write to SINMUX Set input multiplexer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x02); // select external sensor
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x53); // write to GNTH1 | TI3
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x99); // write to OUTC
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x50); // write to GNTH1 | NOP
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to STOP

    I get a "lift detect" interrupt whenever the pressure drops by ~0.1 hPa, i.e., whenever I lift the sensor over my head.

    Pretty cool!

    3 replies

    Technical Moderator
    October 23, 2023

    Hi @KWine ,

    Where have you found the example on github? Can you share the link?

    Thanks

    KWineAuthor
    Visitor II
    October 23, 2023

    https://github.com/STMicroelectronics/STMems_Finite_State_Machine

    and specifically for the LSM6DSV,

    https://github.com/STMicroelectronics/STMems_Finite_State_Machine/tree/master/application_examples/lsm6dsv

    Very useful! But neither in the LSM6DSV nor any other (i.e., LSM6DSO) folder do I see an example for using external baro data. This would be a useful addition! Thanks.

    KWineAuthor
    Visitor II
    October 23, 2023

    A corollary question. I averaged ten baro samples at 1 Hz on start up to get:

    15:17:43.812 -> reference Pressure = 973.6434 mBar
    15:17:43.812 -> standard deviation = 0.0115 mBar
    15:17:43.812 -> HF reference Pressure = 0x639B
    15:17:43.812 -> FF reference Pressure = 973.5000 mBar

    It looks like the half-precision result is only good to 0.5 mBar, but the difference in pressure I see when I raise the baro three feet off the table (a typical gesture motion) is about 0.1 mBar such that including baro data in the FIFO for FSM using Mode 2 seems rather hopeless.  

     

    Nevermind, I see that only the sensitivity is to be entered in HFP format while the baro data is kept at full precision.

    KWineAuthorAnswer
    Visitor II
    October 24, 2023

    Just an FYI, I got this to work. First I configured the baro registers on Emb Adv Features page 2 with the hPa/LSB sensitivity and an average of the power-on pressure as a reference:

     // set baro sensitivity and offset for FSM operations
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW, 0x40); // Enable page write
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL, 0x21); // Select page 2 (bit 0 must always be 1)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_ADDR, 0x00); // Select EXT_FORMAT register
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x04); // select 3-byte format for barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // set lower byte of baro sensitivity (1/4096 = 0x0C00 in HFP)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x0C); // set higher byte for baro sensitivity
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x000000FF)); // set XL byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x0000FF00) >> 8); // set L byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, (refPressure & 0x00FF0000) >> 16); // set H byte for baro offset
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_SEL, 0x01); // Select page 0 (bit 0 must always be 1)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_RW, 0x00); // Disable page write

    Then I adapted the ST motion detect FSM program to detect a 0.1 hPa pressue drop corresponding to a ~1 meter rise in altitude (so lift detect):

     // lift detect (threshold crossing) using barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x51); // write to CONFIG_A (one threshold, one mask, one short timer)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to CONFIG_B
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10); // write to SIZE (18 byte program)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to SETTINGS
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to RESET POINTER
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to PROGRAM POINTER
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x9A); // write to THRESH1 LSB
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x01); // write to THRESH1 MSB (0x019A is 410 which means 0.1 mBar for barometer)
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x40); // write to MASKA (-x axis) x-axis is pressure for barometer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to TMASKA
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to TC
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x10); // write to TIMER3 (16 samples at 30 Hz = 0.53 seconds)
     
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x23); // write to SINMUX Set input multiplexer
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x02); // select external sensor
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x53); // write to GNTH1 | TI3
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x99); // write to OUTC
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x50); // write to GNTH1 | NOP
     _i2c_bus->writeByte(LSM6DSV_ADDRESS, LSM6DSV_PAGE_VALUE, 0x00); // write to STOP

    I get a "lift detect" interrupt whenever the pressure drops by ~0.1 hPa, i.e., whenever I lift the sensor over my head.

    Pretty cool!