2023-10-22 04:00 PM
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!
Solved! Go to Solution.
2023-10-24 10:59 AM - edited 2023-10-24 11:05 AM
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!
2023-10-23 02:47 AM
Hi @KWine ,
Where have you found the example on github? Can you share the link?
Thanks
2023-10-23 09:07 AM
https://github.com/STMicroelectronics/STMems_Finite_State_Machine
and specifically for the 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.
2023-10-23 03:41 PM - edited 2023-10-23 03:52 PM
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.
2023-10-24 10:59 AM - edited 2023-10-24 11:05 AM
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!